1cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler/*
2cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * Copyright (C) 2016 The Android Open Source Project
3cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler *
4cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * Licensed under the Apache License, Version 2.0 (the "License");
5cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * you may not use this file except in compliance with the License.
6cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * You may obtain a copy of the License at
7cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler *
8cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler *      http://www.apache.org/licenses/LICENSE-2.0
9cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler *
10cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * Unless required by applicable law or agreed to in writing, software
11cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * distributed under the License is distributed on an "AS IS" BASIS,
12cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * See the License for the specific language governing permissions and
14cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler * limitations under the License.
15cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler */
16cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
17a715cb1840f9a0c813c90707a351687f7a77950eMattias Nissler#ifndef NVRAM_MESSAGES_IO_H_
18a715cb1840f9a0c813c90707a351687f7a77950eMattias Nissler#define NVRAM_MESSAGES_IO_H_
19cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
20cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerextern "C" {
21cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler#include <stddef.h>
22cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler#include <stdint.h>
23cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler}
24cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
25a715cb1840f9a0c813c90707a351687f7a77950eMattias Nissler#include <nvram/messages/blob.h>
26a715cb1840f9a0c813c90707a351687f7a77950eMattias Nissler#include <nvram/messages/compiler.h>
27cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
28cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslernamespace nvram {
29cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
30cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// Abstraction used by the protobuf decoder to read data. The idea here is that
313d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// |InputStreamBuffer| maintains a window of the data to be read. Access to the
323d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// contents of the current window is direct, i.e. doesn't need to go through
333d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// virtual dispatch to subclasses. Whenever the window is exhausted, the next
343d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// window must be set up. This latter operation is left for implementation of
353d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// the virtual |Advance()| member function in subclasses, which is entirely free
363d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// to pull its data from anywhere.
37cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT InputStreamBuffer {
38cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
393d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  InputStreamBuffer() = default;
40cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  InputStreamBuffer(const void* data, size_t size);
41cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  InputStreamBuffer(const void* start, const void* end);
423d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  virtual ~InputStreamBuffer() = default;
43cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
44cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Checks whether the stream is exhausted;
45cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Done();
46cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
47cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Consume |size| bytes from the stream and store them in the provided |data|
48cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // buffer. Returns false if insufficient bytes are available.
49cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Read(void* data, size_t size);
50cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
51cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Consume a single byte and place it in |byte|. Returns true if successful,
52cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // i.e. if there was a byte available.
53cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool ReadByte(uint8_t* byte);
54cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
55cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Discard |size| bytes from the stream. Returns false if there are fewer
56cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // bytes available.
57cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Skip(size_t size);
58cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
59cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler protected:
60cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Update the |pos_| and |end_| pointers for the next buffer window. Returns
61cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // true if the window was successfully set up, false on I/O errors or stream
62cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // exhaustion. The default implementation just returns false to signal
63cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // immediate stream exhaustion. Subclasses should override this to pull in
64cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // more data from the underlying data source.
65cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  virtual bool Advance();
66cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
67cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Pointers to the buffer to read from. |InputStreamBuffer| only advances
68cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |pos_| until reaching |end_|. At this point, |Advance| is called for the
69cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // subclass to initialize the next buffer window and update the pointers.
70cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  const uint8_t* pos_ = nullptr;
71cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  const uint8_t* end_ = nullptr;
72cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
73cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Allow |NestedInputStreamBuffer| to mess with |pos_| and |end_|, also in its
74cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // delegate, which isn't necessarily of type |NestedInputStreamBuffer|.
75cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  friend class NestedInputStreamBuffer;
76cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
77cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
78cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// An |InputStreamBuffer| implementation that pulls its data from a delegate,
79cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// but only up to a predetermined limit of bytes.
80cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT NestedInputStreamBuffer : public InputStreamBuffer {
81cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
82cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Initialize a |NestedInputStreamBuffer| to provide at most |size| bytes from
83cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |delegate|. Note that |delegate| must remain valid throughout the life time
84cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // of this |NestedInputStreamBuffer|.
85cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  NestedInputStreamBuffer(InputStreamBuffer* delegate, size_t size);
863d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  ~NestedInputStreamBuffer() override = default;
87cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
88cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler private:
89cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // InputStreamBuffer:
90cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Advance() override;
91cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
9242455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  // Determine the input window end based on |delegate|'s current window and the
9342455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  // requested |size| to read. If |size| can be satisfied from |delegate|'s
9442455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  // current window, return an end pointer within that window. If size is larger
9542455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  // than the remaining bytes available in |delegate|'s input window, return
9642455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  // |delegate|'s |end_| pointer.
9742455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler  static const uint8_t* ClampEnd(InputStreamBuffer* delegate, size_t size);
9842455ff2abfc7ed92a35287d1b3bc6049161adb9Mattias Nissler
99cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  InputStreamBuffer* delegate_;
100cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  size_t remaining_;
101cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
102cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
1033d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// Abstraction used by the protobuf decoder to output data. This class maintains
1043d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// a current window of memory to write output to. Access to the current window's
1053d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// bytes is direct and doesn't require virtual dispatch. Once the capacity of
1063d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// the current window is exhausted, the virtual |Advance()| member function is
1073d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// invoked to set up a new window. Subclasses are entirely free to implement
1083d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// this operation as appropriate for their I/O mechanism, for example a
1093d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// socket-based implementations might flush the buffer to the socket and reset
1103d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler// the window pointers to accept more output.
111cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT OutputStreamBuffer {
112cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
1133d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  OutputStreamBuffer() = default;
114cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  OutputStreamBuffer(void* data, size_t size);
115cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  OutputStreamBuffer(void* data, void* end);
1163d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  virtual ~OutputStreamBuffer() = default;
117cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
118cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Checks whether the stream is exhausted.
119cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Done();
120cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
121cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Writes a blob of |size| bytes provided in |data| to the underlying buffer.
122cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Returns false if there is not enough space available.
123cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Write(const void* data, size_t size);
124cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
125cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Writes |byte| to the underlying buffer. Returns false if there is not
126cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // enough space available.
127cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool WriteByte(uint8_t byte);
128cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
129cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler protected:
130cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Set up the next data buffer window in |pos_| and |end_|. Returns true on
131cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // success, false on I/O errors or stream exhaustion. The default
132cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // implementation unconditionally returns false, i.e. signaling stream
133cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // exhaustion after the initial window is filled. Subclasses should override
134cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // this to flush buffers to the underlying data sink and set up a fresh buffer
135cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // for more data as appropriate.
136cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  virtual bool Advance();
137cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
138cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // The |pos_| and |end_| pointers define a window of writable buffer space for
139cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |OutputStreamBuffer| to place data in. |pos_| grows towards |end_| as
140cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // writes occur. Once |pos_| hits |end_|, |OutputStreamBuffer| will call
141cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |Advance|, which subclasses can implement to provide a new buffer window in
142cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |pos_| and |end_|.
143cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  uint8_t* pos_ = nullptr;
144cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  uint8_t* end_ = nullptr;
145cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
146cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
147417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler// An |OutputStreamBuffer| backed by a single data buffer.
148417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nisslerclass NVRAM_EXPORT ArrayOutputStreamBuffer : public OutputStreamBuffer {
149417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler public:
150417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  ArrayOutputStreamBuffer() = default;
151417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  ArrayOutputStreamBuffer(void* data, size_t size)
152417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler      : OutputStreamBuffer(data, size), data_(pos_) {}
153417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  ArrayOutputStreamBuffer(void* data, void* end)
154417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler      : OutputStreamBuffer(data, end), data_(pos_) {}
155417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  ~ArrayOutputStreamBuffer() override = default;
156417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler
157417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  // Returns the number of bytes already written.
158417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  size_t bytes_written() const { return pos_ - data_; }
159417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler
160417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler private:
161417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler  uint8_t* data_ = nullptr;
162417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler};
163417e23fa8c8c8f9dd77a19e60c47b46d5454000dMattias Nissler
164cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// An |OutputStream| implementation that doesn't write anything, but just counts
165cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// the number of bytes written.
166cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT CountingOutputStreamBuffer : public OutputStreamBuffer {
167cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
168cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  CountingOutputStreamBuffer();
1693d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  ~CountingOutputStreamBuffer() override = default;
170cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
171cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  size_t bytes_written() const {
172cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler    return bytes_written_ + (pos_ - scratch_space_);
173cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  }
174cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
175cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler protected:
176cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // OutputStreamBuffer:
177cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Advance() override;
178cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
179cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler private:
180cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // We share a single scratch buffer that all |CountingOutputStreamBuffer|
181cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // instances use as the destination for writes. Its contents are pretty much
182cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // unpredictable.
1833d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  //
1843d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  // TODO(mnissler): This adds a static 256 bytes memory allocation to each
1853d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  // process linking to this code. If that becomes a problem, we might want to
1863d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  // be smarter here and dynamically allocate a chunk of memory only when it's
1873d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  // needed, or maybe even map some address space that's not even backed by
1883d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  // actual memory (not sure that's possible).
1893d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  static constexpr size_t kScratchSpaceSize = 256;
190cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  static uint8_t scratch_space_[kScratchSpaceSize];
191cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
192cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Number of bytes that had been written when the last |Advance()| call
193cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // occurred.
194cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  size_t bytes_written_ = 0;
195cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
196cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
197cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// An |OutputStreamBuffer| implementation that stores all data to a wrapped
198cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// |Blob|, growing it as necessary.
199cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT BlobOutputStreamBuffer : public OutputStreamBuffer {
200cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
201cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Construct a |BlobOutputStreamBuffer| that stores all written data to
202cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |blob|, which will get resized as necessary. Note that |blob| must remain
203cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // valid for the life time of the |BlobOutputStreamBuffer| object.
204bb621b95ea636314c87b885107c8d5331992f9bbChih-Hung Hsieh  explicit BlobOutputStreamBuffer(Blob* blob);
2053d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  ~BlobOutputStreamBuffer() override = default;
206cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
207cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Truncate the blob to match the current output size.
208cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Truncate();
209cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
210cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler protected:
211cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // OutputStreamBuffer:
2123d2f13f288feb42f1dfcfe558af27955edefaad3Mattias Nissler  bool Advance() override;
213cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
214cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler private:
215cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  Blob* blob_;
216cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
217cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
218cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// Protobuf wire types.
219cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerenum class WireType : int8_t {
220cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kVarint = 0,
221cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kFixed64 = 1,
222cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kLengthDelimited = 2,
223cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kStartGroup = 3,
224cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kEndGroup = 4,
225cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  kFixed32 = 5,
226cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
227cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
228cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// A class implementing a parser for the low-level protobuf wire format. It
229cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// obtains raw data from a wrapped |InputStream| and offers member functions
230cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// that facilitate decoding the data according to the protobuf wire format.
231cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT ProtoReader {
232cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
233cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Construct a new |ProtoReader| that consumes data from |stream_buffer|.
234cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |stream_buffer| must remain valid throughout the life time of the
235cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |ProtoReader|.
236cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  explicit ProtoReader(InputStreamBuffer* stream_buffer);
237cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
238cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Access to the underlying stream buffer.
239cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  InputStreamBuffer* stream_buffer() { return stream_buffer_; }
240cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
241cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Wire type of the current field.
242cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  WireType wire_type() const { return static_cast<WireType>(wire_type_); }
243cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
244cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Field number of the current field.
245cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  uint64_t field_number() const { return field_number_; }
246cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
247cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Size of the field data, if known in advance.
248cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  size_t field_size() const { return field_size_; }
249cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
250cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Whether all data is consumed.
251cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Done() const { return stream_buffer_->Done(); }
252cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
253cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Reads the next wire tag from the current position in the underlying
254cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |stream_buffer_| and initializes internal fields. Previous state is
255cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // discarded silently.
256cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool ReadWireTag();
257cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
258cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Read a varint-encoded field and advances to the next field. Returns true if
259cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // successful.
260cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool ReadVarint(uint64_t* value);
261cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
262cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Read field data. Checks that |size| matches |field_size()| and copies out
263cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // the data to the provided |data| buffer. Advances to the next field and
264cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // returns true if successful.
265cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool ReadLengthDelimited(void* data, size_t size);
266cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
267cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Skips over the current field data.
268cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool SkipField();
269cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
270cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler private:
271cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  static constexpr int8_t kInvalidWireType = -1;
272cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
273cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  InputStreamBuffer* stream_buffer_;
274cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
275cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Information about the current field. |wire_type == kInvalidWireType|
276cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // indicates that there is no current field to be consumed.
277cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  int8_t wire_type_ = kInvalidWireType;
278cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  uint64_t field_number_ = 0;
279cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  size_t field_size_ = 0;
280cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
281cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
282cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// |ProtoWriter| contains logic to write raw data according to the protobuf wire
283cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler// format to an |OutputStreamBuffer|.
284cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nisslerclass NVRAM_EXPORT ProtoWriter {
285cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler public:
286cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Construct a |ProtoWriter| which will send its output to |stream_buffer|.
287cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |stream_buffer| must remain valid for the life time of the |ProtoWriter|.
288cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  explicit ProtoWriter(OutputStreamBuffer* stream_buffer);
289cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
290cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Access to the underlying stream buffer.
291cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  OutputStreamBuffer* stream_buffer() { return stream_buffer_; }
292cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
293cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Sets the field number to use when emitting a tag.
294cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  void set_field_number(uint64_t field_number) { field_number_ = field_number; }
295cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
296cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Whether the writer has exhausted the underlying |OutputStream|'s capacity.
297cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool Done() const { return stream_buffer_->Done(); }
298cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
299cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Write |value| as a varint-encoded field. Returns true if successful, i.e.
300cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // the data was successfully written to |stream_buffer_|.
301cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool WriteVarint(uint64_t value);
302cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
303cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Write |size| bytes stored at |data| to |stream_buffer_|. Returns true if
304cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // successful, i.e. the data was successfully written to |stream_buffer_|.
305cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool WriteLengthDelimited(const void* data, size_t size);
306cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
307cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // Writes a wire tag for a length-delimited field, followed by a length
308cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // indication for |size| data bytes. It is up to the caller to emit exactly
309cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // |size| bytes to |stream_buffer()|, otherwise the encoded data will be
310cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // malformed.
311cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool WriteLengthHeader(size_t size);
312cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
313cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler private:
314cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // A helper to write a wire tag using the current field number and the
315cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  // provided wire type.
316cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  bool WriteWireTag(WireType wire_type);
317cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
318cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  OutputStreamBuffer* stream_buffer_;
319cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler  uint64_t field_number_ = 0;
320cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler};
321cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
322cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler}  // namespace nvram
323cdab12349a989828ccc9698bd9f6a0f1687453f9Mattias Nissler
324a715cb1840f9a0c813c90707a351687f7a77950eMattias Nissler#endif  // NVRAM_MESSAGES_IO_H_
325