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