1#ifndef SOURCEMETA_CORE_JSON_AUTO_H_
2#define SOURCEMETA_CORE_JSON_AUTO_H_
4#include <sourcemeta/core/json_value.h>
19namespace sourcemeta::core {
27template <
typename CharT,
typename Traits,
typename Alloc>
34template <
typename CharT,
typename Traits>
40template <std::
size_t N>
45template <std::
size_t N>
47 : std::integral_constant<std::size_t, N> {};
52 { T::from_json(value) } -> std::same_as<std::optional<T>>;
58 { value.to_json() } -> std::same_as<JSON>;
66 typename T::json_auto;
67} || !std::is_same_v<typename T::json_auto, std::false_type>;
73 typename T::value_type;
74 typename T::const_iterator;
75 { type.cbegin() } -> std::same_as<typename T::const_iterator>;
76 { type.cend() } -> std::same_as<typename T::const_iterator>;
86 typename T::value_type;
87 typename T::const_iterator;
89 { type.cbegin() } -> std::same_as<typename T::const_iterator>;
90 { type.cend() } -> std::same_as<typename T::const_iterator>;
93 std::is_same_v<typename T::key_type, JSON::String>;
98 requires {
typename T::reverse_iterator; };
104template <
typename U,
typename V>
111template <
typename... Ts>
117 typename std::tuple_size<std::remove_cvref_t<T>>::type;
118} && (std::tuple_size_v<std::remove_cvref_t<T>> == 1);
125 requires {
typename std::tuple_size<std::remove_cvref_t<T>>::type; } &&
126 (std::tuple_size_v<std::remove_cvref_t<T>> >= 2) &&
128 std::pair<std::tuple_element_t<0, std::remove_cvref_t<T>>,
129 std::tuple_element_t<1, std::remove_cvref_t<T>>>,
130 std::remove_cvref_t<T>>);
134template <json_auto_list_like T>
auto to_json(
const T &value) ->
JSON;
135template <json_auto_map_like T>
auto to_json(
const T &value) ->
JSON;
136template <
typename L,
typename R>
138template <json_auto_tuple_mono T>
auto to_json(
const T &value) ->
JSON;
139template <json_auto_tuple_poly T>
auto to_json(
const T &value) ->
JSON;
150 return value.to_json();
156 requires(json_auto_has_method_from<T>)
158 return T::from_json(value);
163 requires std::is_same_v<T, bool>
164auto from_json(
const JSON &value) -> std::optional<T> {
174 requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
178 if (value.is_integer() && std::in_range<T>(value.to_integer())) {
179 return static_cast<T
>(value.to_integer());
187 requires std::is_same_v<T, Decimal>
189 if (value.is_decimal()) {
190 return value.to_decimal();
200 requires std::is_same_v<T, JSON::Object::hash_type>
203 result.push_back(
JSON{
static_cast<std::size_t
>(hash.a >> 64)});
204 result.push_back(
JSON{
static_cast<std::size_t
>(hash.a)});
205 result.push_back(
JSON{
static_cast<std::size_t
>(hash.b >> 64)});
206 result.push_back(
JSON{
static_cast<std::size_t
>(hash.b)});
214 requires std::is_same_v<T, JSON::Object::hash_type>
216 if (!value.is_array() || value.size() != 4 || !value.at(0).is_integer() ||
217 !value.at(1).is_integer() || !value.at(2).is_integer() ||
218 !value.at(3).is_integer()) {
222 using uint128_type = JSON::Object::hash_type::type;
223 return T{(
static_cast<uint128_type
>(
224 static_cast<std::uint64_t
>(value.at(0).to_integer()))
226 static_cast<uint128_type
>(
227 static_cast<std::uint64_t
>(value.at(1).to_integer())),
228 (
static_cast<uint128_type
>(
229 static_cast<std::uint64_t
>(value.at(2).to_integer()))
231 static_cast<uint128_type
>(
232 static_cast<std::uint64_t
>(value.at(3).to_integer()))};
237 requires(std::constructible_from<JSON, T> &&
239 !std::is_same_v<T, unsigned long long>)
247 requires std::is_same_v<T, std::filesystem::file_time_type>
249 return JSON{
static_cast<std::int64_t
>(value.time_since_epoch().count())};
254 requires std::is_same_v<T, std::filesystem::file_time_type>
255auto from_json(
const JSON &value) -> std::optional<T> {
256 if (value.is_integer()) {
257 using file_time_type = std::filesystem::file_time_type;
258 return file_time_type{file_time_type::duration{
259 static_cast<file_time_type::duration::rep
>(value.to_integer())}};
267 requires(std::is_same_v<T, std::filesystem::path> &&
270 !std::is_convertible_v<T, std::string>)
272 return JSON{value.string()};
277 requires std::is_same_v<T, std::filesystem::path>
279 if (value.is_string()) {
280 return value.to_string();
291 if constexpr (N <= 64) {
292 return JSON{
static_cast<std::int64_t
>(bitset.to_ullong())};
294 return JSON{bitset.to_string()};
303 if constexpr (N <= 64) {
304 if (value.is_integer()) {
305 return T{
static_cast<unsigned long long>(value.to_integer())};
310 if (value.is_string()) {
311 return T{value.to_string()};
320 requires std::is_same_v<T, unsigned long long>
322 return JSON{
static_cast<std::int64_t
>(value)};
327 requires std::is_same_v<T, JSON>
336 if (value.is_string()) {
337 return value.to_string();
345 requires std::is_enum_v<T>
347 return to_json(
static_cast<std::underlying_type_t<T>
>(value));
352 requires std::is_enum_v<T>
354 if (value.is_integer()) {
355 return static_cast<T
>(value.to_integer());
363template <
typename T>
auto to_json(
const std::optional<T> &value) ->
JSON {
364 return value.has_value() ?
to_json(value.value()) :
JSON{
nullptr};
369 requires requires {
typename T::value_type; } &&
370 std::is_same_v<T, std::optional<typename T::value_type>>
371auto from_json(
const JSON &value) -> std::optional<T> {
372 if (value.is_null()) {
373 return std::optional<T>{
374 std::optional<typename T::value_type>{std::nullopt}};
377 if (!result.has_value()) {
387template <json_auto_list_like T>
388auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end)
392 for (
auto iterator = begin; iterator != end; ++iterator) {
393 result.push_back(
to_json(*iterator));
398 std::sort(result.as_array().begin(), result.as_array().end());
407template <json_auto_list_like T,
408 std::invocable<const typename T::value_type &> F>
409auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end,
410 const F &callback) ->
JSON {
413 for (
auto iterator = begin; iterator != end; ++iterator) {
414 result.push_back(callback(*iterator));
419 std::sort(result.as_array().begin(), result.as_array().end());
426template <json_auto_list_like T>
auto to_json(
const T &value) -> JSON {
427 return to_json<T>(value.cbegin(), value.cend());
432template <json_auto_list_like T,
433 std::invocable<const typename T::value_type &> F>
435 return to_json<T>(value.cbegin(), value.cend(), callback);
439template <json_auto_list_like T>
440auto from_json(
const JSON &value) -> std::optional<T> {
441 if (!value.is_array()) {
447 if constexpr (
requires { result.reserve(value.size()); }) {
448 result.reserve(value.size());
451 for (
const auto &item : value.as_array()) {
453 if (!subvalue.has_value()) {
457 if constexpr (
requires { result.insert(subvalue.value()); }) {
458 result.insert(std::move(subvalue).value());
460 result.push_back(std::move(subvalue).value());
469template <json_auto_list_like T>
472 const std::function<std::optional<typename T::value_type>(
const JSON &)>
473 &callback) -> std::optional<T> {
480 if constexpr (
requires { result.reserve(value.
size()); }) {
481 result.reserve(value.
size());
484 for (
const auto &item : value.
as_array()) {
485 auto subvalue{callback(item)};
486 if (!subvalue.has_value()) {
490 if constexpr (
requires { result.insert(subvalue.value()); }) {
491 result.insert(std::move(subvalue).value());
493 result.push_back(std::move(subvalue).value());
501template <json_auto_map_like T>
502auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end)
505 for (
auto iterator = begin; iterator != end; ++iterator) {
506 result.assign(iterator->first,
to_json(iterator->second));
513template <json_auto_map_like T>
auto to_json(
const T &value) ->
JSON {
514 return to_json<T>(value.cbegin(), value.cend());
519 std::invocable<const typename T::mapped_type &> F>
520auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end,
521 const F &callback) ->
JSON {
523 for (
auto iterator = begin; iterator != end; ++iterator) {
524 result.assign(iterator->first, callback(iterator->second));
531template <json_auto_map_like T>
538 for (
const auto &item : value.
as_object()) {
540 if (!subvalue.has_value()) {
544 result.emplace(item.first, std::move(subvalue).value());
552template <json_auto_map_like T>
555 const std::function<std::optional<typename T::mapped_type>(
const JSON &)>
556 &callback) -> std::optional<T> {
562 for (
const auto &item : value.
as_object()) {
563 auto subvalue{callback(item.second)};
564 if (!subvalue.has_value()) {
568 result.emplace(item.first, std::move(subvalue).value());
575template <json_auto_map_like T,
576 std::invocable<const typename T::mapped_type &> F>
577auto to_json(
const T &value,
const F &callback) -> JSON {
578 return to_json<T>(value.cbegin(), value.cend(), callback);
583template <
typename L,
typename R>
586 tuple.push_back(
to_json(value.first));
587 tuple.push_back(
to_json(value.second));
593 requires json_auto_is_pair<T>::value
594auto from_json(
const JSON &value) -> std::optional<T> {
601 if (!first.has_value() || !second.has_value()) {
605 return std::make_pair<typename T::first_type, typename T::second_type>(
606 std::move(first).value(), std::move(second).value());
611template <json_auto_tuple_mono T>
auto to_json(
const T &value) ->
JSON {
614 [&](
const auto &element) ->
auto { tuple.push_back(
to_json(element)); },
620template <json_auto_tuple_mono T>
627 if (!first.has_value()) {
631 return {std::move(first).value()};
635template <json_auto_tuple_poly T>
auto to_json(
const T &value) ->
JSON {
638 [&tuple](
const auto &...elements) ->
auto {
639 (tuple.push_back(
to_json(elements)), ...);
646template <
typename T, std::size_t... Indices>
647auto from_json_tuple_poly(
const JSON &value, std::index_sequence<Indices...>)
655template <json_auto_tuple_poly T>
657 if (!value.
is_array() || value.
size() != std::tuple_size_v<T>) {
662 return from_json_tuple_poly<T>(
663 value, std::make_index_sequence<std::tuple_size_v<T>>{});
665 }
catch (
const std::bad_optional_access &) {
675 result.push_back(
JSON{
static_cast<std::int64_t
>(value.index())});
677 [&result](
const auto &alternative) ->
auto {
678 result.push_back(
to_json(alternative));
685template <
typename T, std::
size_t Index = 0>
686auto from_json_variant_impl(
const JSON &data, std::size_t index)
687 -> std::optional<T> {
688 if constexpr (
Index >= std::variant_size_v<T>) {
691 if (
Index == index) {
693 if (result.has_value()) {
694 return T{std::in_place_index<Index>, std::move(result).value()};
699 return from_json_variant_impl<T, Index + 1>(data, index);
709 if (!value.
is_array() || value.
size() != 2 || !value.
at(0).is_integer()) {
713 const auto index{
static_cast<std::size_t
>(value.
at(0).to_integer())};
714 if (index >= std::variant_size_v<T>) {
717 return from_json_variant_impl<T>(value.
at(1), index);
SOURCEMETA_FORCEINLINE auto as_array() const noexcept -> const Array &
Definition json_value.h:745
SOURCEMETA_FORCEINLINE auto to_boolean() const noexcept -> bool
Definition json_value.h:626
SOURCEMETA_FORCEINLINE auto as_object() noexcept -> Object &
Definition json_value.h:791
static auto make_array() -> JSON
SOURCEMETA_FORCEINLINE auto is_object() const noexcept -> bool
Definition json_value.h:576
static auto make_object() -> JSON
SOURCEMETA_FORCEINLINE auto is_boolean() const noexcept -> bool
Definition json_value.h:433
SOURCEMETA_FORCEINLINE auto is_array() const noexcept -> bool
Definition json_value.h:561
static auto size(const String &value) noexcept -> std::size_t
SOURCEMETA_FORCEINLINE auto at(const typename Array::size_type index) const -> const JSON &
Definition json_value.h:904
auto to_json(const T &value) -> JSON
Definition json_auto.h:149
auto from_json(const JSON &value) -> std::optional< T >
Definition json_auto.h:157
@ Index
A map of index labels carrying no RDF ranging over an object.
Definition jsonld_materialize.h:116