fb-util-0.1.0.1: cpp/HsStruct.cpp
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "cpp/HsStruct.h"
#include "cpp/Marshallable.h"
/*
* HsJSON
*/
HsJSON::HsJSON(const folly::dynamic& value) {
switch (value.type()) {
case folly::dynamic::NULLT:
type = Type::Null;
break;
case folly::dynamic::BOOL:
type = Type::Bool;
integral = value.asBool();
break;
case folly::dynamic::INT64:
type = Type::Integral;
integral = value.asInt();
break;
case folly::dynamic::DOUBLE:
type = Type::Real;
real = value.asDouble();
break;
case folly::dynamic::STRING:
type = Type::String;
new (&string) HsString(value.asString());
break;
case folly::dynamic::ARRAY:
type = Type::Array;
{
std::vector<HsJSON> v;
v.reserve(value.size());
for (const folly::dynamic& i : value) {
v.emplace_back(i);
}
new (&array) HsArray<HsJSON>(std::move(v));
}
break;
case folly::dynamic::OBJECT:
type = Type::Object;
{
std::vector<HsString> keys;
std::vector<HsJSON> values;
keys.reserve(value.size());
values.reserve(value.size());
for (const auto& i : value.items()) {
keys.emplace_back(i.first.asString());
values.emplace_back(i.second);
}
new (&object) HsObject<HsJSON>(std::move(keys), std::move(values));
}
break;
}
}
folly::dynamic HsJSON::toDynamic() && {
switch (type) {
case Type::Null:
return folly::dynamic();
case Type::Bool:
return folly::dynamic(static_cast<bool>(integral));
case Type::Integral:
return folly::dynamic(integral);
case Type::Real:
return folly::dynamic(real);
case Type::String:
return folly::dynamic(std::move(string).toStdString());
case Type::Array: {
auto res = folly::dynamic::array();
auto end = std::make_move_iterator(array.end());
for (auto itr = std::make_move_iterator(array.begin()); itr != end;
itr++) {
res.push_back(std::move(*itr).toDynamic());
}
return res;
}
case Type::Object: {
folly::dynamic res = folly::dynamic::object;
auto items = std::move(object).take_items();
// Manual version of zipping 2 iterators together
auto key_itr = std::make_move_iterator(items.first.begin());
auto key_end = std::make_move_iterator(items.first.end());
auto val_itr = std::make_move_iterator(items.second.begin());
auto val_end = std::make_move_iterator(items.second.end());
while (key_itr != key_end && val_itr != val_end) {
res.insert(
std::move(*key_itr).toStdString(), std::move(*val_itr).toDynamic());
key_itr++;
val_itr++;
}
return res;
}
}
folly::assume_unreachable();
}
void HsJSON::construct(HsJSON&& other) {
DCHECK(this != &other);
type = other.type;
switch (type) {
case Type::Null:
break;
case Type::Bool:
case Type::Integral:
integral = other.integral;
break;
case Type::Real:
real = other.real;
break;
case Type::String:
new (&string) HsString(std::move(other.string));
break;
case Type::Array:
new (&array) HsArray<HsJSON>(std::move(other.array));
break;
case Type::Object:
new (&object) HsObject<HsJSON>(std::move(other.object));
break;
}
}
void HsJSON::destruct() {
if (type == Type::String) {
string.~HsString();
} else if (type == Type::Array) {
array.~HsArray();
} else if (type == Type::Object) {
object.~HsMap();
}
}
void ctorHsJSONNull(HsJSON* p) noexcept {
new (p) HsJSON();
}
void ctorHsJSONBool(HsJSON* p, bool b) noexcept {
new (p) HsJSON(b);
}
void ctorHsJSONInt(HsJSON* p, int64_t i) noexcept {
new (p) HsJSON(i);
}
void ctorHsJSONDouble(HsJSON* p, double d) noexcept {
new (p) HsJSON(d);
}
void ctorHsJSONString(HsJSON* p, HsString* txt) noexcept {
new (p) HsJSON(std::move(*txt));
}
void ctorHsJSONArray(HsJSON* p, HsArray<HsJSON>* a) noexcept {
new (p) HsJSON(std::move(*a));
}
void ctorHsJSONObject(HsJSON* p, HsObject<HsJSON>* o) noexcept {
new (p) HsJSON(std::move(*o));
}
/*
* HsObject
*/
extern "C" void common_hs_ctorHsObjectJSON(
HsObject<HsJSON>* p,
HsArray<HsString>* keys,
HsArray<HsJSON>* vals) {
new (p) HsObject<HsJSON>(
std::move(*keys).toStdVector(), std::move(*vals).toStdVector());
}
/*
* HsStringPiece
*/
HsStringPiece* newHsStringPiece(const char* p, size_t n) noexcept {
return new HsStringPiece(p, n);
}
void ctorHsStringPiece(HsRange<char>* ret, const char* p, size_t n) noexcept {
new (ret) HsStringPiece(p, n);
}
/*
* HsString
*/
HsString* newHsString(const char* p, size_t n) noexcept {
return new HsString(std::string(p, n));
}
void ctorHsString(HsString* ret, const char* p, size_t n) noexcept {
new (ret) HsString(std::string(p, n));
}
/*
* HsEither
*/
// HsEither<char,char> instead of HsEither<void,void> just to keep class
// definition happy.
void* newHsEither(HsEitherTag tag, void* val) {
return new DummyHsEither(tag, val);
}
HS_DEFINE_MARSHALLABLE(HsMaybeInt, HsMaybe<int64_t>);
HS_DEFINE_MARSHALLABLE(HsMaybeDouble, HsMaybe<double>);
HS_DEFINE_MARSHALLABLE(HsMaybeString, HsMaybe<HsString>);
HS_DEFINE_MARSHALLABLE(HsEitherStringInt, HsEither<HsString, int64_t>);
HS_DEFINE_MARSHALLABLE(HsEitherStringDouble, HsEither<HsString, double>);
HS_DEFINE_MARSHALLABLE(HsEitherStringString, HsEither<HsString, HsString>);
HS_DEFINE_MARSHALLABLE(
HsEitherStringArrayInt,
HsEither<HsString, HsArray<int64_t>>);
HS_DEFINE_MARSHALLABLE(
HsEitherStringArrayDouble,
HsEither<HsString, HsArray<double>>);
HS_DEFINE_MARSHALLABLE(
HsEitherStringArrayString,
HsEither<HsString, HsArray<HsString>>);
HS_DEFINE_MARSHALLABLE(HsString, HsString);
HS_DEFINE_MARSHALLABLE(HsStringPiece, HsStringPiece);
HS_DEFINE_MARSHALLABLE(HsArrayInt16, HsArray<int16_t>);
HS_DEFINE_MARSHALLABLE(HsArrayInt32, HsArray<int32_t>);
HS_DEFINE_MARSHALLABLE(HsArrayInt64, HsArray<int64_t>);
HS_DEFINE_MARSHALLABLE(HsArrayUInt8, HsArray<uint8_t>);
HS_DEFINE_MARSHALLABLE(HsArrayUInt16, HsArray<uint16_t>);
HS_DEFINE_MARSHALLABLE(HsArrayUInt32, HsArray<uint32_t>);
HS_DEFINE_MARSHALLABLE(HsArrayUInt64, HsArray<uint64_t>);
HS_DEFINE_MARSHALLABLE(HsArrayFloat, HsArray<float>);
HS_DEFINE_MARSHALLABLE(HsArrayDouble, HsArray<double>);
HS_DEFINE_MARSHALLABLE(HsArrayString, HsArray<HsString>);
HS_DEFINE_MARSHALLABLE(HsArrayStringPiece, HsArray<HsStringPiece>);
HS_DEFINE_MARSHALLABLE(HsArrayJSON, HsArray<HsJSON>);
HS_DEFINE_MARSHALLABLE(HsSetInt16, HsSet<int16_t>);
HS_DEFINE_MARSHALLABLE(HsSetInt32, HsSet<int32_t>);
HS_DEFINE_MARSHALLABLE(HsSetInt64, HsSet<int64_t>);
HS_DEFINE_MARSHALLABLE(HsSetUInt8, HsSet<uint8_t>);
HS_DEFINE_MARSHALLABLE(HsSetUInt16, HsSet<uint16_t>);
HS_DEFINE_MARSHALLABLE(HsSetUInt32, HsSet<uint32_t>);
HS_DEFINE_MARSHALLABLE(HsSetUInt64, HsSet<uint64_t>);
HS_DEFINE_MARSHALLABLE(HsSetFloat, HsSet<float>);
HS_DEFINE_MARSHALLABLE(HsSetDouble, HsSet<double>);
HS_DEFINE_MARSHALLABLE(HsSetString, HsSet<HsString>);
HS_DEFINE_MARSHALLABLE(HsSetJSON, HsSet<HsJSON>);
HS_DEFINE_MARSHALLABLE(HsMapIntInt, HsMap<int64_t, int64_t>);
HS_DEFINE_MARSHALLABLE(HsMapUInt8UInt8, HsMap<uint8_t, uint8_t>);
HS_DEFINE_MARSHALLABLE(HsMapUInt16UInt16, HsMap<uint16_t, uint16_t>);
HS_DEFINE_MARSHALLABLE(HsMapInt32Int32, HsMap<int32_t, int32_t>);
HS_DEFINE_MARSHALLABLE(HsMapInt32Double, HsMap<int32_t, double>);
HS_DEFINE_MARSHALLABLE(HsMapIntDouble, HsMap<int64_t, double>);
HS_DEFINE_MARSHALLABLE(HsMapIntString, HsMap<int64_t, HsString>);
HS_DEFINE_MARSHALLABLE(HsMapInt32String, HsMap<int32_t, HsString>);
HS_DEFINE_MARSHALLABLE(HsMapDoubleInt32, HsMap<double, int32_t>);
HS_DEFINE_MARSHALLABLE(HsMapStringInt32, HsMap<HsString, int32_t>);
HS_DEFINE_MARSHALLABLE(HsMapStringInt, HsMap<HsString, int64_t>);
HS_DEFINE_MARSHALLABLE(HsMapStringDouble, HsMap<HsString, double>);
HS_DEFINE_MARSHALLABLE(HsMapStringString, HsMap<HsString, HsString>);
HS_DEFINE_MARSHALLABLE(HsObjectJSON, HsObject<HsJSON>);
HS_DEFINE_MARSHALLABLE(HsJSON, HsJSON);
HS_OPTION_CPP(Bool, bool);
HS_OPTION_CPP(UInt8, uint8_t);
HS_OPTION_CPP(Int16, int16_t);
HS_OPTION_CPP(Int32, int32_t);
HS_OPTION_CPP(Int64, int64_t);
HS_OPTION_CPP(UInt32, uint32_t);
HS_OPTION_CPP(UInt64, uint64_t);
HS_OPTION_CPP(Float, float);
HS_OPTION_CPP(Double, double);
HS_OPTION_CPP(String, HsString);
HS_OPTION_CPP(StringView, HsStringPiece);
HS_OPTION_CPP(HsJSON, HsJSON);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(Int16, int16_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(Int32, int32_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(Int64, int64_t);
// std::vector<bool> doesn't guarantee contiguous memory layout,
// so use HsArray<uint8_t> to store one bool per byte
HS_DEFINE_ARRAY_CONSTRUCTIBLE(UInt8, uint8_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(UInt16, uint16_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(UInt32, uint32_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(UInt64, uint64_t);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(Float, float);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(Double, double);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(String, HsString);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(StringView, HsStringPiece);
HS_DEFINE_ARRAY_CONSTRUCTIBLE(HsJSON, HsJSON);
HS_DEFINE_MAP_CONSTRUCTIBLE(IntInt, int64_t, int64_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(UInt8UInt8, uint8_t, uint8_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(UInt16UInt16, uint16_t, uint16_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(Int32Int32, int32_t, int32_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(Int32Double, int32_t, double);
HS_DEFINE_MAP_CONSTRUCTIBLE(Int32String, int32_t, HsString);
HS_DEFINE_MAP_CONSTRUCTIBLE(DoubleInt32, double, int32_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(StringInt32, HsString, int32_t);
HS_DEFINE_MAP_CONSTRUCTIBLE(StringDouble, HsString, double);
HS_DEFINE_MAP_CONSTRUCTIBLE(StringString, HsString, HsString);
HS_DEFINE_SET_CONSTRUCTIBLE(Int16, int16_t);
HS_DEFINE_SET_CONSTRUCTIBLE(Int32, int32_t);
HS_DEFINE_SET_CONSTRUCTIBLE(Int64, int64_t);
HS_DEFINE_SET_CONSTRUCTIBLE(UInt8, uint8_t);
HS_DEFINE_SET_CONSTRUCTIBLE(UInt16, uint16_t);
HS_DEFINE_SET_CONSTRUCTIBLE(UInt32, uint32_t);
HS_DEFINE_SET_CONSTRUCTIBLE(UInt64, uint64_t);
HS_DEFINE_SET_CONSTRUCTIBLE(Float, float);
HS_DEFINE_SET_CONSTRUCTIBLE(Double, double);
HS_DEFINE_SET_CONSTRUCTIBLE(String, HsString);
HS_DEFINE_SET_CONSTRUCTIBLE(HsJSON, HsJSON);