blob: 5a090855236a3c32adef2b474273e5ec93235656 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
// This source code is released into the public domain.
module;
#include <ucl.h>
export module nihil.ucl:object_cast;
import nihil.std;
import nihil.monad;
import :type;
import :object;
import :array;
namespace nihil::ucl {
//
// Ensure a UCL object is convertible to another type.
//
// Implementation for basic types.
template<datatype To>
struct convert_check
{
[[nodiscard]] auto check(::ucl_object_t const *from)
-> std::expected<void, type_mismatch>
{
auto from_type = static_cast<object_type>(::ucl_object_type(from));
auto to_type = To::ucl_type;
// Converting from anything to object is permitted.
if (to_type == object_type::object)
return {};
// Converting between two equal types is permitted.
if (from_type == to_type)
return {};
// Otherwise, this is an error.
return std::unexpected(type_mismatch(to_type, from_type));
}
};
// Implementation for array.
template<typename T>
struct convert_check<array<T>>
{
[[nodiscard]] auto check(::ucl_object_t const *from)
-> std::expected<void, type_mismatch>
{
using To = array<T>;
auto from_type = static_cast<object_type>(::ucl_object_type(from));
auto to_type = To::ucl_type;
// If the source type is not an array, this is an error.
if (from_type != object_type::array)
co_return std::unexpected(
type_mismatch(to_type, from_type));
for (std::size_t i = 0, size = ::ucl_array_size(from);
i < size; ++i) {
auto const *arr_obj = ::ucl_array_find_index(from, i);
co_await convert_check<typename To::value_type>{}
.check(arr_obj);
}
co_return {};
}
};
/*
* Convert a UCL object to another type.
*/
export template<datatype To>
auto object_cast(object const &from) -> std::expected<To, type_mismatch>
{
auto const *uobj = from.get_ucl_object();
co_await convert_check<To>{}.check(uobj);
co_return To(nihil::ucl::ref, uobj);
}
} // namespace nihil::ucl
|