// Copyright (c) Facebook, Inc. and its affiliates // SPDX-License-Identifier: MIT OR Apache-2.0 #pragma once #include #include #include "binary.hpp" #include "serde.hpp" // Maximum length supported in practice (e.g. Java). constexpr size_t BINCODE_MAX_LENGTH = (1ull << 31) - 1; namespace serde { class BincodeSerializer : public BinarySerializer { using Parent = BinarySerializer; public: BincodeSerializer() : Parent(SIZE_MAX) {} void serialize_f32(float value); void serialize_f64(double value); void serialize_len(size_t value); void serialize_variant_index(uint32_t value); static constexpr bool enforce_strict_map_ordering = false; }; class BincodeDeserializer : public BinaryDeserializer { using Parent = BinaryDeserializer; public: BincodeDeserializer(std::vector bytes) : Parent(std::move(bytes), SIZE_MAX) {} float deserialize_f32(); double deserialize_f64(); size_t deserialize_len(); uint32_t deserialize_variant_index(); static constexpr bool enforce_strict_map_ordering = false; }; // Native floats and doubles must be IEEE-754 values of the expected size. static_assert(std::numeric_limits::is_iec559); static_assert(std::numeric_limits::is_iec559); static_assert(sizeof(float) == sizeof(uint32_t)); static_assert(sizeof(double) == sizeof(uint64_t)); inline void BincodeSerializer::serialize_f32(float value) { Parent::serialize_u32(*reinterpret_cast(&value)); } inline void BincodeSerializer::serialize_f64(double value) { Parent::serialize_u64(*reinterpret_cast(&value)); } inline void BincodeSerializer::serialize_len(size_t value) { if (value > BINCODE_MAX_LENGTH) { throw serde::serialization_error("Length is too large"); } Parent::serialize_u64((uint64_t)value); } inline void BincodeSerializer::serialize_variant_index(uint32_t value) { Parent::serialize_u32((uint32_t)value); } inline float BincodeDeserializer::deserialize_f32() { auto value = Parent::deserialize_u32(); return *reinterpret_cast(&value); } inline double BincodeDeserializer::deserialize_f64() { auto value = Parent::deserialize_u64(); return *reinterpret_cast(&value); } inline size_t BincodeDeserializer::deserialize_len() { auto value = (size_t)Parent::deserialize_u64(); if (value > BINCODE_MAX_LENGTH) { throw serde::deserialization_error("Length is too large"); } return (size_t)value; } inline uint32_t BincodeDeserializer::deserialize_variant_index() { return Parent::deserialize_u32(); } } // end of namespace serde