mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-11-04 16:27:18 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			643 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			643 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/************************************************************************************
 | 
						|
 *
 | 
						|
 * D++, A Lightweight C++ library for Discord
 | 
						|
 *
 | 
						|
 * Copyright 2021 Craig Edwards and D++ contributors 
 | 
						|
 * (https://github.com/brainboxdotcc/DPP/graphs/contributors)
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 * 
 | 
						|
 * Parts of this file inspired by, or outright copied from erlpack:
 | 
						|
 * https://github.com/discord/erlpack/
 | 
						|
 * 
 | 
						|
 * Acknowledgements:
 | 
						|
 *
 | 
						|
 *   sysdep.h:
 | 
						|
 *       Based on work by FURUHASHI Sadayuki in msgpack-python
 | 
						|
 *       (https://github.com/msgpack/msgpack-python)
 | 
						|
 *
 | 
						|
 *       Copyright (C) 2008-2010 FURUHASHI Sadayuki
 | 
						|
 *       Licensed under the Apache License, Version 2.0 (the "License").
 | 
						|
 *
 | 
						|
 ************************************************************************************/
 | 
						|
 | 
						|
#pragma once
 | 
						|
#include <dpp/export.h>
 | 
						|
#include <dpp/snowflake.h>
 | 
						|
#include <dpp/json_fwd.h>
 | 
						|
 | 
						|
