IRequest.h 7.41 KB
Newer Older
Paweł Wegner's avatar
Paweł Wegner committed
1 2 3 4 5 6 7 8 9
/*****************************************************************************
 * IRequest : IRequest interface
 *
 *****************************************************************************
 * Copyright (C) 2016-2016 VideoLAN
 *
 * Authors: Paweł Wegner <pawel.wegner95@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
Paweł Wegner's avatar
Paweł Wegner committed
10
 * modify it under the terms of the GNU Lesser General Public License
Paweł Wegner's avatar
Paweł Wegner committed
11 12 13 14 15 16
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Paweł Wegner's avatar
Paweł Wegner committed
17
 * GNU Lesser General Public License for more details.
Paweł Wegner's avatar
Paweł Wegner committed
18
 *
Paweł Wegner's avatar
Paweł Wegner committed
19
 * You should have received a copy of the GNU Lesser General Public License
Paweł Wegner's avatar
Paweł Wegner committed
20 21 22 23 24 25 26
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef IREQUEST_H
#define IREQUEST_H

27
#include <functional>
Paweł Wegner's avatar
Paweł Wegner committed
28 29 30 31 32 33 34
#include <memory>
#include <vector>

#include "IItem.h"

namespace cloudstorage {

35
struct Error;
36
struct PageData;
37

38 39
template <class Left, class Right>
class Either;
40 41 42

template <class T>
using EitherError = Either<Error, T>;
43

44 45 46 47 48 49
struct GeneralData {
  std::string username_;
  uint64_t space_total_;
  uint64_t space_used_;
};

50
struct PageData {
51
  IItem::List items_;
52 53 54
  std::string next_token_;  // empty if no next page
};

55 56 57 58 59
struct Token {
  std::string token_;
  std::string access_token_;
};

60 61 62 63 64 65 66 67 68 69
struct Range {
  static constexpr uint64_t Begin = 0;
  static constexpr uint64_t Full = -1;

  uint64_t start_;
  uint64_t size_;
};

const Range FullRange = {Range::Begin, Range::Full};

70 71 72 73
/**
 * Class representing pending request. When there is no reference to the
 * request, it's immediately cancelled.
 */
74
class IGenericRequest {
Paweł Wegner's avatar
Paweł Wegner committed
75
 public:
76
  virtual ~IGenericRequest() = default;
Paweł Wegner's avatar
Paweł Wegner committed
77

78 79 80
  /**
   * Blocks until request finishes.
   */
Paweł Wegner's avatar
Paweł Wegner committed
81
  virtual void finish() = 0;
82 83 84 85 86

  /**
   * Cancels request; may involve curl request cancellation which may last very
   * long if curl was compiled without asynchronous name resolver(c-ares).
   */
Paweł Wegner's avatar
Paweł Wegner committed
87
  virtual void cancel() = 0;
88 89 90 91 92
};

template <class ReturnValue>
class IRequest : public IGenericRequest {
 public:
93
  using Pointer = std::unique_ptr<IRequest>;
94 95 96 97 98

  /**
   * Retrieves the result, blocks if it wasn't computed just yet.
   * @return result
   */
Paweł Wegner's avatar
Paweł Wegner committed
99 100 101
  virtual ReturnValue result() = 0;
};

102 103
template <class... Arguments>
class IGenericCallback {
Paweł Wegner's avatar
Paweł Wegner committed
104
 public:
105 106 107
  using Pointer = std::shared_ptr<IGenericCallback>;

  virtual ~IGenericCallback() = default;
Paweł Wegner's avatar
Paweł Wegner committed
108

109 110 111 112 113 114 115
  virtual void done(Arguments... args) = 0;
};

class IListDirectoryCallback
    : public IGenericCallback<EitherError<IItem::List>> {
 public:
  using Pointer = std::shared_ptr<IListDirectoryCallback>;
Paweł Wegner's avatar
Paweł Wegner committed
116

117 118 119 120 121
  /**
   * Called when directory's child was fetched.
   *
   * @param item fetched item
   */
Paweł Wegner's avatar
Paweł Wegner committed
122 123 124
  virtual void receivedItem(IItem::Pointer item) = 0;
};

125
class IDownloadFileCallback : public IGenericCallback<EitherError<void>> {
Paweł Wegner's avatar
Paweł Wegner committed
126
 public:
127
  using Pointer = std::shared_ptr<IDownloadFileCallback>;
Paweł Wegner's avatar
Paweł Wegner committed
128

129 130 131 132 133 134
  /**
   * Called when received a part of file.
   *
   * @param data buffer
   * @param length length of buffer
   */
Paweł Wegner's avatar
Paweł Wegner committed
135
  virtual void receivedData(const char* data, uint32_t length) = 0;
136 137 138 139 140 141 142

  /**
   * Called when progress has changed.
   *
   * @param total count of bytes to download
   * @param now count of bytes downloaded
   */
143
  virtual void progress(uint64_t total, uint64_t now) = 0;
Paweł Wegner's avatar
Paweł Wegner committed
144 145
};

