55
66namespace {
77auto value_from_json (const sourcemeta::core::JSON &wrapper)
8- -> sourcemeta::blaze::Value {
9- assert (wrapper.is_object ());
10- assert (wrapper.defines (" t" ));
11- assert (wrapper.defines (" v" ));
12- const auto &type{wrapper.at (" t" )};
13- const auto &value{wrapper.at (" v" )};
14- assert (type.is_integer () && type.is_positive ());
8+ -> std::optional<sourcemeta::blaze::Value> {
9+ if (!wrapper.is_object ()) {
10+ return std::nullopt ;
11+ }
12+
13+ const auto type{wrapper.try_at (" t" )};
14+ const auto value{wrapper.try_at (" v" )};
15+ if (!type || !value) {
16+ return std::nullopt ;
17+ }
18+
1519 using namespace sourcemeta ::blaze;
16- switch (type. to_integer ()) {
20+ switch (type-> to_integer ()) {
1721 // clang-format off
18- case 0 : return sourcemeta::core::from_json<ValueNone>(value);
19- case 1 : return sourcemeta::core::from_json<ValueJSON>(value);
20- case 2 : return sourcemeta::core::from_json<ValueSet>(value);
21- case 3 : return sourcemeta::core::from_json<ValueString>(value);
22- case 4 : return sourcemeta::core::from_json<ValueProperty>(value);
23- case 5 : return sourcemeta::core::from_json<ValueStrings>(value);
24- case 6 : return sourcemeta::core::from_json<ValueStringSet>(value);
25- case 7 : return sourcemeta::core::from_json<ValueTypes>(value);
26- case 8 : return sourcemeta::core::from_json<ValueType>(value);
27- case 9 : return sourcemeta::core::from_json<ValueRegex>(value);
28- case 10 : return sourcemeta::core::from_json<ValueUnsignedInteger>(value);
29- case 11 : return sourcemeta::core::from_json<ValueRange>(value);
30- case 12 : return sourcemeta::core::from_json<ValueBoolean>(value);
31- case 13 : return sourcemeta::core::from_json<ValueNamedIndexes>(value);
32- case 14 : return sourcemeta::core::from_json<ValueStringType>(value);
33- case 15 : return sourcemeta::core::from_json<ValueStringMap>(value);
34- case 16 : return sourcemeta::core::from_json<ValuePropertyFilter>(value);
35- case 17 : return sourcemeta::core::from_json<ValueIndexPair>(value);
36- case 18 : return sourcemeta::core::from_json<ValuePointer>(value);
37- case 19 : return sourcemeta::core::from_json<ValueTypedProperties>(value);
38- case 20 : return sourcemeta::core::from_json<ValueStringHashes>(value);
39- case 21 : return sourcemeta::core::from_json<ValueTypedHashes>(value);
22+ case 0 : return sourcemeta::core::from_json<ValueNone>(* value);
23+ case 1 : return sourcemeta::core::from_json<ValueJSON>(* value);
24+ case 2 : return sourcemeta::core::from_json<ValueSet>(* value);
25+ case 3 : return sourcemeta::core::from_json<ValueString>(* value);
26+ case 4 : return sourcemeta::core::from_json<ValueProperty>(* value);
27+ case 5 : return sourcemeta::core::from_json<ValueStrings>(* value);
28+ case 6 : return sourcemeta::core::from_json<ValueStringSet>(* value);
29+ case 7 : return sourcemeta::core::from_json<ValueTypes>(* value);
30+ case 8 : return sourcemeta::core::from_json<ValueType>(* value);
31+ case 9 : return sourcemeta::core::from_json<ValueRegex>(* value);
32+ case 10 : return sourcemeta::core::from_json<ValueUnsignedInteger>(* value);
33+ case 11 : return sourcemeta::core::from_json<ValueRange>(* value);
34+ case 12 : return sourcemeta::core::from_json<ValueBoolean>(* value);
35+ case 13 : return sourcemeta::core::from_json<ValueNamedIndexes>(* value);
36+ case 14 : return sourcemeta::core::from_json<ValueStringType>(* value);
37+ case 15 : return sourcemeta::core::from_json<ValueStringMap>(* value);
38+ case 16 : return sourcemeta::core::from_json<ValuePropertyFilter>(* value);
39+ case 17 : return sourcemeta::core::from_json<ValueIndexPair>(* value);
40+ case 18 : return sourcemeta::core::from_json<ValuePointer>(* value);
41+ case 19 : return sourcemeta::core::from_json<ValueTypedProperties>(* value);
42+ case 20 : return sourcemeta::core::from_json<ValueStringHashes>(* value);
43+ case 21 : return sourcemeta::core::from_json<ValueTypedHashes>(* value);
4044 // clang-format on
4145 default :
4246 assert (false );
@@ -45,44 +49,70 @@ auto value_from_json(const sourcemeta::core::JSON &wrapper)
4549}
4650
4751auto instructions_from_json (const sourcemeta::core::JSON &instructions)
48- -> sourcemeta::blaze::Instructions {
49- assert (instructions.is_array ());
52+ -> std::optional<sourcemeta::blaze::Instructions> {
53+ if (!instructions.is_array ()) {
54+ return std::nullopt ;
55+ }
56+
5057 sourcemeta::blaze::Instructions result;
5158 result.reserve (instructions.size ());
5259 for (const auto &instruction : instructions.as_array ()) {
53- assert (instruction.is_object ());
54- assert (instruction.defines (" t" ));
55- assert (instruction.defines (" s" ));
56- assert (instruction.defines (" i" ));
57- assert (instruction.defines (" k" ));
58- assert (instruction.defines (" r" ));
59- assert (instruction.defines (" v" ));
60- assert (instruction.defines (" c" ));
61- const auto &type{instruction.at (" t" )};
62- const auto &relative_schema_location{instruction.at (" s" )};
63- const auto &relative_instance_location{instruction.at (" i" )};
64- const auto &keyword_location{instruction.at (" k" )};
65- const auto &schema_resource{instruction.at (" r" )};
66- const auto &value{instruction.at (" v" )};
67- const auto &children{instruction.at (" c" )};
68- assert (type.is_integer () && type.is_positive ());
69- assert (relative_schema_location.is_string ());
70- assert (relative_instance_location.is_string ());
71- assert (keyword_location.is_string ());
72- assert (schema_resource.is_integer () && schema_resource.is_positive ());
73- assert (value.is_object ());
74- assert (children.is_array ());
60+ if (!instruction.is_object ()) {
61+ return std::nullopt ;
62+ }
63+
64+ const auto type{instruction.try_at (" t" )};
65+ const auto relative_schema_location{instruction.try_at (" s" )};
66+ const auto relative_instance_location{instruction.try_at (" i" )};
67+ const auto keyword_location{instruction.try_at (" k" )};
68+ const auto schema_resource{instruction.try_at (" r" )};
69+ const auto value{instruction.try_at (" v" )};
70+ const auto children{instruction.try_at (" c" )};
71+
72+ if (!type || !relative_schema_location || !relative_instance_location ||
73+ !keyword_location || !schema_resource || !value || !children) {
74+ return std::nullopt ;
75+ } else if (!type->is_positive () || !relative_schema_location->is_string () ||
76+ !relative_instance_location->is_string () ||
77+ !keyword_location->is_string () ||
78+ !schema_resource->is_positive () || !value->is_object () ||
79+ !children->is_array ()) {
80+ return std::nullopt ;
81+ }
82+
83+ auto type_result{
84+ sourcemeta::core::from_json<sourcemeta::blaze::InstructionIndex>(
85+ *type)};
86+ auto relative_schema_location_result{
87+ sourcemeta::core::from_json<sourcemeta::core::Pointer>(
88+ *relative_schema_location)};
89+ auto relative_instance_location_result{
90+ sourcemeta::core::from_json<sourcemeta::core::Pointer>(
91+ *relative_instance_location)};
92+ auto keyword_location_result{
93+ sourcemeta::core::from_json<std::string>(*keyword_location)};
94+ auto schema_resource_result{
95+ sourcemeta::core::from_json<std::size_t >(*schema_resource)};
96+ auto value_result{value_from_json (*value)};
97+ auto children_result{instructions_from_json (*children)};
98+
99+ if (!type_result.has_value () ||
100+ !relative_schema_location_result.has_value () ||
101+ !relative_instance_location_result.has_value () ||
102+ !keyword_location_result.has_value () ||
103+ !schema_resource_result.has_value () || !value_result.has_value () ||
104+ !children_result.has_value ()) {
105+ return std::nullopt ;
106+ }
75107
76108 // TODO: Maybe we should emplace here?
77- result.push_back (
78- {sourcemeta::core::from_json<sourcemeta::blaze::InstructionIndex>(type),
79- sourcemeta::core::from_json<sourcemeta::core::Pointer>(
80- relative_schema_location),
81- sourcemeta::core::from_json<sourcemeta::core::Pointer>(
82- relative_instance_location),
83- sourcemeta::core::from_json<std::string>(keyword_location),
84- sourcemeta::core::from_json<std::size_t >(schema_resource),
85- value_from_json (value), instructions_from_json (children)});
109+ result.push_back ({std::move (type_result).value (),
110+ std::move (relative_schema_location_result).value (),
111+ std::move (relative_instance_location_result).value (),
112+ std::move (keyword_location_result).value (),
113+ std::move (schema_resource_result).value (),
114+ std::move (value_result).value (),
115+ std::move (children_result).value ()});
86116 }
87117
88118 return result;
@@ -139,19 +169,26 @@ auto to_json(const Template &schema_template) -> sourcemeta::core::JSON {
139169 return result;
140170}
141171
142- auto from_json (const sourcemeta::core::JSON &json) -> Template {
143- assert (json.is_object ());
144- assert (json.defines (" instructions" ));
145- assert (json.defines (" dynamic" ));
146- assert (json.defines (" track" ));
147- const auto &instructions{json.at (" instructions" )};
148- const auto &dynamic{json.at (" dynamic" )};
149- const auto &track{json.at (" track" )};
150- assert (instructions.is_array ());
151- assert (dynamic.is_boolean ());
152- assert (track.is_boolean ());
153- return {instructions_from_json (instructions), dynamic.to_boolean (),
154- track.to_boolean ()};
172+ auto from_json (const sourcemeta::core::JSON &json) -> std::optional<Template> {
173+ if (!json.is_object ()) {
174+ return std::nullopt ;
175+ }
176+
177+ const auto instructions{json.try_at (" instructions" )};
178+ const auto dynamic{json.try_at (" dynamic" )};
179+ const auto track{json.try_at (" track" )};
180+ if (!instructions || !dynamic || !track) {
181+ return std::nullopt ;
182+ }
183+
184+ auto instructions_result{instructions_from_json (*instructions)};
185+ if (!instructions_result.has_value () || !dynamic->is_boolean () ||
186+ !track->is_boolean ()) {
187+ return std::nullopt ;
188+ }
189+
190+ return Template{std::move (instructions_result).value (), dynamic->to_boolean (),
191+ track->to_boolean ()};
155192}
156193
157194} // namespace sourcemeta::blaze
0 commit comments