36 namespace discord_core_internal {
42 template<
typename return_type>
inline return_type ntohsNew(return_type value) {
43 return static_cast<return_type
>(((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8));
46 template<
typename return_type>
inline return_type ntohlNew(return_type value) {
47 return static_cast<return_type
>(((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8) | ((value & 0x00FF0000) >> 8) | ((value & 0xFF000000) >> 24));
50 template<
typename return_type>
inline return_type ntohllNew(return_type value) {
51 return static_cast<return_type
>(((value & 0x00000000000000FFull) << 56) | ((value & 0x000000000000FF00ULL) << 40) | ((value & 0x0000000000FF0000ULL) << 24) |
52 ((value & 0x00000000FF000000ULL) << 8) | ((value & 0x000000FF00000000ULL) >> 8) | ((value & 0x0000FF0000000000ULL) >> 24) |
53 ((value & 0x00FF000000000000ULL) >> 40) | ((value & 0xFF00000000000000ULL) >> 56));
61 if constexpr (std::endian::native == std::endian::little) {
62 switch (
sizeof(return_type)) {
70 return ntohllNew(net);
85 template<
typename return_type,
typename value_type>
inline void storeBits(value_type* to, return_type num) {
86 const uint8_t byteSize{ 8 };
90 for (uint64_t x = 0; x <
sizeof(return_type); ++x) {
91 to[x] =
static_cast<value_type
>(num >> (byteSize * x));
100 inline explicit etf_parse_error(jsonifier::string_view message,
const std::source_location& location = std::source_location::current())
104 enum class etf_type : int8_t {
106 Small_Integer_Ext = 97,
114 Small_Atom_Ext = 115,
118 constexpr uint8_t formatVersion{ 131 };
121 class DiscordCoreAPI_Dll
etf_parser :
public jsonifier_internal::alloc_wrapper<uint8_t> {
124 using allocator = jsonifier_internal::alloc_wrapper<uint8_t>;
129 inline jsonifier::string_view_base<uint8_t>
parseEtfToJson(jsonifier::string_view_base<uint8_t> dataToParse) {
130 dataBuffer = dataToParse.data();
131 dataSize = dataToParse.size();
135 if (readBitsFromBuffer<uint8_t>() != formatVersion) {
136 throw etf_parse_error{
"etf_parser::parseEtfToJson() error: incorrect format version specified." };
138 singleValueETFToJson();
139 return { finalString.data(), currentSize };
143 jsonifier::string_base<uint8_t> finalString{};
144 const uint8_t* dataBuffer{};
145 uint64_t currentSize{};
153 if (offSet +
sizeof(return_type) > dataSize) {
154 throw etf_parse_error{
"etf_parser::readBitsFromBuffer() error: readBitsFromBuffer() past end of the buffer." };
156 return_type newValue{};
157 std::memcpy(&newValue, dataBuffer + offSet,
sizeof(return_type));
158 offSet +=
sizeof(return_type);
167 if (finalString.size() < currentSize + length) {
168 finalString.resize((finalString.size() + length) * 2);
170 std::memcpy(finalString.data() + currentSize, data, length);
171 currentSize += length;
178 writeCharacters(
"\"\"", 2);
181 if (offSet +
static_cast<uint64_t
>(length) > dataSize) {
182 throw etf_parse_error{
"erl_packer::writeCharactersFromBuffer() error: read past end of buffer." };
184 if (finalString.size() < currentSize + length) {
185 finalString.resize((finalString.size() + length) * 2);
187 const uint8_t* stringNew = dataBuffer + offSet;
189 if (length >= 3 && length <= 5) {
190 if (length == 3 && stringNew[0] ==
'n' && stringNew[1] ==
'i' && stringNew[2] ==
'l') {
191 writeCharacters(
"null", 4);
193 }
else if (length == 4 && stringNew[0] ==
'n' && stringNew[1] ==
'u' && stringNew[2] ==
'l' && stringNew[3] ==
'l') {
194 writeCharacters(
"null", 4);
196 }
else if (length == 4 && stringNew[0] ==
't' && stringNew[1] ==
'r' && stringNew[2] ==
'u' && stringNew[3] ==
'e') {
197 writeCharacters(
"true", 4);
199 }
else if (length == 5 && stringNew[0] ==
'f' && stringNew[1] ==
'a' && stringNew[2] ==
'l' && stringNew[3] ==
's' && stringNew[4] ==
'e') {
200 writeCharacters(
"false", 5);
204 writeCharacter<
'"'>();
205 for (uint64_t x = 0; x < length; ++x) {
206 switch (stringNew[x]) {
208 switch (stringNew[++x]) {
210 writeCharacter<
'\"'>();
213 writeCharacter<'\\'>();
214 writeCharacter<'\\'>();
217 writeCharacter<'\b'>();
220 writeCharacter<'\f'>();
223 writeCharacter<'\n'>();
226 writeCharacter<'\r'>();
229 writeCharacter<'\t'>();
232 writeCharacter(stringNew[x]);
239 writeCharacter<'\\'>();
240 writeCharacter<
'\"'>();
244 writeCharacter(stringNew[x]);
249 writeCharacter<
'"'>();
254 template<
typename value_type>
inline void writeCharacter(
const value_type value) {
255 if (finalString.size() < currentSize + 1) {
256 finalString.resize((finalString.size() + 1) * 2);
258 allocator::construct(&finalString[currentSize++],
static_cast<uint8_t
>(value));
264 if (finalString.size() < currentSize + 1) {
265 finalString.resize((finalString.size() + 1) * 2);
267 allocator::construct(&finalString[currentSize++],
static_cast<uint8_t
>(charToWrite));
272 if (offSet > dataSize) {
273 throw etf_parse_error{
"erl_packer::singleValueETFToJson() error: read past end of buffer." };
275 uint8_t type = readBitsFromBuffer<uint8_t>();
276 switch (
static_cast<etf_type
>(type)) {
277 case etf_type::New_Float_Ext: {
278 return parseNewFloatExt();
280 case etf_type::Small_Integer_Ext: {
281 return parseSmallIntegerExt();
283 case etf_type::Integer_Ext: {
284 return parseIntegerExt();
286 case etf_type::Atom_Ext: {
287 return parseAtomExt();
289 case etf_type::Nil_Ext: {
290 return parseNilExt();
292 case etf_type::String_Ext: {
293 return parseStringExt();
295 case etf_type::List_Ext: {
296 return parseListExt();
298 case etf_type::Binary_Ext: {
299 return parseBinaryExt();
301 case etf_type::Small_Big_Ext: {
302 return parseSmallBigExt();
304 case etf_type::Small_Atom_Ext: {
305 return parseSmallAtomExt();
307 case etf_type::Map_Ext: {
308 return parseMapExt();
311 throw etf_parse_error{
"etf_parser::singleValueETFToJson() error: unknown data type in etf, the type: " + jsonifier::toString(type) };
318 uint32_t length = readBitsFromBuffer<uint32_t>();
319 writeCharacter<'['>();
320 if (
static_cast<uint64_t
>(offSet) + length > dataSize) {
321 throw etf_parse_error{
"erl_packer::parseListExt() error: read past end of buffer." };
323 for (uint16_t x = 0; x < length; ++x) {
324 singleValueETFToJson();
325 if (x < length - 1) {
326 writeCharacter<','>();
329 readBitsFromBuffer<uint8_t>();
330 writeCharacter<']'>();
335 auto string = jsonifier::toString(readBitsFromBuffer<uint8_t>());
336 writeCharacters(
string.data(),
string.size());
341 auto string = jsonifier::toString(readBitsFromBuffer<uint32_t>());
342 writeCharacters(
string.data(),
string.size());
347 writeCharacter<
'"'>();
348 uint16_t length = readBitsFromBuffer<uint16_t>();
349 if (
static_cast<uint64_t
>(offSet) + length > dataSize) {
350 throw etf_parse_error{
"erl_packer::parseStringExt() error: read past end of buffer." };
352 for (uint16_t x = 0; x < length; ++x) {
353 parseSmallIntegerExt();
355 writeCharacter<
'"'>();
360 uint64_t value = readBitsFromBuffer<uint64_t>();
362 std::memcpy(&newDouble, &value,
sizeof(
double));
363 jsonifier::string valueNew = jsonifier::toString(newDouble);
364 writeCharacters(valueNew.data(), valueNew.size());
369 auto digits = readBitsFromBuffer<uint8_t>();
370 uint8_t sign = readBitsFromBuffer<uint8_t>();
373 throw etf_parse_error{
"etf_parser::parseSmallBigExt() error: big integers larger than 8 bytes not supported." };
378 for (uint8_t x = 0; x < digits; ++x) {
379 uint64_t digit = readBitsFromBuffer<uint8_t>();
380 value += digit * bits;
385 auto string = jsonifier::toString(value);
386 writeCharacters(
string.data(),
string.size());
388 auto string = jsonifier::toString(-(
static_cast<int64_t
>(value)));
389 writeCharacters(
string.data(),
string.size());
395 writeCharactersFromBuffer(readBitsFromBuffer<uint16_t>());
400 writeCharactersFromBuffer(readBitsFromBuffer<uint32_t>());
405 writeCharacters(
"[]", 2);
410 writeCharactersFromBuffer(readBitsFromBuffer<uint8_t>());
415 uint32_t length = readBitsFromBuffer<uint32_t>();
416 writeCharacter<
'{'>();
417 for (uint32_t x = 0; x < length; ++x) {
418 singleValueETFToJson();
419 writeCharacter<':'>();
420 singleValueETFToJson();
421 if (x < length - 1) {
422 writeCharacter<','>();
425 writeCharacter<'}'>();
435 inline etf_serialize_error(jsonifier::string_view message,
const std::source_location& location = std::source_location::current())
440 enum class json_type : uint8_t { null_t = 0,
object_t = 1,
array_t = 2, string_t = 3, float_t = 4, uint_t = 5, int_t = 6, bool_t = 7 };
443 template<
typename value_type>
444 concept array_t = jsonifier::concepts::range<value_type> && jsonifier::concepts::has_resize<std::unwrap_ref_decay_t<value_type>> &&
445 jsonifier::concepts::has_emplace_back<std::unwrap_ref_decay_t<value_type>> && jsonifier::concepts::vector_subscriptable<std::unwrap_ref_decay_t<value_type>> &&
446 requires(value_type&& data) {
typename value_type::value_type; };
449 template<
typename value_type>
451 typename value_type::mapped_type;
452 typename value_type::key_type;
453 } && jsonifier::concepts::range<value_type>;
455 class etf_serializer {
457 template<
typename value_type>
using allocator = jsonifier_internal::alloc_wrapper<value_type>;
458 using object_type = unordered_map<jsonifier::string, etf_serializer>;
459 using array_type = jsonifier::vector<etf_serializer>;
460 using string_type = jsonifier::string;
461 using float_type = double;
462 using uint_type = uint64_t;
463 using int_type = int64_t;
464 using bool_type = bool;
466 inline etf_serializer() =
default;
468 inline etf_serializer& operator=(etf_serializer&& data)
noexcept {
470 stringReal = std::move(data.stringReal);
472 data.type = json_type::null_t;
474 case json_type::object_t: {
475 objectValue = data.objectValue;
476 data.objectValue =
nullptr;
479 case json_type::array_t: {
480 arrayValue = data.arrayValue;
481 data.arrayValue =
nullptr;
484 case json_type::string_t: {
485 stringValue = data.stringValue;
486 data.stringValue =
nullptr;
489 case json_type::float_t: {
490 floatValue = data.floatValue;
491 data.floatValue =
nullptr;
494 case json_type::int_t: {
495 intValue = data.intValue;
496 data.intValue =
nullptr;
499 case json_type::uint_t: {
500 uintValue = data.uintValue;
501 data.uintValue =
nullptr;
504 case json_type::bool_t: {
505 boolValue = data.boolValue;
506 data.boolValue =
nullptr;
509 case json_type::null_t: {
516 inline etf_serializer(etf_serializer&& data)
noexcept {
517 *
this = std::move(data);
520 inline etf_serializer& operator=(
const etf_serializer& data) {
523 case json_type::object_t: {
524 setValue<json_type::object_t>(data.getObject());
527 case json_type::array_t: {
528 setValue<json_type::array_t>(data.getArray());
531 case json_type::string_t: {
532 setValue<json_type::string_t>(data.getString());
535 case json_type::float_t: {
536 setValue<json_type::float_t>(data.getFloat());
539 case json_type::uint_t: {
540 setValue<json_type::uint_t>(data.getUint());
543 case json_type::int_t: {
544 setValue<json_type::int_t>(data.getInt());
547 case json_type::bool_t: {
548 setValue<json_type::bool_t>(data.getBool());
551 case json_type::null_t: {
555 stringReal = data.stringReal;
559 inline etf_serializer(
const etf_serializer& data) {
563 template<
object_t value_type>
inline etf_serializer& operator=(value_type&& data)
noexcept {
564 setValue<json_type::object_t>(std::forward<value_type>(data));
568 template<
object_t value_type>
inline etf_serializer(value_type&& data)
noexcept {
569 *
this = std::forward<value_type>(data);
572 template<array_t value_type>
inline etf_serializer& operator=(value_type&& data)
noexcept {
573 setValue<json_type::array_t>(std::forward<value_type>(data));
577 template<array_t value_type>
inline etf_serializer(value_type&& data)
noexcept {
578 *
this = std::forward<value_type>(data);
581 template<jsonifier::concepts::
string_t value_type>
inline etf_serializer& operator=(value_type&& data)
noexcept {
582 setValue<json_type::string_t>(std::forward<value_type>(data));
586 template<jsonifier::concepts::
string_t value_type>
inline etf_serializer(value_type&& data)
noexcept {
587 *
this = std::forward<value_type>(data);
590 template<u
int_type str_length>
inline etf_serializer& operator=(
const char (&str)[str_length]) {
591 setValue<json_type::string_t>(str);
595 template<u
int_type str_length>
inline etf_serializer(
const char (&str)[str_length]) {
599 template<jsonifier::concepts::
float_t value_type>
inline etf_serializer& operator=(value_type&& data) {
600 setValue<json_type::float_t>(std::forward<value_type>(data));
604 template<jsonifier::concepts::
float_t value_type>
inline etf_serializer(value_type&& data) {
605 *
this = std::forward<value_type>(data);
608 template<jsonifier::concepts::
integer_t value_type>
inline etf_serializer& operator=(value_type&& data) {
609 if constexpr (jsonifier::concepts::signed_t<value_type>) {
610 setValue<json_type::int_t>(std::forward<value_type>(data));
611 }
else if constexpr (jsonifier::concepts::unsigned_t<value_type>) {
612 setValue<json_type::uint_t>(std::forward<value_type>(data));
617 template<jsonifier::concepts::
integer_t value_type>
inline etf_serializer(value_type&& data) {
618 *
this = std::forward<value_type>(data);
621 template<jsonifier::concepts::
bool_t value_type>
inline etf_serializer& operator=(value_type&& data) {
622 setValue<json_type::bool_t>(std::forward<value_type>(data));
626 template<jsonifier::concepts::
bool_t value_type>
inline etf_serializer(value_type&& data) {
627 *
this = std::forward<value_type>(data);
630 template<jsonifier::concepts::enum_t value_type>
inline etf_serializer& operator=(value_type&& data)
noexcept {
631 setValue<json_type::int_t>(
static_cast<int_type
>(std::forward<value_type>(data)));
635 template<jsonifier::concepts::enum_t value_type>
inline etf_serializer(value_type&& data)
noexcept {
636 *
this = std::forward<value_type>(data);
639 inline etf_serializer& operator=(
json_type data) {
641 case json_type::object_t: {
642 setValue<json_type::object_t>();
645 case json_type::array_t: {
646 setValue<json_type::array_t>();
649 case json_type::string_t: {
650 setValue<json_type::string_t>();
653 case json_type::float_t: {
654 setValue<json_type::float_t>();
657 case json_type::uint_t: {
658 setValue<json_type::uint_t>();
661 case json_type::int_t: {
662 setValue<json_type::int_t>();
665 case json_type::bool_t: {
666 setValue<json_type::bool_t>();
669 case json_type::null_t: {
670 setValue<json_type::null_t>();
685 inline operator jsonifier::string_base<uint8_t>() {
688 serializeJsonToEtfString(*
this);
692 etf_serializer& operator[](
typename object_type::key_type&& key) {
693 if (type == json_type::null_t) {
694 setValue<json_type::object_t>();
697 if (type == json_type::object_t) {
698 return getObject().operator[](std::forward<typename object_type::key_type>(key));
700 throw etf_serialize_error{
"Sorry, but this value's type is not object." };
703 inline etf_serializer& operator[](uint_type index) {
704 if (type == json_type::null_t) {
705 setValue<json_type::array_t>();
708 if (type == json_type::array_t) {
709 if (index >= getArray().size()) {
710 getArray().resize(index + 1);
713 return getArray().at(index);
715 throw etf_serialize_error{
"Sorry, but this value's type is not array." };
718 inline void emplaceBack(etf_serializer&& data) {
719 if (type == json_type::null_t) {
720 setValue<json_type::array_t>();
723 if (type == json_type::array_t) {
724 getArray().emplace_back(std::move(data));
727 throw etf_serialize_error{
"Sorry, but this value's type is not array." };
730 inline void emplaceBack(
const etf_serializer& other) {
731 if (type == json_type::null_t) {
732 setValue<json_type::array_t>();
735 if (type == json_type::array_t) {
736 getArray().emplace_back(other);
739 throw etf_serialize_error{
"Sorry, but this value's type is not array." };
742 inline bool_type operator==(
const etf_serializer& lhs)
const {
743 if (lhs.type != type) {
747 case json_type::object_t: {
748 if (!compareValues<json_type::object_t>(lhs)) {
753 case json_type::array_t: {
754 if (!compareValues<json_type::array_t>(lhs)) {
759 case json_type::string_t: {
760 if (!compareValues<json_type::string_t>(lhs)) {
765 case json_type::float_t: {
766 if (!compareValues<json_type::float_t>(lhs)) {
771 case json_type::uint_t: {
772 if (!compareValues<json_type::uint_t>(lhs)) {
777 case json_type::int_t: {
778 if (!compareValues<json_type::int_t>(lhs)) {
783 case json_type::bool_t: {
784 if (!compareValues<json_type::bool_t>(lhs)) {
789 case json_type::null_t: {
796 inline object_type& getObject()
const {
797 if (type != json_type::object_t) {
798 throw etf_serialize_error{
"Sorry, but this value's type is not object!" };
803 inline array_type& getArray()
const {
804 if (type != json_type::array_t) {
805 throw etf_serialize_error{
"Sorry, but this value's type is not array!" };
810 inline string_type& getString()
const {
811 if (type != json_type::string_t) {
812 throw etf_serialize_error{
"Sorry, but this value's type is not string!" };
817 inline float_type& getFloat()
const {
818 if (type != json_type::float_t) {
819 throw etf_serialize_error{
"Sorry, but this value's type is not float!" };
824 inline uint_type& getUint()
const {
825 if (type != json_type::uint_t) {
826 throw etf_serialize_error{
"Sorry, but this value's type is not uint!" };
831 inline int_type& getInt()
const {
832 if (type != json_type::int_t) {
833 throw etf_serialize_error{
"Sorry, but this value's type is not int!" };
838 inline bool_type& getBool()
const {
839 if (type != json_type::bool_t) {
840 throw etf_serialize_error{
"Sorry, but this value's type is not bool!" };
845 inline ~etf_serializer() {
850 jsonifier::string_base<uint8_t> stringReal{};
853 object_type* objectValue;
854 array_type* arrayValue;
855 string_type* stringValue;
856 float_type* floatValue;
857 uint_type* uintValue;
859 bool_type* boolValue;
862 inline void serializeJsonToEtfString(
const etf_serializer& dataToParse) {
863 switch (dataToParse.type) {
864 case json_type::object_t: {
865 return writeEtfObject(dataToParse.getObject());
867 case json_type::array_t: {
868 return writeEtfArray(dataToParse.getArray());
870 case json_type::string_t: {
871 return writeEtfString(dataToParse.getString());
873 case json_type::float_t: {
874 return writeEtfFloat(dataToParse.getFloat());
876 case json_type::uint_t: {
877 return writeEtfUint(dataToParse.getUint());
879 case json_type::int_t: {
880 return writeEtfInt(dataToParse.getInt());
882 case json_type::bool_t: {
883 return writeEtfBool(dataToParse.getBool());
885 case json_type::null_t: {
886 return writeEtfNull();
891 inline void writeEtfObject(
const object_type& jsonData) {
892 appendMapHeader(
static_cast<uint32_t
>(jsonData.size()));
893 for (
auto& [key, valueNew]: jsonData) {
894 appendBinaryExt(key,
static_cast<uint32_t
>(key.size()));
895 serializeJsonToEtfString(valueNew);
899 inline void writeEtfArray(
const array_type& jsonData) {
900 appendListHeader(
static_cast<uint32_t
>(jsonData.size()));
901 for (
auto& valueNew: jsonData) {
902 serializeJsonToEtfString(valueNew);
907 inline void writeEtfString(
const string_type& jsonData) {
908 appendBinaryExt(jsonData,
static_cast<uint32_t
>(jsonData.size()));
911 inline void writeEtfUint(
const uint_type jsonData) {
912 if (jsonData <= std::numeric_limits<uint8_t>::max() && jsonData >= std::numeric_limits<uint8_t>::min()) {
913 appendUint8(
static_cast<uint8_t
>(jsonData));
914 }
else if (jsonData <= std::numeric_limits<uint32_t>::max() && jsonData >= std::numeric_limits<uint32_t>::min()) {
915 appendUint32(
static_cast<uint32_t
>(jsonData));
917 appendUint64(jsonData);
921 inline void writeEtfInt(
const int_type jsonData) {
922 if (jsonData <= std::numeric_limits<int8_t>::max() && jsonData >= std::numeric_limits<int8_t>::min()) {
923 appendInt8(
static_cast<int8_t
>(jsonData));
924 }
else if (jsonData <= std::numeric_limits<int32_t>::max() && jsonData >= std::numeric_limits<int32_t>::min()) {
925 appendInt32(
static_cast<int32_t
>(jsonData));
927 appendInt64(jsonData);
931 inline void writeEtfFloat(
const float_type jsonData) {
932 appendNewFloatExt(jsonData);
935 inline void writeEtfBool(
const bool_type jsonData) {
936 appendBool(jsonData);
939 inline void writeEtfNull() {
943 template<
typename value_type>
inline void writeString(
const value_type* data, uint_type length) {
944 auto oldSize = stringReal.size();
945 stringReal.resize(oldSize + length);
946 std::memcpy(stringReal.data() + oldSize, data, length);
949 inline void appendBinaryExt(jsonifier::string_view bytes, uint32_t sizeNew) {
950 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::Binary_Ext) };
952 writeString(newBuffer, std::size(newBuffer));
953 writeString(bytes.data(), bytes.size());
956 inline void appendNewFloatExt(
const float_type newFloat) {
957 uint8_t newBuffer[9]{
static_cast<uint8_t
>(etf_type::New_Float_Ext) };
958 uint_type newValue{};
959 std::memcpy(&newValue, &newFloat,
sizeof(newFloat));
961 writeString(newBuffer, std::size(newBuffer));
964 inline void appendListHeader(
const uint32_t sizeNew) {
965 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::List_Ext) };
967 writeString(newBuffer, std::size(newBuffer));
970 inline void appendMapHeader(
const uint32_t sizeNew) {
971 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::Map_Ext) };
973 writeString(newBuffer, std::size(newBuffer));
976 inline void appendUint64(uint_type valueNew) {
977 uint8_t newBuffer[11]{
static_cast<uint8_t
>(etf_type::Small_Big_Ext) };
978 uint8_t encodedBytes{};
979 while (valueNew > 0) {
980 newBuffer[3 + encodedBytes] =
static_cast<uint8_t
>(valueNew & 0xFF);
984 newBuffer[1] = encodedBytes;
986 writeString(newBuffer, 1ull + 2ull +
static_cast<uint_type
>(encodedBytes));
989 inline void appendInt64(int_type valueNew) {
990 uint8_t newBuffer[11]{
static_cast<uint8_t
>(etf_type::Small_Big_Ext) };
991 uint8_t encodedBytes{};
992 while (valueNew > 0) {
993 newBuffer[3 + encodedBytes] =
static_cast<uint8_t
>(valueNew & 0xFF);
997 newBuffer[1] = encodedBytes;
1003 writeString(newBuffer, 1ull + 2ull +
static_cast<uint_type
>(encodedBytes));
1006 inline void appendUint32(
const uint32_t valueNew) {
1007 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::Integer_Ext) };
1009 writeString(newBuffer, std::size(newBuffer));
1012 inline void appendInt32(
const int32_t valueNew) {
1013 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::Integer_Ext) };
1015 writeString(newBuffer, std::size(newBuffer));
1018 inline void appendUint8(
const uint8_t valueNew) {
1019 uint8_t newBuffer[2]{
static_cast<uint8_t
>(etf_type::Small_Integer_Ext),
static_cast<uint8_t
>(valueNew) };
1020 writeString(newBuffer, std::size(newBuffer));
1023 inline void appendInt8(
const int8_t valueNew) {
1024 uint8_t newBuffer[2]{
static_cast<uint8_t
>(etf_type::Small_Integer_Ext),
static_cast<uint8_t
>(valueNew) };
1025 writeString(newBuffer, std::size(newBuffer));
1028 inline void appendBool(bool_type data) {
1030 uint8_t newBuffer[6]{
static_cast<uint8_t
>(etf_type::Small_Atom_Ext),
static_cast<uint8_t
>(4),
't',
'r',
'u',
'e' };
1031 writeString(newBuffer, std::size(newBuffer));
1034 uint8_t newBuffer[7]{
static_cast<uint8_t
>(etf_type::Small_Atom_Ext),
static_cast<uint8_t
>(5),
'f',
'a',
'l',
's',
'e' };
1035 writeString(newBuffer, std::size(newBuffer));
1039 inline void appendVersion() {
1040 uint8_t newBuffer[1]{
static_cast<uint8_t
>(formatVersion) };
1041 writeString(newBuffer, std::size(newBuffer));
1044 inline void appendNilExt() {
1045 uint8_t newBuffer[1]{
static_cast<uint8_t
>(etf_type::Nil_Ext) };
1046 writeString(newBuffer, std::size(newBuffer));
1049 inline void appendNil() {
1050 uint8_t newBuffer[5]{
static_cast<uint8_t
>(etf_type::Small_Atom_Ext),
static_cast<uint8_t
>(3),
'n',
'i',
'l' };
1051 writeString(newBuffer, std::size(newBuffer));
1054 template<
json_type typeNew,
typename... value_types>
inline void setValue(value_types&&... args) {
1057 if constexpr (typeNew == json_type::object_t) {
1058 allocator<object_type> alloc{};
1059 objectValue = alloc.allocate(1);
1060 alloc.construct(objectValue, std::forward<value_types>(args)...);
1061 }
else if constexpr (typeNew == json_type::array_t) {
1062 allocator<array_type> alloc{};
1063 arrayValue = alloc.allocate(1);
1064 alloc.construct(arrayValue, std::forward<value_types>(args)...);
1065 }
else if constexpr (typeNew == json_type::string_t) {
1066 allocator<string_type> alloc{};
1067 stringValue = alloc.allocate(1);
1068 alloc.construct(stringValue, std::forward<value_types>(args)...);
1069 }
else if constexpr (typeNew == json_type::float_t) {
1070 allocator<float_type> alloc{};
1071 floatValue = alloc.allocate(1);
1072 alloc.construct(floatValue, std::forward<value_types>(args)...);
1073 }
else if constexpr (typeNew == json_type::uint_t) {
1074 allocator<uint_type> alloc{};
1075 uintValue = alloc.allocate(1);
1076 alloc.construct(uintValue, std::forward<value_types>(args)...);
1077 }
else if constexpr (typeNew == json_type::int_t) {
1078 allocator<int_type> alloc{};
1079 intValue = alloc.allocate(1);
1080 alloc.construct(intValue, std::forward<value_types>(args)...);
1081 }
else if constexpr (typeNew == json_type::bool_t) {
1082 allocator<bool_type> alloc{};
1083 boolValue = alloc.allocate(1);
1084 alloc.construct(boolValue, std::forward<value_types>(args)...);
1088 template<json_type typeNew>
inline void destroy() {
1089 if constexpr (typeNew == json_type::object_t) {
1090 allocator<object_type> alloc{};
1091 alloc.destroy(objectValue);
1092 alloc.deallocate(
static_cast<object_type*
>(objectValue), 1);
1093 objectValue =
nullptr;
1094 }
else if constexpr (typeNew == json_type::array_t) {
1095 allocator<array_type> alloc{};
1096 alloc.destroy(arrayValue);
1097 alloc.deallocate(
static_cast<array_type*
>(arrayValue), 1);
1098 arrayValue =
nullptr;
1099 }
else if constexpr (typeNew == json_type::string_t) {
1100 allocator<string_type> alloc{};
1101 alloc.destroy(stringValue);
1102 alloc.deallocate(
static_cast<string_type*
>(stringValue), 1);
1103 stringValue =
nullptr;
1104 }
else if constexpr (typeNew == json_type::float_t) {
1105 allocator<float_type> alloc{};
1106 alloc.destroy(floatValue);
1107 alloc.deallocate(
static_cast<float_type*
>(floatValue), 1);
1108 floatValue =
nullptr;
1109 }
else if constexpr (typeNew == json_type::uint_t) {
1110 allocator<uint_type> alloc{};
1111 alloc.destroy(uintValue);
1112 alloc.deallocate(
static_cast<uint_type*
>(uintValue), 1);
1113 uintValue =
nullptr;
1114 }
else if constexpr (typeNew == json_type::int_t) {
1115 allocator<int_type> alloc{};
1116 alloc.destroy(intValue);
1117 alloc.deallocate(
static_cast<int_type*
>(intValue), 1);
1119 }
else if constexpr (typeNew == json_type::bool_t) {
1120 allocator<bool_type> alloc{};
1121 alloc.destroy(boolValue);
1122 alloc.deallocate(
static_cast<bool_type*
>(boolValue), 1);
1123 boolValue =
nullptr;
1127 template<json_type typeNew>
inline bool_type compareValues(
const etf_serializer& other)
const {
1128 if constexpr (typeNew == json_type::object_t) {
1129 return *objectValue == *other.objectValue;
1130 }
else if constexpr (typeNew == json_type::array_t) {
1131 return *arrayValue == *other.arrayValue;
1132 }
else if constexpr (typeNew == json_type::string_t) {
1133 return *stringValue == *other.stringValue;
1134 }
else if constexpr (typeNew == json_type::float_t) {
1135 return *floatValue == *other.floatValue;
1136 }
else if constexpr (typeNew == json_type::uint_t) {
1137 return *uintValue == *other.uintValue;
1138 }
else if constexpr (typeNew == json_type::int_t) {
1139 return *intValue == *other.intValue;
1140 }
else if constexpr (typeNew == json_type::bool_t) {
1141 return *boolValue == *other.boolValue;
1147 inline void destroyImpl() {
1149 case json_type::object_t: {
1150 destroy<json_type::object_t>();
1153 case json_type::array_t: {
1154 destroy<json_type::array_t>();
1157 case json_type::string_t: {
1158 destroy<json_type::string_t>();
1161 case json_type::float_t: {
1162 destroy<json_type::float_t>();
1165 case json_type::uint_t: {
1166 destroy<json_type::uint_t>();
1169 case json_type::int_t: {
1170 destroy<json_type::int_t>();
1173 case json_type::bool_t: {
1174 destroy<json_type::bool_t>();
1177 case json_type::null_t: {
1184 type = json_type::null_t;
Class for parsing etf data into json format.
void parseNilExt()
Parse etf data representing a nil value and convert to json null.
void parseStringExt()
Parse etf data representing a string and convert to json string.
jsonifier::string_view_base< uint8_t > parseEtfToJson(jsonifier::string_view_base< uint8_t > dataToParse)
Parse etf data to json format.
void parseIntegerExt()
Parse etf data representing an integer and convert to json number.
void parseListExt()
Parse etf data representing a list and convert to json array.
void writeCharactersFromBuffer(uint32_t length)
Write characters from the buffer to the final json string.
void writeCharacter()
Write a character to the final json string.
void writeCharacters(const char *data, uint64_t length)
Write characters to the final json string.
void parseBinaryExt()
Parse etf data representing a binary and convert to json string.
void singleValueETFToJson()
Parse a single etf value and convert to json.
void writeCharacter(const value_type value)
Write a character to the final json string.
void parseSmallAtomExt()
Parse etf data representing a small atom and convert to json string.
void parseSmallIntegerExt()
Parse etf data representing a small integer and convert to json number.
void parseAtomExt()
Parse etf data representing an atom and convert to json string.
return_type readBitsFromBuffer()
Read bits from the data buffer and convert to return_type.
void parseMapExt()
Parse etf data representing a map and convert to json object.
void parseNewFloatExt()
Parse etf data representing a new float and convert to json number.
void parseSmallBigExt()
Parse etf data representing a small big integer and convert to json number.
A websocket client, for communication via a tcp-connection.
Concept for array types excluding etf_serializer.
Concept for object (associative container) types excluding etf_serializer.
json_type
Enumeration for different json value types.
void storeBits(value_type *to, return_type num)
Stores the bits of a number into a character array.
return_type reverseByteOrder(return_type net)
Reverses the byte order of a value if needed, based on the endianness.
The main namespace for the forward-facing interfaces.
An exception class derived from std::runtime_error for dca-related exceptions.
Exception class for etf parsing errors.
etf_parse_error(jsonifier::string_view message, const std::source_location &location=std::source_location::current())
Constructs an etf_parse_error instance with a message and source location.
Custom exception class for etf serialization errors.
etf_serialize_error(jsonifier::string_view message, const std::source_location &location=std::source_location::current())
Constructor for etf_serialize_error.