11cb0ef41Sopenharmony_ci{# This template is generated by gen_cbor_templates.py. #}
21cb0ef41Sopenharmony_ci// Generated by lib/encoding_h.template.
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci// Copyright 2019 The Chromium Authors. All rights reserved.
51cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
61cb0ef41Sopenharmony_ci// found in the LICENSE file.
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci{% if config.encoding_lib.header == "" %}
91cb0ef41Sopenharmony_ci#ifndef {{"_".join(config.protocol.namespace)}}_encoding_h
101cb0ef41Sopenharmony_ci#define {{"_".join(config.protocol.namespace)}}_encoding_h
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <cstddef>
131cb0ef41Sopenharmony_ci#include <cstdint>
141cb0ef41Sopenharmony_ci#include <cstring>
151cb0ef41Sopenharmony_ci#include <limits>
161cb0ef41Sopenharmony_ci#include <memory>
171cb0ef41Sopenharmony_ci#include <string>
181cb0ef41Sopenharmony_ci#include <vector>
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci{% for namespace in config.protocol.namespace %}
211cb0ef41Sopenharmony_cinamespace {{namespace}} {
221cb0ef41Sopenharmony_ci{% endfor %}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// ===== encoding/encoding.h =====
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci// =============================================================================
281cb0ef41Sopenharmony_ci// span - sequence of bytes
291cb0ef41Sopenharmony_ci// =============================================================================
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci// This template is similar to std::span, which will be included in C++20.
321cb0ef41Sopenharmony_citemplate <typename T>
331cb0ef41Sopenharmony_ciclass span {
341cb0ef41Sopenharmony_ci public:
351cb0ef41Sopenharmony_ci  using index_type = size_t;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  span() : data_(nullptr), size_(0) {}
381cb0ef41Sopenharmony_ci  span(const T* data, index_type size) : data_(data), size_(size) {}
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  const T* data() const { return data_; }
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  const T* begin() const { return data_; }
431cb0ef41Sopenharmony_ci  const T* end() const { return data_ + size_; }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  const T& operator[](index_type idx) const { return data_[idx]; }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  span<T> subspan(index_type offset, index_type count) const {
481cb0ef41Sopenharmony_ci    return span(data_ + offset, count);
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  span<T> subspan(index_type offset) const {
521cb0ef41Sopenharmony_ci    return span(data_ + offset, size_ - offset);
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  bool empty() const { return size_ == 0; }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  index_type size() const { return size_; }
581cb0ef41Sopenharmony_ci  index_type size_bytes() const { return size_ * sizeof(T); }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci private:
611cb0ef41Sopenharmony_ci  const T* data_;
621cb0ef41Sopenharmony_ci  index_type size_;
631cb0ef41Sopenharmony_ci};
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_citemplate <typename T>
661cb0ef41Sopenharmony_cispan<T> SpanFrom(const std::vector<T>& v) {
671cb0ef41Sopenharmony_ci  return span<T>(v.data(), v.size());
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_citemplate <size_t N>
711cb0ef41Sopenharmony_cispan<uint8_t> SpanFrom(const char (&str)[N]) {
721cb0ef41Sopenharmony_ci  return span<uint8_t>(reinterpret_cast<const uint8_t*>(str), N - 1);
731cb0ef41Sopenharmony_ci}
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ciinline span<uint8_t> SpanFrom(const char* str) {
761cb0ef41Sopenharmony_ci  return str ? span<uint8_t>(reinterpret_cast<const uint8_t*>(str), strlen(str))
771cb0ef41Sopenharmony_ci             : span<uint8_t>();
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ciinline span<uint8_t> SpanFrom(const std::string& v) {
811cb0ef41Sopenharmony_ci  return span<uint8_t>(reinterpret_cast<const uint8_t*>(v.data()), v.size());
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci// =============================================================================
851cb0ef41Sopenharmony_ci// Status and Error codes
861cb0ef41Sopenharmony_ci// =============================================================================
871cb0ef41Sopenharmony_cienum class Error {
881cb0ef41Sopenharmony_ci  OK = 0,
891cb0ef41Sopenharmony_ci  // JSON parsing errors - json_parser.{h,cc}.
901cb0ef41Sopenharmony_ci  JSON_PARSER_UNPROCESSED_INPUT_REMAINS = 0x01,
911cb0ef41Sopenharmony_ci  JSON_PARSER_STACK_LIMIT_EXCEEDED = 0x02,
921cb0ef41Sopenharmony_ci  JSON_PARSER_NO_INPUT = 0x03,
931cb0ef41Sopenharmony_ci  JSON_PARSER_INVALID_TOKEN = 0x04,
941cb0ef41Sopenharmony_ci  JSON_PARSER_INVALID_NUMBER = 0x05,
951cb0ef41Sopenharmony_ci  JSON_PARSER_INVALID_STRING = 0x06,
961cb0ef41Sopenharmony_ci  JSON_PARSER_UNEXPECTED_ARRAY_END = 0x07,
971cb0ef41Sopenharmony_ci  JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED = 0x08,
981cb0ef41Sopenharmony_ci  JSON_PARSER_STRING_LITERAL_EXPECTED = 0x09,
991cb0ef41Sopenharmony_ci  JSON_PARSER_COLON_EXPECTED = 0x0a,
1001cb0ef41Sopenharmony_ci  JSON_PARSER_UNEXPECTED_MAP_END = 0x0b,
1011cb0ef41Sopenharmony_ci  JSON_PARSER_COMMA_OR_MAP_END_EXPECTED = 0x0c,
1021cb0ef41Sopenharmony_ci  JSON_PARSER_VALUE_EXPECTED = 0x0d,
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  CBOR_INVALID_INT32 = 0x0e,
1051cb0ef41Sopenharmony_ci  CBOR_INVALID_DOUBLE = 0x0f,
1061cb0ef41Sopenharmony_ci  CBOR_INVALID_ENVELOPE = 0x10,
1071cb0ef41Sopenharmony_ci  CBOR_INVALID_STRING8 = 0x11,
1081cb0ef41Sopenharmony_ci  CBOR_INVALID_STRING16 = 0x12,
1091cb0ef41Sopenharmony_ci  CBOR_INVALID_BINARY = 0x13,
1101cb0ef41Sopenharmony_ci  CBOR_UNSUPPORTED_VALUE = 0x14,
1111cb0ef41Sopenharmony_ci  CBOR_NO_INPUT = 0x15,
1121cb0ef41Sopenharmony_ci  CBOR_INVALID_START_BYTE = 0x16,
1131cb0ef41Sopenharmony_ci  CBOR_UNEXPECTED_EOF_EXPECTED_VALUE = 0x17,
1141cb0ef41Sopenharmony_ci  CBOR_UNEXPECTED_EOF_IN_ARRAY = 0x18,
1151cb0ef41Sopenharmony_ci  CBOR_UNEXPECTED_EOF_IN_MAP = 0x19,
1161cb0ef41Sopenharmony_ci  CBOR_INVALID_MAP_KEY = 0x1a,
1171cb0ef41Sopenharmony_ci  CBOR_STACK_LIMIT_EXCEEDED = 0x1b,
1181cb0ef41Sopenharmony_ci  CBOR_TRAILING_JUNK = 0x1c,
1191cb0ef41Sopenharmony_ci  CBOR_MAP_START_EXPECTED = 0x1d,
1201cb0ef41Sopenharmony_ci  CBOR_MAP_STOP_EXPECTED = 0x1e,
1211cb0ef41Sopenharmony_ci  CBOR_ENVELOPE_SIZE_LIMIT_EXCEEDED = 0x1f,
1221cb0ef41Sopenharmony_ci};
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci// A status value with position that can be copied. The default status
1251cb0ef41Sopenharmony_ci// is OK. Usually, error status values should come with a valid position.
1261cb0ef41Sopenharmony_cistruct Status {
1271cb0ef41Sopenharmony_ci  static constexpr size_t npos() { return std::numeric_limits<size_t>::max(); }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  bool ok() const { return error == Error::OK; }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  Error error = Error::OK;
1321cb0ef41Sopenharmony_ci  size_t pos = npos();
1331cb0ef41Sopenharmony_ci  Status(Error error, size_t pos) : error(error), pos(pos) {}
1341cb0ef41Sopenharmony_ci  Status() = default;
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  // Returns a 7 bit US-ASCII string, either "OK" or an error message
1371cb0ef41Sopenharmony_ci  // that includes the position.
1381cb0ef41Sopenharmony_ci  std::string ToASCIIString() const;
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci private:
1411cb0ef41Sopenharmony_ci  std::string ToASCIIString(const char* msg) const;
1421cb0ef41Sopenharmony_ci};
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci// Handler interface for parser events emitted by a streaming parser.
1451cb0ef41Sopenharmony_ci// See cbor::NewCBOREncoder, cbor::ParseCBOR, json::NewJSONEncoder,
1461cb0ef41Sopenharmony_ci// json::ParseJSON.
1471cb0ef41Sopenharmony_ciclass StreamingParserHandler {
1481cb0ef41Sopenharmony_ci public:
1491cb0ef41Sopenharmony_ci  virtual ~StreamingParserHandler() = default;
1501cb0ef41Sopenharmony_ci  virtual void HandleMapBegin() = 0;
1511cb0ef41Sopenharmony_ci  virtual void HandleMapEnd() = 0;
1521cb0ef41Sopenharmony_ci  virtual void HandleArrayBegin() = 0;
1531cb0ef41Sopenharmony_ci  virtual void HandleArrayEnd() = 0;
1541cb0ef41Sopenharmony_ci  virtual void HandleString8(span<uint8_t> chars) = 0;
1551cb0ef41Sopenharmony_ci  virtual void HandleString16(span<uint16_t> chars) = 0;
1561cb0ef41Sopenharmony_ci  virtual void HandleBinary(span<uint8_t> bytes) = 0;
1571cb0ef41Sopenharmony_ci  virtual void HandleDouble(double value) = 0;
1581cb0ef41Sopenharmony_ci  virtual void HandleInt32(int32_t value) = 0;
1591cb0ef41Sopenharmony_ci  virtual void HandleBool(bool value) = 0;
1601cb0ef41Sopenharmony_ci  virtual void HandleNull() = 0;
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  // The parser may send one error even after other events have already
1631cb0ef41Sopenharmony_ci  // been received. Client code is reponsible to then discard the
1641cb0ef41Sopenharmony_ci  // already processed events.
1651cb0ef41Sopenharmony_ci  // |error| must be an eror, as in, |error.is_ok()| can't be true.
1661cb0ef41Sopenharmony_ci  virtual void HandleError(Status error) = 0;
1671cb0ef41Sopenharmony_ci};
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_cinamespace cbor {
1701cb0ef41Sopenharmony_ci// The binary encoding for the inspector protocol follows the CBOR specification
1711cb0ef41Sopenharmony_ci// (RFC 7049). Additional constraints:
1721cb0ef41Sopenharmony_ci// - Only indefinite length maps and arrays are supported.
1731cb0ef41Sopenharmony_ci// - Maps and arrays are wrapped with an envelope, that is, a
1741cb0ef41Sopenharmony_ci//   CBOR tag with value 24 followed by a byte string specifying
1751cb0ef41Sopenharmony_ci//   the byte length of the enclosed map / array. The byte string
1761cb0ef41Sopenharmony_ci//   must use a 32 bit wide length.
1771cb0ef41Sopenharmony_ci// - At the top level, a message must be an indefinite length map
1781cb0ef41Sopenharmony_ci//   wrapped by an envelope.
1791cb0ef41Sopenharmony_ci// - Maximal size for messages is 2^32 (4 GiB).
1801cb0ef41Sopenharmony_ci// - For scalars, we support only the int32_t range, encoded as
1811cb0ef41Sopenharmony_ci//   UNSIGNED/NEGATIVE (major types 0 / 1).
1821cb0ef41Sopenharmony_ci// - UTF16 strings, including with unbalanced surrogate pairs, are encoded
1831cb0ef41Sopenharmony_ci//   as CBOR BYTE_STRING (major type 2). For such strings, the number of
1841cb0ef41Sopenharmony_ci//   bytes encoded must be even.
1851cb0ef41Sopenharmony_ci// - UTF8 strings (major type 3) are supported.
1861cb0ef41Sopenharmony_ci// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, never
1871cb0ef41Sopenharmony_ci//   as UTF16 strings.
1881cb0ef41Sopenharmony_ci// - Arbitrary byte arrays, in the inspector protocol called 'binary',
1891cb0ef41Sopenharmony_ci//   are encoded as BYTE_STRING (major type 2), prefixed with a byte
1901cb0ef41Sopenharmony_ci//   indicating base64 when rendered as JSON.
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci// =============================================================================
1931cb0ef41Sopenharmony_ci// Detecting CBOR content
1941cb0ef41Sopenharmony_ci// =============================================================================
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci// The first byte for an envelope, which we use for wrapping dictionaries
1971cb0ef41Sopenharmony_ci// and arrays; and the byte that indicates a byte string with 32 bit length.
1981cb0ef41Sopenharmony_ci// These two bytes start an envelope, and thereby also any CBOR message
1991cb0ef41Sopenharmony_ci// produced or consumed by this protocol. See also |EnvelopeEncoder| below.
2001cb0ef41Sopenharmony_ciuint8_t InitialByteForEnvelope();
2011cb0ef41Sopenharmony_ciuint8_t InitialByteFor32BitLengthByteString();
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci// Checks whether |msg| is a cbor message.
2041cb0ef41Sopenharmony_cibool IsCBORMessage(span<uint8_t> msg);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci// =============================================================================
2071cb0ef41Sopenharmony_ci// Encoding individual CBOR items
2081cb0ef41Sopenharmony_ci// =============================================================================
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci// Some constants for CBOR tokens that only take a single byte on the wire.
2111cb0ef41Sopenharmony_ciuint8_t EncodeTrue();
2121cb0ef41Sopenharmony_ciuint8_t EncodeFalse();
2131cb0ef41Sopenharmony_ciuint8_t EncodeNull();
2141cb0ef41Sopenharmony_ciuint8_t EncodeIndefiniteLengthArrayStart();
2151cb0ef41Sopenharmony_ciuint8_t EncodeIndefiniteLengthMapStart();
2161cb0ef41Sopenharmony_ciuint8_t EncodeStop();
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci// Encodes |value| as |UNSIGNED| (major type 0) iff >= 0, or |NEGATIVE|
2191cb0ef41Sopenharmony_ci// (major type 1) iff < 0.
2201cb0ef41Sopenharmony_civoid EncodeInt32(int32_t value, std::vector<uint8_t>* out);
2211cb0ef41Sopenharmony_civoid EncodeInt32(int32_t value, std::string* out);
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci// Encodes a UTF16 string as a BYTE_STRING (major type 2). Each utf16
2241cb0ef41Sopenharmony_ci// character in |in| is emitted with most significant byte first,
2251cb0ef41Sopenharmony_ci// appending to |out|.
2261cb0ef41Sopenharmony_civoid EncodeString16(span<uint16_t> in, std::vector<uint8_t>* out);
2271cb0ef41Sopenharmony_civoid EncodeString16(span<uint16_t> in, std::string* out);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci// Encodes a UTF8 string |in| as STRING (major type 3).
2301cb0ef41Sopenharmony_civoid EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out);
2311cb0ef41Sopenharmony_civoid EncodeString8(span<uint8_t> in, std::string* out);
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci// Encodes the given |latin1| string as STRING8.
2341cb0ef41Sopenharmony_ci// If any non-ASCII character is present, it will be represented
2351cb0ef41Sopenharmony_ci// as a 2 byte UTF8 sequence.
2361cb0ef41Sopenharmony_civoid EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out);
2371cb0ef41Sopenharmony_civoid EncodeFromLatin1(span<uint8_t> latin1, std::string* out);
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci// Encodes the given |utf16| string as STRING8 if it's entirely US-ASCII.
2401cb0ef41Sopenharmony_ci// Otherwise, encodes as STRING16.
2411cb0ef41Sopenharmony_civoid EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out);
2421cb0ef41Sopenharmony_civoid EncodeFromUTF16(span<uint16_t> utf16, std::string* out);
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci// Encodes arbitrary binary data in |in| as a BYTE_STRING (major type 2) with
2451cb0ef41Sopenharmony_ci// definitive length, prefixed with tag 22 indicating expected conversion to
2461cb0ef41Sopenharmony_ci// base64 (see RFC 7049, Table 3 and Section 2.4.4.2).
2471cb0ef41Sopenharmony_civoid EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out);
2481cb0ef41Sopenharmony_civoid EncodeBinary(span<uint8_t> in, std::string* out);
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci// Encodes / decodes a double as Major type 7 (SIMPLE_VALUE),
2511cb0ef41Sopenharmony_ci// with additional info = 27, followed by 8 bytes in big endian.
2521cb0ef41Sopenharmony_civoid EncodeDouble(double value, std::vector<uint8_t>* out);
2531cb0ef41Sopenharmony_civoid EncodeDouble(double value, std::string* out);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci// =============================================================================
2561cb0ef41Sopenharmony_ci// cbor::EnvelopeEncoder - for wrapping submessages
2571cb0ef41Sopenharmony_ci// =============================================================================
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci// An envelope indicates the byte length of a wrapped item.
2601cb0ef41Sopenharmony_ci// We use this for maps and array, which allows the decoder
2611cb0ef41Sopenharmony_ci// to skip such (nested) values whole sale.
2621cb0ef41Sopenharmony_ci// It's implemented as a CBOR tag (major type 6) with additional
2631cb0ef41Sopenharmony_ci// info = 24, followed by a byte string with a 32 bit length value;
2641cb0ef41Sopenharmony_ci// so the maximal structure that we can wrap is 2^32 bits long.
2651cb0ef41Sopenharmony_ci// See also: https://tools.ietf.org/html/rfc7049#section-2.4.4.1
2661cb0ef41Sopenharmony_ciclass EnvelopeEncoder {
2671cb0ef41Sopenharmony_ci public:
2681cb0ef41Sopenharmony_ci  // Emits the envelope start bytes and records the position for the
2691cb0ef41Sopenharmony_ci  // byte size in |byte_size_pos_|. Also emits empty bytes for the
2701cb0ef41Sopenharmony_ci  // byte sisze so that encoding can continue.
2711cb0ef41Sopenharmony_ci  void EncodeStart(std::vector<uint8_t>* out);
2721cb0ef41Sopenharmony_ci  void EncodeStart(std::string* out);
2731cb0ef41Sopenharmony_ci  // This records the current size in |out| at position byte_size_pos_.
2741cb0ef41Sopenharmony_ci  // Returns true iff successful.
2751cb0ef41Sopenharmony_ci  bool EncodeStop(std::vector<uint8_t>* out);
2761cb0ef41Sopenharmony_ci  bool EncodeStop(std::string* out);
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci private:
2791cb0ef41Sopenharmony_ci  size_t byte_size_pos_ = 0;
2801cb0ef41Sopenharmony_ci};
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci// =============================================================================
2831cb0ef41Sopenharmony_ci// cbor::NewCBOREncoder - for encoding from a streaming parser
2841cb0ef41Sopenharmony_ci// =============================================================================
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci// This can be used to convert to CBOR, by passing the return value to a parser
2871cb0ef41Sopenharmony_ci// that drives it. The handler will encode into |out|, and iff an error occurs
2881cb0ef41Sopenharmony_ci// it will set |status| to an error and clear |out|. Otherwise, |status.ok()|
2891cb0ef41Sopenharmony_ci// will be |true|.
2901cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewCBOREncoder(
2911cb0ef41Sopenharmony_ci    std::vector<uint8_t>* out,
2921cb0ef41Sopenharmony_ci    Status* status);
2931cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewCBOREncoder(std::string* out,
2941cb0ef41Sopenharmony_ci                                                       Status* status);
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci// =============================================================================
2971cb0ef41Sopenharmony_ci// cbor::CBORTokenizer - for parsing individual CBOR items
2981cb0ef41Sopenharmony_ci// =============================================================================
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci// Tags for the tokens within a CBOR message that CBORTokenizer understands.
3011cb0ef41Sopenharmony_ci// Note that this is not the same terminology as the CBOR spec (RFC 7049),
3021cb0ef41Sopenharmony_ci// but rather, our adaptation. For instance, we lump unsigned and signed
3031cb0ef41Sopenharmony_ci// major type into INT32 here (and disallow values outside the int32_t range).
3041cb0ef41Sopenharmony_cienum class CBORTokenTag {
3051cb0ef41Sopenharmony_ci  // Encountered an error in the structure of the message. Consult
3061cb0ef41Sopenharmony_ci  // status() for details.
3071cb0ef41Sopenharmony_ci  ERROR_VALUE,
3081cb0ef41Sopenharmony_ci  // Booleans and NULL.
3091cb0ef41Sopenharmony_ci  TRUE_VALUE,
3101cb0ef41Sopenharmony_ci  FALSE_VALUE,
3111cb0ef41Sopenharmony_ci  NULL_VALUE,
3121cb0ef41Sopenharmony_ci  // An int32_t (signed 32 bit integer).
3131cb0ef41Sopenharmony_ci  INT32,
3141cb0ef41Sopenharmony_ci  // A double (64 bit floating point).
3151cb0ef41Sopenharmony_ci  DOUBLE,
3161cb0ef41Sopenharmony_ci  // A UTF8 string.
3171cb0ef41Sopenharmony_ci  STRING8,
3181cb0ef41Sopenharmony_ci  // A UTF16 string.
3191cb0ef41Sopenharmony_ci  STRING16,
3201cb0ef41Sopenharmony_ci  // A binary string.
3211cb0ef41Sopenharmony_ci  BINARY,
3221cb0ef41Sopenharmony_ci  // Starts an indefinite length map; after the map start we expect
3231cb0ef41Sopenharmony_ci  // alternating keys and values, followed by STOP.
3241cb0ef41Sopenharmony_ci  MAP_START,
3251cb0ef41Sopenharmony_ci  // Starts an indefinite length array; after the array start we
3261cb0ef41Sopenharmony_ci  // expect values, followed by STOP.
3271cb0ef41Sopenharmony_ci  ARRAY_START,
3281cb0ef41Sopenharmony_ci  // Ends a map or an array.
3291cb0ef41Sopenharmony_ci  STOP,
3301cb0ef41Sopenharmony_ci  // An envelope indicator, wrapping a map or array.
3311cb0ef41Sopenharmony_ci  // Internally this carries the byte length of the wrapped
3321cb0ef41Sopenharmony_ci  // map or array. While CBORTokenizer::Next() will read / skip the entire
3331cb0ef41Sopenharmony_ci  // envelope, CBORTokenizer::EnterEnvelope() reads the tokens
3341cb0ef41Sopenharmony_ci  // inside of it.
3351cb0ef41Sopenharmony_ci  ENVELOPE,
3361cb0ef41Sopenharmony_ci  // We've reached the end there is nothing else to read.
3371cb0ef41Sopenharmony_ci  DONE,
3381cb0ef41Sopenharmony_ci};
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci// The major types from RFC 7049 Section 2.1.
3411cb0ef41Sopenharmony_cienum class MajorType {
3421cb0ef41Sopenharmony_ci  UNSIGNED = 0,
3431cb0ef41Sopenharmony_ci  NEGATIVE = 1,
3441cb0ef41Sopenharmony_ci  BYTE_STRING = 2,
3451cb0ef41Sopenharmony_ci  STRING = 3,
3461cb0ef41Sopenharmony_ci  ARRAY = 4,
3471cb0ef41Sopenharmony_ci  MAP = 5,
3481cb0ef41Sopenharmony_ci  TAG = 6,
3491cb0ef41Sopenharmony_ci  SIMPLE_VALUE = 7
3501cb0ef41Sopenharmony_ci};
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci// CBORTokenizer segments a CBOR message, presenting the tokens therein as
3531cb0ef41Sopenharmony_ci// numbers, strings, etc. This is not a complete CBOR parser, but makes it much
3541cb0ef41Sopenharmony_ci// easier to implement one (e.g. ParseCBOR, above). It can also be used to parse
3551cb0ef41Sopenharmony_ci// messages partially.
3561cb0ef41Sopenharmony_ciclass CBORTokenizer {
3571cb0ef41Sopenharmony_ci public:
3581cb0ef41Sopenharmony_ci  explicit CBORTokenizer(span<uint8_t> bytes);
3591cb0ef41Sopenharmony_ci  ~CBORTokenizer();
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  // Identifies the current token that we're looking at,
3621cb0ef41Sopenharmony_ci  // or ERROR_VALUE (in which ase ::Status() has details)
3631cb0ef41Sopenharmony_ci  // or DONE (if we're past the last token).
3641cb0ef41Sopenharmony_ci  CBORTokenTag TokenTag() const;
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // Advances to the next token.
3671cb0ef41Sopenharmony_ci  void Next();
3681cb0ef41Sopenharmony_ci  // Can only be called if TokenTag() == CBORTokenTag::ENVELOPE.
3691cb0ef41Sopenharmony_ci  // While Next() would skip past the entire envelope / what it's
3701cb0ef41Sopenharmony_ci  // wrapping, EnterEnvelope positions the cursor inside of the envelope,
3711cb0ef41Sopenharmony_ci  // letting the client explore the nested structure.
3721cb0ef41Sopenharmony_ci  void EnterEnvelope();
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci  // If TokenTag() is CBORTokenTag::ERROR_VALUE, then Status().error describes
3751cb0ef41Sopenharmony_ci  // the error more precisely; otherwise it'll be set to Error::OK.
3761cb0ef41Sopenharmony_ci  // In either case, Status().pos is the current position.
3771cb0ef41Sopenharmony_ci  struct Status Status() const;
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  // The following methods retrieve the token values. They can only
3801cb0ef41Sopenharmony_ci  // be called if TokenTag() matches.
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::INT32.
3831cb0ef41Sopenharmony_ci  int32_t GetInt32() const;
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::DOUBLE.
3861cb0ef41Sopenharmony_ci  double GetDouble() const;
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::STRING8.
3891cb0ef41Sopenharmony_ci  span<uint8_t> GetString8() const;
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  // Wire representation for STRING16 is low byte first (little endian).
3921cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::STRING16.
3931cb0ef41Sopenharmony_ci  span<uint8_t> GetString16WireRep() const;
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::BINARY.
3961cb0ef41Sopenharmony_ci  span<uint8_t> GetBinary() const;
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  // To be called only if ::TokenTag() == CBORTokenTag::ENVELOPE.
3991cb0ef41Sopenharmony_ci  span<uint8_t> GetEnvelopeContents() const;
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci private:
4021cb0ef41Sopenharmony_ci  void ReadNextToken(bool enter_envelope);
4031cb0ef41Sopenharmony_ci  void SetToken(CBORTokenTag token, size_t token_byte_length);
4041cb0ef41Sopenharmony_ci  void SetError(Error error);
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  span<uint8_t> bytes_;
4071cb0ef41Sopenharmony_ci  CBORTokenTag token_tag_;
4081cb0ef41Sopenharmony_ci  struct Status status_;
4091cb0ef41Sopenharmony_ci  size_t token_byte_length_;
4101cb0ef41Sopenharmony_ci  MajorType token_start_type_;
4111cb0ef41Sopenharmony_ci  uint64_t token_start_internal_value_;
4121cb0ef41Sopenharmony_ci};
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci// =============================================================================
4151cb0ef41Sopenharmony_ci// cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
4161cb0ef41Sopenharmony_ci// =============================================================================
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci// Parses a CBOR encoded message from |bytes|, sending events to
4191cb0ef41Sopenharmony_ci// |out|. If an error occurs, sends |out->HandleError|, and parsing stops.
4201cb0ef41Sopenharmony_ci// The client is responsible for discarding the already received information in
4211cb0ef41Sopenharmony_ci// that case.
4221cb0ef41Sopenharmony_civoid ParseCBOR(span<uint8_t> bytes, StreamingParserHandler* out);
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci// =============================================================================
4251cb0ef41Sopenharmony_ci// cbor::AppendString8EntryToMap - for limited in-place editing of messages
4261cb0ef41Sopenharmony_ci// =============================================================================
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci// Modifies the |cbor| message by appending a new key/value entry at the end
4291cb0ef41Sopenharmony_ci// of the map. Patches up the envelope size; Status.ok() iff successful.
4301cb0ef41Sopenharmony_ci// If not successful, |cbor| may be corrupted after this call.
4311cb0ef41Sopenharmony_ciStatus AppendString8EntryToCBORMap(span<uint8_t> string8_key,
4321cb0ef41Sopenharmony_ci                                   span<uint8_t> string8_value,
4331cb0ef41Sopenharmony_ci                                   std::vector<uint8_t>* cbor);
4341cb0ef41Sopenharmony_ciStatus AppendString8EntryToCBORMap(span<uint8_t> string8_key,
4351cb0ef41Sopenharmony_ci                                   span<uint8_t> string8_value,
4361cb0ef41Sopenharmony_ci                                   std::string* cbor);
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_cinamespace internals {  // Exposed only for writing tests.
4391cb0ef41Sopenharmony_cisize_t ReadTokenStart(span<uint8_t> bytes,
4401cb0ef41Sopenharmony_ci                      cbor::MajorType* type,
4411cb0ef41Sopenharmony_ci                      uint64_t* value);
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_civoid WriteTokenStart(cbor::MajorType type,
4441cb0ef41Sopenharmony_ci                     uint64_t value,
4451cb0ef41Sopenharmony_ci                     std::vector<uint8_t>* encoded);
4461cb0ef41Sopenharmony_civoid WriteTokenStart(cbor::MajorType type,
4471cb0ef41Sopenharmony_ci                     uint64_t value,
4481cb0ef41Sopenharmony_ci                     std::string* encoded);
4491cb0ef41Sopenharmony_ci}  // namespace internals
4501cb0ef41Sopenharmony_ci}  // namespace cbor
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_cinamespace json {
4531cb0ef41Sopenharmony_ci// Client code must provide an instance. Implementation should delegate
4541cb0ef41Sopenharmony_ci// to whatever is appropriate.
4551cb0ef41Sopenharmony_ciclass Platform {
4561cb0ef41Sopenharmony_ci public:
4571cb0ef41Sopenharmony_ci  virtual ~Platform() = default;
4581cb0ef41Sopenharmony_ci  // Parses |str| into |result|. Returns false iff there are
4591cb0ef41Sopenharmony_ci  // leftover characters or parsing errors.
4601cb0ef41Sopenharmony_ci  virtual bool StrToD(const char* str, double* result) const = 0;
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  // Prints |value| in a format suitable for JSON.
4631cb0ef41Sopenharmony_ci  virtual std::unique_ptr<char[]> DToStr(double value) const = 0;
4641cb0ef41Sopenharmony_ci};
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci// =============================================================================
4671cb0ef41Sopenharmony_ci// json::NewJSONEncoder - for encoding streaming parser events as JSON
4681cb0ef41Sopenharmony_ci// =============================================================================
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci// Returns a handler object which will write ascii characters to |out|.
4711cb0ef41Sopenharmony_ci// |status->ok()| will be false iff the handler routine HandleError() is called.
4721cb0ef41Sopenharmony_ci// In that case, we'll stop emitting output.
4731cb0ef41Sopenharmony_ci// Except for calling the HandleError routine at any time, the client
4741cb0ef41Sopenharmony_ci// code must call the Handle* methods in an order in which they'd occur
4751cb0ef41Sopenharmony_ci// in valid JSON; otherwise we may crash (the code uses assert).
4761cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewJSONEncoder(
4771cb0ef41Sopenharmony_ci    const Platform* platform,
4781cb0ef41Sopenharmony_ci    std::vector<uint8_t>* out,
4791cb0ef41Sopenharmony_ci    Status* status);
4801cb0ef41Sopenharmony_cistd::unique_ptr<StreamingParserHandler> NewJSONEncoder(const Platform* platform,
4811cb0ef41Sopenharmony_ci                                                       std::string* out,
4821cb0ef41Sopenharmony_ci                                                       Status* status);
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci// =============================================================================
4851cb0ef41Sopenharmony_ci// json::ParseJSON - for receiving streaming parser events for JSON
4861cb0ef41Sopenharmony_ci// =============================================================================
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_civoid ParseJSON(const Platform& platform,
4891cb0ef41Sopenharmony_ci               span<uint8_t> chars,
4901cb0ef41Sopenharmony_ci               StreamingParserHandler* handler);
4911cb0ef41Sopenharmony_civoid ParseJSON(const Platform& platform,
4921cb0ef41Sopenharmony_ci               span<uint16_t> chars,
4931cb0ef41Sopenharmony_ci               StreamingParserHandler* handler);
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci// =============================================================================
4961cb0ef41Sopenharmony_ci// json::ConvertCBORToJSON, json::ConvertJSONToCBOR - for transcoding
4971cb0ef41Sopenharmony_ci// =============================================================================
4981cb0ef41Sopenharmony_ciStatus ConvertCBORToJSON(const Platform& platform,
4991cb0ef41Sopenharmony_ci                         span<uint8_t> cbor,
5001cb0ef41Sopenharmony_ci                         std::string* json);
5011cb0ef41Sopenharmony_ciStatus ConvertCBORToJSON(const Platform& platform,
5021cb0ef41Sopenharmony_ci                         span<uint8_t> cbor,
5031cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* json);
5041cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
5051cb0ef41Sopenharmony_ci                         span<uint8_t> json,
5061cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* cbor);
5071cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
5081cb0ef41Sopenharmony_ci                         span<uint16_t> json,
5091cb0ef41Sopenharmony_ci                         std::vector<uint8_t>* cbor);
5101cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
5111cb0ef41Sopenharmony_ci                         span<uint8_t> json,
5121cb0ef41Sopenharmony_ci                         std::string* cbor);
5131cb0ef41Sopenharmony_ciStatus ConvertJSONToCBOR(const Platform& platform,
5141cb0ef41Sopenharmony_ci                         span<uint16_t> json,
5151cb0ef41Sopenharmony_ci                         std::string* cbor);
5161cb0ef41Sopenharmony_ci}  // namespace json
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci{% for namespace in config.protocol.namespace %}
5191cb0ef41Sopenharmony_ci} // namespace {{namespace}}
5201cb0ef41Sopenharmony_ci{% endfor %}
5211cb0ef41Sopenharmony_ci#endif // !defined({{"_".join(config.protocol.namespace)}}_encoding_h)
5221cb0ef41Sopenharmony_ci{% endif %}
523