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>
33template <
typename CharT,
typename Traits>
39template <std::
size_t N>
44template <std::
size_t N>
46 : std::integral_constant<std::size_t, N> {};
51 { T::from_json(value) } -> std::same_as<std::optional<T>>;
57 { value.to_json() } -> std::same_as<JSON>;
65 typename T::json_auto;
66} || !std::is_same_v<typename T::json_auto, std::false_type>;
72 typename T::value_type;
73 typename T::const_iterator;
74 { type.cbegin() } -> std::same_as<typename T::const_iterator>;
75 { type.cend() } -> std::same_as<typename T::const_iterator>;
84 typename T::value_type;
85 typename T::const_iterator;
87 { type.cbegin() } -> std::same_as<typename T::const_iterator>;
88 { type.cend() } -> std::same_as<typename T::const_iterator>;
91 std::is_same_v<typename T::key_type, JSON::String>;
96 requires {
typename T::reverse_iterator; };
102template <
typename U,
typename V>
109template <
typename... Ts>
115 typename std::tuple_size<std::remove_cvref_t<T>>::type;
116} && (std::tuple_size_v<std::remove_cvref_t<T>> == 1);
123 requires {
typename std::tuple_size<std::remove_cvref_t<T>>::type; } &&
124 (std::tuple_size_v<std::remove_cvref_t<T>> >= 2) &&
126 std::pair<std::tuple_element_t<0, std::remove_cvref_t<T>>,
127 std::tuple_element_t<1, std::remove_cvref_t<T>>>,
128 std::remove_cvref_t<T>>);
132template <json_auto_list_like T>
auto to_json(
const T &value) ->
JSON;
133template <json_auto_map_like T>
auto to_json(
const T &value) ->
JSON;
134template <
typename L,
typename R>
136template <json_auto_tuple_mono T>
auto to_json(
const T &value) ->
JSON;
137template <json_auto_tuple_poly T>
auto to_json(
const T &value) ->
JSON;
148 return value.to_json();
154 requires(json_auto_has_method_from<T>)
156 return T::from_json(value);
161 requires std::is_same_v<T, bool>
162auto from_json(
const JSON &value) -> std::optional<T> {
171 requires(std::is_integral_v<T> && !std::is_same_v<T, bool>)
175 if (value.is_integer() && std::in_range<T>(value.to_integer())) {
176 return static_cast<T
>(value.to_integer());
183 requires std::is_same_v<T, Decimal>
185 if (value.is_decimal()) {
186 return value.to_decimal();
195 requires std::is_same_v<T, JSON::Object::hash_type>
198 result.push_back(
JSON{
static_cast<std::size_t
>(hash.a >> 64)});
199 result.push_back(
JSON{
static_cast<std::size_t
>(hash.a)});
200 result.push_back(
JSON{
static_cast<std::size_t
>(hash.b >> 64)});
201 result.push_back(
JSON{
static_cast<std::size_t
>(hash.b)});
209 requires std::is_same_v<T, JSON::Object::hash_type>
211 if (!value.is_array() || value.size() != 4 || !value.at(0).is_integer() ||
212 !value.at(1).is_integer() || !value.at(2).is_integer() ||
213 !value.at(3).is_integer()) {
217 using uint128_type = JSON::Object::hash_type::type;
218 return T{(
static_cast<uint128_type
>(
219 static_cast<std::uint64_t
>(value.at(0).to_integer()))
221 static_cast<uint128_type
>(
222 static_cast<std::uint64_t
>(value.at(1).to_integer())),
223 (
static_cast<uint128_type
>(
224 static_cast<std::uint64_t
>(value.at(2).to_integer()))
226 static_cast<uint128_type
>(
227 static_cast<std::uint64_t
>(value.at(3).to_integer()))};
232 requires(std::constructible_from<JSON, T> &&
234 !std::is_same_v<T, unsigned long long>)
242 requires std::is_same_v<T, std::filesystem::file_time_type>
244 return JSON{
static_cast<std::int64_t
>(value.time_since_epoch().count())};
249 requires std::is_same_v<T, std::filesystem::file_time_type>
250auto from_json(
const JSON &value) -> std::optional<T> {
251 if (value.is_integer()) {
252 using file_time_type = std::filesystem::file_time_type;
253 return file_time_type{file_time_type::duration{
254 static_cast<file_time_type::duration::rep
>(value.to_integer())}};
261 requires(std::is_same_v<T, std::filesystem::path> &&
264 !std::is_convertible_v<T, std::string>)
266 return JSON{value.string()};
271 requires std::is_same_v<T, std::filesystem::path>
273 if (value.is_string()) {
274 return value.to_string();
284 if constexpr (BIT_COUNT <= 64) {
285 return JSON{
static_cast<std::int64_t
>(bitset.to_ullong())};
287 return JSON{bitset.to_string()};
296 if constexpr (BIT_COUNT <= 64) {
297 if (value.is_integer()) {
298 return T{
static_cast<unsigned long long>(value.to_integer())};
303 if (value.is_string()) {
304 return T{value.to_string()};
312 requires std::is_same_v<T, unsigned long long>
314 return JSON{
static_cast<std::int64_t
>(value)};
319 requires std::is_same_v<T, JSON>
328 if (value.is_string()) {
329 return value.to_string();
336 requires std::is_enum_v<T>
338 return to_json(
static_cast<std::underlying_type_t<T>
>(value));
343 requires std::is_enum_v<T>
345 if (value.is_integer()) {
346 return static_cast<T
>(value.to_integer());
353template <
typename T>
auto to_json(
const std::optional<T> &value) ->
JSON {
354 return value.has_value() ?
to_json(value.value()) :
JSON{
nullptr};
359 requires requires {
typename T::value_type; } &&
360 std::is_same_v<T, std::optional<typename T::value_type>>
361auto from_json(
const JSON &value) -> std::optional<T> {
362 if (value.is_null()) {
363 return std::optional<T>{
364 std::optional<typename T::value_type>{std::nullopt}};
367 if (!result.has_value()) {
376template <json_auto_list_like T>
377auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end)
381 for (
auto iterator = begin; iterator != end; ++iterator) {
382 result.push_back(
to_json(*iterator));
387 std::sort(result.as_array().begin(), result.as_array().end());
396template <json_auto_list_like T,
397 std::invocable<const typename T::value_type &> F>
398auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end,
399 const F &callback) ->
JSON {
402 for (
auto iterator = begin; iterator != end; ++iterator) {
403 result.push_back(callback(*iterator));
408 std::sort(result.as_array().begin(), result.as_array().end());
415template <json_auto_list_like T>
auto to_json(
const T &value) -> JSON {
416 return to_json<T>(value.cbegin(), value.cend());
421template <json_auto_list_like T,
422 std::invocable<const typename T::value_type &> F>
424 return to_json<T>(value.cbegin(), value.cend(), callback);
428template <json_auto_list_like T>
429auto from_json(
const JSON &value) -> std::optional<T> {
430 if (!value.is_array()) {
436 if constexpr (
requires { result.reserve(value.size()); }) {
437 result.reserve(value.size());
440 for (
const auto &item : value.as_array()) {
442 if (!subvalue.has_value()) {
446 if constexpr (
requires { result.insert(subvalue.value()); }) {
447 result.insert(std::move(subvalue).value());
449 result.push_back(std::move(subvalue).value());
458template <json_auto_list_like T>
461 const std::function<std::optional<typename T::value_type>(
const JSON &)>
462 &callback) -> std::optional<T> {
469 if constexpr (
requires { result.reserve(value.
size()); }) {
470 result.reserve(value.
size());
473 for (
const auto &item : value.
as_array()) {
474 auto subvalue{callback(item)};
475 if (!subvalue.has_value()) {
479 if constexpr (
requires { result.insert(subvalue.value()); }) {
480 result.insert(std::move(subvalue).value());
482 result.push_back(std::move(subvalue).value());
490template <json_auto_map_like T>
491auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end)
494 for (
auto iterator = begin; iterator != end; ++iterator) {
495 result.assign(iterator->first,
to_json(iterator->second));
502template <json_auto_map_like T>
auto to_json(
const T &value) ->
JSON {
503 return to_json<T>(value.cbegin(), value.cend());
508 std::invocable<const typename T::mapped_type &> F>
509auto to_json(
typename T::const_iterator begin,
typename T::const_iterator end,
510 const F &callback) ->
JSON {
512 for (
auto iterator = begin; iterator != end; ++iterator) {
513 result.assign(iterator->first, callback(iterator->second));
520template <json_auto_map_like T>
527 for (
const auto &item : value.
as_object()) {
529 if (!subvalue.has_value()) {
533 result.emplace(item.first, std::move(subvalue).value());
541template <json_auto_map_like T>
544 const std::function<std::optional<typename T::mapped_type>(
const JSON &)>
545 &callback) -> std::optional<T> {
551 for (
const auto &item : value.
as_object()) {
552 auto subvalue{callback(item.second)};
553 if (!subvalue.has_value()) {
557 result.emplace(item.first, std::move(subvalue).value());
564template <json_auto_map_like T,
565 std::invocable<const typename T::mapped_type &> F>
566auto to_json(
const T &value,
const F &callback) -> JSON {
567 return to_json<T>(value.cbegin(), value.cend(), callback);
572template <
typename L,
typename R>
575 tuple.push_back(
to_json(value.first));
576 tuple.push_back(
to_json(value.second));
582 requires JSONAutoIsPair<T>::value
583auto from_json(
const JSON &value) -> std::optional<T> {
590 if (!first.has_value() || !second.has_value()) {
594 return std::make_pair<typename T::first_type, typename T::second_type>(
595 std::move(first).value(), std::move(second).value());
600template <json_auto_tuple_mono T>
auto to_json(
const T &value) ->
JSON {
603 [&](
const auto &element) ->
auto { tuple.push_back(
to_json(element)); },
609template <json_auto_tuple_mono T>
616 if (!first.has_value()) {
620 return {std::move(first).value()};
624template <json_auto_tuple_poly T>
auto to_json(
const T &value) ->
JSON {
627 [&tuple](
const auto &...elements) ->
auto {
628 (tuple.push_back(
to_json(elements)), ...);
635template <
typename T, std::size_t... Indices>
636auto from_json_tuple_poly(
637 const JSON &value, [[maybe_unused]] std::index_sequence<Indices...> indices)
645template <json_auto_tuple_poly T>
647 if (!value.
is_array() || value.
size() != std::tuple_size_v<T>) {
652 return from_json_tuple_poly<T>(
653 value, std::make_index_sequence<std::tuple_size_v<T>>{});
655 }
catch (
const std::bad_optional_access &) {
665 result.push_back(
JSON{
static_cast<std::int64_t
>(value.index())});
667 [&result](
const auto &alternative) ->
auto {
668 result.push_back(
to_json(alternative));
675template <
typename T, std::
size_t Index = 0>
676auto from_json_variant_impl(
const JSON &data, std::size_t index)
677 -> std::optional<T> {
678 if constexpr (
Index >= std::variant_size_v<T>) {
681 if (
Index == index) {
683 if (result.has_value()) {
684 return T{std::in_place_index<Index>, std::move(result).value()};
689 return from_json_variant_impl<T, Index + 1>(data, index);
698 if (!value.
is_array() || value.
size() != 2 || !value.
at(0).is_integer()) {
702 const auto index{
static_cast<std::size_t
>(value.
at(0).to_integer())};
703 if (index >= std::variant_size_v<T>) {
706 return from_json_variant_impl<T>(value.
at(1), index);
SOURCEMETA_FORCEINLINE auto as_array() const noexcept -> const Array &
Definition json_value.h:737
SOURCEMETA_FORCEINLINE auto to_boolean() const noexcept -> bool
Definition json_value.h:619
SOURCEMETA_FORCEINLINE auto as_object() noexcept -> Object &
Definition json_value.h:782
static auto make_array() -> JSON
SOURCEMETA_FORCEINLINE auto is_object() const noexcept -> bool
Definition json_value.h:571
SOURCEMETA_FORCEINLINE auto at(const Array::size_type index) const -> const JSON &
Definition json_value.h:893
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:557
static auto size(const String &value) noexcept -> std::size_t
auto to_json(const T &value) -> JSON
Definition json_auto.h:147
auto from_json(const JSON &value) -> std::optional< T >
Definition json_auto.h:155
@ Index
A map of index labels carrying no RDF ranging over an object.
Definition jsonld_materialize.h:116