146
class IUploadFileCallback : public IGenericCallback<EitherError<IItem>> {
Paweł Wegner's avatar
Paweł Wegner committed
147
 public:
148
  using Pointer = std::shared_ptr<IUploadFileCallback>;
Paweł Wegner's avatar
Paweł Wegner committed
149

150 151 152 153
  /**
   * Called when upload starts, can be also called when retransmission is
   * required due to network issues.
   */
Paweł Wegner's avatar
Paweł Wegner committed
154
  virtual void reset() = 0;
155 156 157 158 159 160 161 162

  /**
   * Called when the file data should be uploaded.
   *
   * @param data buffer to put data to
   * @param maxlength max count of bytes which can be put to the buffer
   * @return count of bytes put to the buffer
   */
Paweł Wegner's avatar
Paweł Wegner committed
163
  virtual uint32_t putData(char* data, uint32_t maxlength) = 0;
164 165 166 167

  /**
   * @return size of currently uploaded file
   */
Paweł Wegner's avatar
Paweł Wegner committed
168
  virtual uint64_t size() = 0;
169 170 171 172 173 174 175

  /**
   * Called when upload progress changed.
   *
   * @param total count of bytes to upload
   * @param now count of bytes already uploaded
   */
176
  virtual void progress(uint64_t total, uint64_t now) = 0;
Paweł Wegner's avatar
Paweł Wegner committed
177 178
};

179 180 181 182 183
struct Error {
  int code_;
  std::string description_;
};

184 185 186
template <class Left, class Right>
class Either {
 public:
Paweł Wegner's avatar
Paweł Wegner committed
187
  Either() {}
188 189
  Either(const Left& left) : left_(std::make_shared<Left>(left)) {}
  Either(const Right& right) : right_(std::make_shared<Right>(right)) {}
190 191
  Either(std::shared_ptr<Left> left) : left_(left) {}
  Either(std::shared_ptr<Right> right) : right_(right) {}
192 193 194 195 196 197 198 199 200

  std::shared_ptr<Left> left() const { return left_; }
  std::shared_ptr<Right> right() const { return right_; }

 private:
  std::shared_ptr<Left> left_;
  std::shared_ptr<Right> right_;
};

201 202 203
template <class Left>
class Either<Left, void> {
 public:
Paweł Wegner's avatar
Paweł Wegner committed
204
  Either() {}
205 206 207 208 209 210 211 212 213 214
  Either(std::nullptr_t) {}
  Either(const Left& left) : left_(std::make_shared<Left>(left)) {}
  Either(std::shared_ptr<Left> left) : left_(left) {}

  std::shared_ptr<Left> left() const { return left_; }

 private:
  std::shared_ptr<Left> left_;
};

215 216 217 218 219 220 221 222 223 224 225 226 227 228
template <class... Arguments>
class GenericCallback {
 public:
  GenericCallback() {}

  GenericCallback(const GenericCallback& d) : functor_(d.functor_) {}

  template <class Function>
  GenericCallback(const Function& callback)
      : functor_(std::make_shared<Functor>(callback)) {}

  GenericCallback(typename IGenericCallback<Arguments...>::Pointer functor)
      : functor_(functor) {}

229 230
  GenericCallback(std::nullptr_t) {}

231
  operator bool() const { return static_cast<bool>(functor_); }
232 233 234

  void operator()(Arguments... d) const { functor_->done(d...); }

235 236 237 238 239 240
  template <class Callback, class... CallbackArguments>
  static typename IGenericCallback<Arguments...>::Pointer make(
      CallbackArguments&&... args) {
    return std::make_shared<Callback>(std::forward<CallbackArguments>(args)...);
  }

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
 private:
  class Functor : public IGenericCallback<Arguments...> {
   public:
    Functor(const std::function<void(Arguments...)> callback)
        : callback_(callback) {}

    void done(Arguments... args) override { callback_(args...); }

   private:
    std::function<void(Arguments...)> callback_;
  };

  typename IGenericCallback<Arguments...>::Pointer functor_;
};

using ExchangeCodeCallback = GenericCallback<EitherError<Token>>;
using GetItemUrlCallback = GenericCallback<EitherError<std::string>>;
using GetItemCallback = GenericCallback<EitherError<IItem>>;
using GetItemDataCallback = GenericCallback<EitherError<IItem>>;
using DeleteItemCallback = GenericCallback<EitherError<void>>;
using CreateDirectoryCallback = GenericCallback<EitherError<IItem>>;
using MoveItemCallback = GenericCallback<EitherError<IItem>>;
using RenameItemCallback = GenericCallback<EitherError<IItem>>;
using ListDirectoryPageCallback = GenericCallback<EitherError<PageData>>;
using ListDirectoryCallback = GenericCallback<EitherError<IItem::List>>;
using DownloadFileCallback = GenericCallback<EitherError<void>>;
using UploadFileCallback = GenericCallback<EitherError<IItem>>;
using GetThumbnailCallback = GenericCallback<EitherError<void>>;
using GeneralDataCallback = GenericCallback<EitherError<GeneralData>>;
Paweł Wegner's avatar
Paweł Wegner committed
270 271 272 273

}  // namespace cloudstorage

#endif  // IREQUEST_H