|
@@ -80,101 +80,111 @@ namespace InvercargillJson {
|
|
|
|
|
|
|
|
node = new Json.Node (Json.NodeType.VALUE);
|
|
node = new Json.Node (Json.NodeType.VALUE);
|
|
|
|
|
|
|
|
- // For ValueElement scalars, read the underlying GValue directly
|
|
|
|
|
- // through a dedicated helper instead of inlining every branch
|
|
|
|
|
- // here: the fully inlined version produced a single ~13KB
|
|
|
|
|
- // function whose optimised stack-slot reuse read a stale cached
|
|
|
|
|
- // GValue pointer on some layouts (deterministic SIGSEGV in the
|
|
|
|
|
- // double/int64 paths during Statum slot signing). Keeping the
|
|
|
|
|
- // scalar dispatch out of line sidesteps that codegen bug.
|
|
|
|
|
- if (element is Invercargill.ValueElement) {
|
|
|
|
|
- if (set_node_from_value(node, ((Invercargill.ValueElement) element).get_value())) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- // Non-fundamental held types (DateTime, BinaryData, objects,
|
|
|
|
|
- // ...) fall through to the dispatch below.
|
|
|
|
|
|
|
+ // Everything scalar lives in out-of-line helpers: the fully
|
|
|
|
|
+ // inlined version produced a single ~13KB function whose
|
|
|
|
|
+ // optimised stack-slot reuse read stale pointers on some
|
|
|
|
|
+ // layouts (intermittent SIGSEGV during Statum slot signing —
|
|
|
|
|
+ // first the double/int64 GValue paths, then the generic
|
|
|
|
|
+ // element.as<T> dispatch). Keeping this function small
|
|
|
|
|
+ // sidesteps that codegen bug entirely.
|
|
|
|
|
+ if (element is Invercargill.ValueElement
|
|
|
|
|
+ && set_node_from_value(node, ((Invercargill.ValueElement) element).get_value())) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (try_set_node_from_element(node, element)) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Could not convert
|
|
|
|
|
+ var type = element.type();
|
|
|
|
|
+ throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Out-of-line typed dispatch for {@link JsonElement.from_element}:
|
|
|
|
|
+ * known element types first, then the element's native
|
|
|
|
|
+ * conversions. Returns true when `node` was filled.
|
|
|
|
|
+ */
|
|
|
|
|
+ private static bool try_set_node_from_element(Json.Node node, Invercargill.Element element) throws Invercargill.ElementError {
|
|
|
var type = element.type();
|
|
var type = element.type();
|
|
|
|
|
|
|
|
// Third priority is conversion of known types
|
|
// Third priority is conversion of known types
|
|
|
if(type == typeof(DateTime)) {
|
|
if(type == typeof(DateTime)) {
|
|
|
node.set_string (element.as<DateTime>().format_iso8601());
|
|
node.set_string (element.as<DateTime>().format_iso8601());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(Invercargill.BinaryData)) {
|
|
if(type == typeof(Invercargill.BinaryData)) {
|
|
|
node.set_string (element.as<Invercargill.BinaryData>().to_base64());
|
|
node.set_string (element.as<Invercargill.BinaryData>().to_base64());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(string)) {
|
|
if(type == typeof(string)) {
|
|
|
node.set_string (element.as<string>());
|
|
node.set_string (element.as<string>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(bool)) {
|
|
if(type == typeof(bool)) {
|
|
|
node.set_boolean (element.as<bool>());
|
|
node.set_boolean (element.as<bool>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(double)) {
|
|
if(type == typeof(double)) {
|
|
|
node.set_double (element.as<double?>());
|
|
node.set_double (element.as<double?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(int64)) {
|
|
if(type == typeof(int64)) {
|
|
|
node.set_int (element.as<int64?>());
|
|
node.set_int (element.as<int64?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(uint8)) {
|
|
if(type == typeof(uint8)) {
|
|
|
node.set_int (element.as<uint>());
|
|
node.set_int (element.as<uint>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(int8)) {
|
|
if(type == typeof(int8)) {
|
|
|
node.set_int (element.as<int>());
|
|
node.set_int (element.as<int>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(uint16)) {
|
|
if(type == typeof(uint16)) {
|
|
|
node.set_int (element.as<uint16>());
|
|
node.set_int (element.as<uint16>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(int16)) {
|
|
if(type == typeof(int16)) {
|
|
|
node.set_int (element.as<int16>());
|
|
node.set_int (element.as<int16>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(uint32)) {
|
|
if(type == typeof(uint32)) {
|
|
|
node.set_int (element.as<uint32>());
|
|
node.set_int (element.as<uint32>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(int32)) {
|
|
if(type == typeof(int32)) {
|
|
|
node.set_int (element.as<int32>());
|
|
node.set_int (element.as<int32>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(uint64?)) {
|
|
if(type == typeof(uint64?)) {
|
|
|
node.set_int ((int64)element.as<uint64?>());
|
|
node.set_int ((int64)element.as<uint64?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(type == typeof(float?)) {
|
|
if(type == typeof(float?)) {
|
|
|
node.set_double (element.as<float?>());
|
|
node.set_double (element.as<float?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Last priority is the element's native conversions
|
|
// Last priority is the element's native conversions
|
|
|
if(element.assignable_to<string>()) {
|
|
if(element.assignable_to<string>()) {
|
|
|
node.set_string (element.as<string>());
|
|
node.set_string (element.as<string>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(element.assignable_to<bool> ()) {
|
|
if(element.assignable_to<bool> ()) {
|
|
|
node.set_boolean(element.as<bool>());
|
|
node.set_boolean(element.as<bool>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(element.assignable_to<double?>()) {
|
|
if(element.assignable_to<double?>()) {
|
|
|
node.set_double(element.as<double?>());
|
|
node.set_double(element.as<double?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
if(element.assignable_to<int64?>()) {
|
|
if(element.assignable_to<int64?>()) {
|
|
|
node.set_int(element.as<int64?>());
|
|
node.set_int(element.as<int64?>());
|
|
|
- return;
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Could not convert
|
|
|
|
|
- throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
|
|
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|