namespace dpp {
 | 
						|
 | 
						|
/** Current ETF format version in use */
 | 
						|
const uint8_t FORMAT_VERSION = 131;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Represents a token which identifies the type of value which follows it
 | 
						|
 * in the ETF binary structure.
 | 
						|
 */
 | 
						|
enum etf_token_type : uint8_t {
 | 
						|
	/// 68  [Distribution header]
 | 
						|
	ett_distribution =	'D',
 | 
						|
	/// 70  [Float64:IEEE float]
 | 
						|
	ett_new_float =		'F',
 | 
						|
	/// 77  [UInt32:Len, UInt8:Bits, Len:Data]
 | 
						|
	ett_bit_binary =	'M',
 | 
						|
	/// 80  [UInt4:UncompressedSize, N:ZlibCompressedData]
 | 
						|
	ett_compressed =	'P',
 | 
						|
	/// 97  [UInt8:Int]
 | 
						|
	ett_smallint =		'a',
 | 
						|
	/// 98  [Int32:Int]
 | 
						|
	ett_integer =		'b',
 | 
						|
	/// 99  [31:Float String] Float in string format (formatted "%.20e", sscanf "%lf"). Superseded by ett_new_float
 | 
						|
	ett_float =		'c',
 | 
						|
	/// 100 [UInt16:Len, Len:AtomName] max Len is 255
 | 
						|
	ett_atom =		'd',
 | 
						|
	/// 101 [atom:Node, UInt32:ID, UInt8:Creation]
 | 
						|
	ett_reference =		'e',
 | 
						|
	/// 102 [atom:Node, UInt32:ID, UInt8:Creation]
 | 
						|
	ett_port =		'f',
 | 
						|
	/// 103 [atom:Node, UInt32:ID, UInt32:Serial, UInt8:Creation]
 | 
						|
	ett_pid =		'g',
 | 
						|
	/// 104 [UInt8:Arity, N:Elements]
 | 
						|
	ett_small_tuple =	'h',
 | 
						|
	/// 105 [UInt32:Arity, N:Elements]
 | 
						|
	ett_large_tuple =	'i',
 | 
						|
	/// 106 empty list
 | 
						|
	ett_nil =		'j',
 | 
						|
	/// 107 [UInt16:Len, Len:Characters]
 | 
						|
	ett_string =		'k',
 | 
						|
	/// 108 [UInt32:Len, Elements, Tail]
 | 
						|
	ett_list =		'l',
 | 
						|
	/// 109 [UInt32:Len, Len:Data]
 | 
						|
	ett_binary =		'm',
 | 
						|
	/// 110 [UInt8:n, UInt8:Sign, n:nums]
 | 
						|
	ett_bigint_small =	'n',
 | 
						|
	/// 111 [UInt32:n, UInt8:Sign, n:nums]
 | 
						|
	ett_bigint_large =	'o',
 | 
						|
	/// 112 [UInt32:Size, UInt8:Arity, 16*Uint6-MD5:Uniq, UInt32:Index, UInt32:NumFree, atom:Module, int:OldIndex, int:OldUniq, pid:Pid, NunFree*ext:FreeVars]
 | 
						|
	ett_new_function =	'p',
 | 
						|
	/// 113 [atom:Module, atom:Function, smallint:Arity]
 | 
						|
	ett_export =		'q',
 | 
						|
	/// 114 [UInt16:Len, atom:Node, UInt8:Creation, Len*UInt32:ID]
 | 
						|
	ett_new_reference =	'r',
 | 
						|
	/// 115 [UInt8:Len, Len:AtomName]
 | 
						|
	ett_atom_small =	's',
 | 
						|
	/// 116 [UInt32:Airty, N:Pairs]
 | 
						|
	ett_map =	 	't',
 | 
						|
	/// 117 [UInt4:NumFree, pid:Pid, atom:Module, int:Index, int:Uniq, NumFree*ext:FreeVars]
 | 
						|
	ett_function =		'u',
 | 
						|
	/// 118 [UInt16:Len, Len:AtomName] max Len is 255 characters (up to 4 bytes per)
 | 
						|
	ett_atom_utf8 =		'v',
 | 
						|
	/// 119 [UInt8:Len, Len:AtomName]
 | 
						|
	ett_atom_utf8_small =	'w'
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief A horrible structure used within the ETF parser to convert uint64_t to double and back.
 | 
						|
 * This is horrible, but it is the official way erlang term format does this, so we can't really
 | 
						|
 * mess with it much.
 | 
						|
 */
 | 
						|
union type_punner {
 | 
						|
	/**
 | 
						|
	 * @brief binary integer value
 | 
						|
	 */
 | 
						|
	uint64_t ui64;
 | 
						|
	/**
 | 
						|
	 * @brief double floating point value
 | 
						|
	 */
 | 
						|
	double df;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Represents a buffer of bytes being encoded into ETF
 | 
						|
 */
 | 
						|
struct DPP_EXPORT etf_buffer {
 | 
						|
	/**
 | 
						|
	 * @brief Raw buffer
 | 
						|
	 */
 | 
						|
	std::vector<char> buf;
 | 
						|
	/**
 | 
						|
	 * @brief Current used length of buffer
 | 
						|
	 * (this is different from buf.size() as it is pre-allocated
 | 
						|
	 * using resize and may not all be in use)
 | 
						|
	 */
 | 
						|
	size_t length;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Construct a new etf buffer object
 | 
						|
	 * 
 | 
						|
	 * @param initial initial buffer size to allocate
 | 
						|
	 */
 | 
						|
	etf_buffer(size_t initial);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Destroy the etf buffer object
 | 
						|
	 */
 | 
						|
	~etf_buffer();
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief The etf_parser class can serialise and deserialise ETF (Erlang Term Format)
 | 
						|
 * into and out of an nlohmann::json object, so that layers above the websocket don't
 | 
						|
 * have to be any different for handling ETF.
 | 
						|
 */
 | 
						|
class DPP_EXPORT etf_parser {
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Current size of binary data
 | 
						|
	 */
 | 
						|
	size_t size;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Current offset into binary data
 | 
						|
	 */
 | 
						|
	size_t offset;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Pointer to binary ETF data to be decoded
 | 
						|
	 */
 | 
						|
	uint8_t* data;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Parse a single value, and if that value contains other
 | 
						|
	 * values (e.g. an array or map) then call itself recursively.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json JSON value from the ETF
 | 
						|
	 */
 | 
						|
	nlohmann::json inner_parse();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Read 8 bits of data from the buffer
 | 
						|
	 * 
 | 
						|
	 * @return uint8_t data retrieved
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	uint8_t read_8_bits();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Read 16 bits of data from the buffer
 | 
						|
	 * 
 | 
						|
	 * @return uint16_t data retrieved
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	uint16_t read_16_bits();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Read 32 bits of data from the buffer
 | 
						|
	 * 
 | 
						|
	 * @return uint32_t data retrieved
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	uint32_t read_32_bits();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Read 64 bits of data from the buffer
 | 
						|
	 * 
 | 
						|
	 * @return uint64_t data retrieved
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	uint64_t read_64_bits();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Read string data from the buffer
 | 
						|
	 *
 | 
						|
	 * @param length Length of string to retrieve 
 | 
						|
	 * @return const char* data retrieved
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	const char* read_string(uint32_t length);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Process an 'atom' value.
 | 
						|
	 * An atom is a "label" or constant value within the data,
 | 
						|
	 * such as a key name, nullptr, or false.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json process_atom(const char* atom, uint16_t length);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode an 'atom' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_atom();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a small 'atom' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_small_atom();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a small integer value (0-255).
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_small_integer();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode an integer value (-MAXINT -> MAXINT-1).
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_integer();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode an array of values.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json values converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_array(uint32_t length);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a list of values.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json values converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_list();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'tuple' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_tuple(uint32_t length);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a nil 'atom' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_nil();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a map (object) value.
 | 
						|
	 * Will recurse to evaluate each member variable.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json values converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_map();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a floating point numeric value.
 | 
						|
	 * (depreciated in erlang but still expected to be supported)
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_float();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a floating type numeric value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_new_float();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'bigint' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_bigint(uint32_t digits);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a small 'bigint' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_bigint_small();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a large 'bigint' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_bigint_large();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a binary value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_binary();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a string value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_string();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a string list value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_string_as_list();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'small tuple' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_tuple_small();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'large tuple' value.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_tuple_large();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a compressed value.
 | 
						|
	 * This is a zlib-compressed binary blob which contains another
 | 
						|
	 * ETF object.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_compressed();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'reference' value.
 | 
						|
	 * Erlang expects this to be supported, in practice Discord doesn't send these right now.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_reference();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'new reference' value.
 | 
						|
	 * Erlang expects this to be supported, in practice Discord doesn't send these right now.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_new_reference();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'port' value.
 | 
						|
	 * Erlang expects this to be supported, in practice Discord doesn't send these right now.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_port();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode a 'PID' value.
 | 
						|
	 * Erlang expects this to be supported, in practice Discord doesn't send these right now.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_pid();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Decode an 'export' value.
 | 
						|
	 * Erlang expects this to be supported, in practice Discord doesn't send these right now.
 | 
						|
	 * 
 | 
						|
	 * @return nlohmann::json value converted to JSON
 | 
						|
	 * @throw dpp::exception Data stream isn't long enough to fetch requested bits
 | 
						|
	 */
 | 
						|
	nlohmann::json decode_export();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Write to output buffer for creation of ETF from JSON
 | 
						|
	 * 
 | 
						|
	 * @param pk buffer struct
 | 
						|
	 * @param bytes byte buffer to write
 | 
						|
	 * @param l number of bytes to write
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void buffer_write(etf_buffer *pk, const char *bytes, size_t l);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append version number to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_version(etf_buffer *b);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append nil value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_nil(etf_buffer *b);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append false value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_false(etf_buffer *b);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append true value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_true(etf_buffer *b);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append small integer value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param d double to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_small_integer(etf_buffer *b, unsigned char d);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append integer value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param d integer to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_integer(etf_buffer *b, int32_t d);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append 64 bit integer value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param d integer to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_unsigned_long_long(etf_buffer *b, unsigned long long d);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append 64 bit integer value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param d integer to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_long_long(etf_buffer *b, long long d);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append double value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param f double to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_double(etf_buffer *b, double f);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append atom value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param bytes pointer to string to append
 | 
						|
	 * @param size size of string to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_atom(etf_buffer *b, const char *bytes, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append utf8 atom value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param bytes pointer to string to append
 | 
						|
	 * @param size size of string to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_atom_utf8(etf_buffer *b, const char *bytes, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append binary value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param bytes pointer to string to append
 | 
						|
	 * @param size size of string to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_binary(etf_buffer *b, const char *bytes, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append string value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param bytes pointer to string to append
 | 
						|
	 * @param size size of string to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_string(etf_buffer *b, const char *bytes, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append tuple value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param size size of value to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_tuple_header(etf_buffer *b, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append list terminator to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_nil_ext(etf_buffer *b);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append a list header value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param size size of values to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_list_header(etf_buffer *b, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Append a map header value to ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param b  buffer to append to
 | 
						|
	 * @param size size of values to append
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void append_map_header(etf_buffer *b, size_t size);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Build ETF buffer
 | 
						|
	 * 
 | 
						|
	 * @param j JSON object to build from
 | 
						|
	 * @param b Buffer to append to
 | 
						|
	 * @throw std::exception Buffer cannot be extended
 | 
						|
	 */
 | 
						|
	void inner_build(const nlohmann::json* j, etf_buffer* b);
 | 
						|
 | 
						|
public:
 | 
						|
	/**
 | 
						|
	 * @brief Construct a new etf parser object
 | 
						|
	 */
 | 
						|
	etf_parser();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Destroy the etf parser object
 | 
						|
	 */
 | 
						|
	~etf_parser();
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Convert ETF binary content to nlohmann::json
 | 
						|
	 * 
 | 
						|
	 * @param in Raw binary ETF data (generally from a websocket)
 | 
						|
	 * @return nlohmann::json JSON data for use in the library
 | 
						|
	 * @throw dpp::exception Malformed or otherwise invalid ETF content
 | 
						|
	 */
 | 
						|
	nlohmann::json parse(const std::string& in);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @brief Create ETF binary data from nlohmann::json
 | 
						|
	 * 
 | 
						|
	 * @param j JSON value to encode to ETF
 | 
						|
	 * @return std::string raw ETF data. Note that this can
 | 
						|
	 * and probably will contain null values, use std::string::data()
 | 
						|
	 * and std::string::size() to manipulate or send it.
 | 
						|
	 * @throw std::exception Not enough memory, or invalid data types/values
 | 
						|
	 */
 | 
						|
	std::string build(const nlohmann::json& j);
 | 
						|
};
 | 
						|
 | 
						|
};
 |