4 ** A high performance, streaming, resumable decoder for the binary protobuf
7 ** This interface works the same regardless of what decoder backend is being
8 ** used. A client of this class does not need to know whether decoding is using
9 ** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default,
10 ** it will always use the fastest available decoder. However, you can call
11 ** set_allow_jit(false) to disable any JIT decoder that might be available.
12 ** This is primarily useful for testing purposes.
15 #ifndef UPB_DECODER_H_
16 #define UPB_DECODER_H_
25 class DecoderMethodPtr;
26 class DecoderMethodOptions;
31 /* The maximum number of bytes we are required to buffer internally between
32 * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte
33 * varint, less one because we are buffering an incomplete value.
35 * Should only be used by unit tests. */
36 #define UPB_DECODER_MAX_RESIDUAL_BYTES 14
38 /* upb_pbdecodermethod ********************************************************/
40 struct upb_pbdecodermethod;
41 typedef struct upb_pbdecodermethod upb_pbdecodermethod;
47 const upb_handlers *upb_pbdecodermethod_desthandlers(
48 const upb_pbdecodermethod *m);
49 const upb_byteshandler *upb_pbdecodermethod_inputhandler(
50 const upb_pbdecodermethod *m);
51 bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
56 /* Represents the code to parse a protobuf according to a destination
58 class upb::pb::DecoderMethodPtr {
60 DecoderMethodPtr() : ptr_(nullptr) {}
61 DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {}
63 const upb_pbdecodermethod* ptr() { return ptr_; }
65 /* The destination handlers that are statically bound to this method.
66 * This method is only capable of outputting to a sink that uses these
68 const Handlers *dest_handlers() const {
69 return upb_pbdecodermethod_desthandlers(ptr_);
72 /* The input handlers for this decoder method. */
73 const BytesHandler* input_handler() const {
74 return upb_pbdecodermethod_inputhandler(ptr_);
77 /* Whether this method is native. */
78 bool is_native() const {
79 return upb_pbdecodermethod_isnative(ptr_);
83 const upb_pbdecodermethod* ptr_;
88 /* upb_pbdecoder **************************************************************/
90 /* Preallocation hint: decoder won't allocate more bytes than this when first
91 * constructed. This hint may be an overestimate for some build configurations.
92 * But if the decoder library is upgraded without recompiling the application,
93 * it may be an underestimate. */
94 #define UPB_PB_DECODER_SIZE 4416
97 typedef struct upb_pbdecoder upb_pbdecoder;
103 upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena,
104 const upb_pbdecodermethod *method,
105 upb_sink output, upb_status *status);
106 const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
107 upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d);
108 uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
109 size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
110 bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
111 void upb_pbdecoder_reset(upb_pbdecoder *d);
116 /* A Decoder receives binary protobuf data on its input sink and pushes the
117 * decoded data to its output sink. */
118 class upb::pb::DecoderPtr {
120 DecoderPtr() : ptr_(nullptr) {}
121 DecoderPtr(upb_pbdecoder* ptr) : ptr_(ptr) {}
123 upb_pbdecoder* ptr() { return ptr_; }
125 /* Constructs a decoder instance for the given method, which must outlive this
126 * decoder. Any errors during parsing will be set on the given status, which
127 * must also outlive this decoder.
129 * The sink must match the given method. */
130 static DecoderPtr Create(Arena *arena, DecoderMethodPtr method,
131 upb::Sink output, Status *status) {
132 return DecoderPtr(upb_pbdecoder_create(arena->ptr(), method.ptr(),
133 output.sink(), status->ptr()));
136 /* Returns the DecoderMethod this decoder is parsing from. */
137 const DecoderMethodPtr method() const {
138 return DecoderMethodPtr(upb_pbdecoder_method(ptr_));
141 /* The sink on which this decoder receives input. */
142 BytesSink input() { return BytesSink(upb_pbdecoder_input(ptr())); }
144 /* Returns number of bytes successfully parsed.
146 * This can be useful for determining the stream position where an error
149 * This value may not be up-to-date when called from inside a parsing
151 uint64_t BytesParsed() { return upb_pbdecoder_bytesparsed(ptr()); }
153 /* Gets/sets the parsing nexting limit. If the total number of nested
154 * submessages and repeated fields hits this limit, parsing will fail. This
155 * is a resource limit that controls the amount of memory used by the parsing
158 * Setting the limit will fail if the parser is currently suspended at a depth
159 * greater than this, or if memory allocation of the stack fails. */
160 size_t max_nesting() { return upb_pbdecoder_maxnesting(ptr()); }
161 bool set_max_nesting(size_t max) { return upb_pbdecoder_maxnesting(ptr()); }
163 void Reset() { upb_pbdecoder_reset(ptr()); }
165 static const size_t kSize = UPB_PB_DECODER_SIZE;
171 #endif /* __cplusplus */
173 /* upb_pbcodecache ************************************************************/
175 /* Lazily builds and caches decoder methods that will push data to the given
176 * handlers. The destination handlercache must outlive this object. */
178 struct upb_pbcodecache;
179 typedef struct upb_pbcodecache upb_pbcodecache;
185 upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest);
186 void upb_pbcodecache_free(upb_pbcodecache *c);
187 bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
188 void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
189 void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy);
190 const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
191 const upb_msgdef *md);
196 /* A class for caching protobuf processing code, whether bytecode for the
197 * interpreted decoder or machine code for the JIT.
199 * This class is not thread-safe. */
200 class upb::pb::CodeCache {
202 CodeCache(upb::HandlerCache *dest)
203 : ptr_(upb_pbcodecache_new(dest->ptr()), upb_pbcodecache_free) {}
204 CodeCache(CodeCache&&) = default;
205 CodeCache& operator=(CodeCache&&) = default;
207 upb_pbcodecache* ptr() { return ptr_.get(); }
208 const upb_pbcodecache* ptr() const { return ptr_.get(); }
210 /* Whether the cache is allowed to generate machine code. Defaults to true.
211 * There is no real reason to turn it off except for testing or if you are
212 * having a specific problem with the JIT.
214 * Note that allow_jit = true does not *guarantee* that the code will be JIT
215 * compiled. If this platform is not supported or the JIT was not compiled
216 * in, the code may still be interpreted. */
217 bool allow_jit() const { return upb_pbcodecache_allowjit(ptr()); }
219 /* This may only be called when the object is first constructed, and prior to
220 * any code generation. */
221 void set_allow_jit(bool allow) { upb_pbcodecache_setallowjit(ptr(), allow); }
223 /* Should the decoder push submessages to lazy handlers for fields that have
224 * them? The caller should set this iff the lazy handlers expect data that is
225 * in protobuf binary format and the caller wishes to lazy parse it. */
226 void set_lazy(bool lazy) { upb_pbcodecache_setlazy(ptr(), lazy); }
228 /* Returns a DecoderMethod that can push data to the given handlers.
229 * If a suitable method already exists, it will be returned from the cache. */
230 const DecoderMethodPtr Get(MessageDefPtr md) {
231 return DecoderMethodPtr(upb_pbcodecache_get(ptr(), md.ptr()));
235 std::unique_ptr<upb_pbcodecache, decltype(&upb_pbcodecache_free)> ptr_;
238 #endif /* __cplusplus */
240 #endif /* UPB_DECODER_H_ */