1 #ifndef SRC_NODE_BOB_H_ 2 #define SRC_NODE_BOB_H_ 3 4 #include <functional> 5 6 namespace node { 7 namespace bob { 8 9 constexpr size_t kMaxCountHint = 16; 10 11 // Negative status codes indicate error conditions. 12 enum Status : int { 13 // Indicates that an attempt was made to pull after end. 14 STATUS_EOS = -1, 15 16 // Indicates the end of the stream. No additional 17 // data will be available and the consumer should stop 18 // pulling. 19 STATUS_END = 0, 20 21 // Indicates that there is additional data available 22 // and the consumer may continue to pull. 23 STATUS_CONTINUE = 1, 24 25 // Indicates that there is no additional data available 26 // but the stream has not ended. The consumer should not 27 // continue to pull but may resume pulling later when 28 // data is available. 29 STATUS_BLOCK = 2, 30 31 // Indicates that there is no additional data available 32 // but the stream has not ended and the source will call 33 // next again later when data is available. STATUS_WAIT 34 // must not be used with the OPTIONS_SYNC option. 35 STATUS_WAIT = 3, 36 }; 37 38 enum Options : int { 39 OPTIONS_NONE = 0, 40 41 // Indicates that the consumer is requesting the end 42 // of the stream. 43 OPTIONS_END = 1, 44 45 // Indicates that the consumer requires the source to 46 // invoke Next synchronously. If the source is 47 // unable to provide data immediately but the 48 // stream has not yet ended, it should call Next 49 // using STATUS_BLOCK. When not set, the source 50 // may call Next asynchronously. 51 OPTIONS_SYNC = 2 52 }; 53 54 // There are Sources and there are Consumers. 55 // 56 // Consumers get data by calling Source::Pull, 57 // optionally passing along a status and allocated 58 // buffer space for the source to fill, and a Next 59 // function the Source will call when data is 60 // available. 61 // 62 // The source calls Next to deliver the data. It can 63 // choose to either use the allocated buffer space 64 // provided by the consumer or it can allocate its own 65 // buffers and push those instead. If it allocates 66 // its own, it can send a Done function that the 67 // Sink will call when it is done consuming the data. 68 using Done = std::function<void(size_t)>; 69 template <typename T> 70 using Next = std::function<void(int, const T*, size_t count, Done done)>; 71 72 template <typename T> 73 class Source { 74 public: 75 virtual int Pull( 76 Next<T> next, 77 int options, 78 T* data, 79 size_t count, 80 size_t max_count_hint = kMaxCountHint) = 0; 81 }; 82 83 84 template <typename T> 85 class SourceImpl : public Source<T> { 86 public: 87 int Pull( 88 Next<T> next, 89 int options, 90 T* data, 91 size_t count, 92 size_t max_count_hint = kMaxCountHint) override; 93 is_eos()94 bool is_eos() const { return eos_; } 95 96 protected: 97 virtual int DoPull( 98 Next<T> next, 99 int options, 100 T* data, 101 size_t count, 102 size_t max_count_hint) = 0; 103 104 private: 105 bool eos_ = false; 106 }; 107 108 } // namespace bob 109 } // namespace node 110 111 #endif // SRC_NODE_BOB_H_ 112