Compare commits

...

6 Commits
v1.9.0 ... main

Author SHA1 Message Date
Andrew Lalis 2d97e36b0c Added toOptional function.
Build and Test Module / build-and-test (push) Successful in 6s Details
Build and Test Module / build-and-test-with-asdf-library (push) Successful in 11s Details
2026-06-15 17:42:38 -04:00
Andrew Lalis 97d996b90c Fix test
Build and Test Module / build-and-test (push) Successful in 8s Details
Build and Test Module / build-and-test-with-asdf-library (push) Successful in 11s Details
2026-06-15 15:55:49 -04:00
Andrew Lalis 12ff597f9d Added more generic element value serialization.
Build and Test Module / build-and-test (push) Successful in 7s Details
Build and Test Module / build-and-test-with-asdf-library (push) Failing after 11s Details
2026-06-15 15:53:49 -04:00
Andrew Lalis 2e131c5164 Added const serialization
Build and Test Module / build-and-test (push) Successful in 6s Details
Build and Test Module / build-and-test-with-asdf-library (push) Successful in 13s Details
2026-06-15 15:25:27 -04:00
Andrew Lalis ac3a070944 Added more checks for optional serialization support.
Build and Test Module / build-and-test (push) Successful in 6s Details
Build and Test Module / build-and-test-with-asdf-library (push) Successful in 11s Details
2026-06-15 15:20:21 -04:00
Andrew Lalis 8abb3a2c42 Add check to ensure serialization code only added when underlying value can be serialized.
Build and Test Module / build-and-test (push) Successful in 6s Details
Build and Test Module / build-and-test-with-asdf-library (push) Successful in 11s Details
2026-06-14 13:54:10 -04:00
1 changed files with 75 additions and 28 deletions

View File

@ -88,36 +88,47 @@ struct Optional(T) {
version (Have_asdf) { version (Have_asdf) {
import asdf; import asdf;
/** static if (
* Deserializes an optional value from raw ASDF data. This function __traits(compiles, deserialize!T(Asdf.init))
* is defined to allow for automatic deserialization of Optionals when ) {
* parsing JSON or other data types. /**
* Params: * Deserializes an optional value from raw ASDF data. This function
* data = The data representing an optional value. * is defined to allow for automatic deserialization of Optionals when
* Returns: An exception if one is thrown. * parsing JSON or other data types.
*/ * Params:
SerdeException deserializeFromAsdf(Asdf data) { * data = The data representing an optional value.
if (data == null) { * Returns: An exception if one is thrown.
this.isNull = true; */
this.value = T.init; SerdeException deserializeFromAsdf(Asdf data) {
} else { static if (!__traits(compiles, {T t; t = T.init;})) {
this.isNull = false; return new SerdeException(
this.value = deserialize!T(data); "Cannot deserialize Optional that contains immutable or otherwise unassignable value. " ~
"Ensure that the following code compiles: T t; t = T.init; for the given type T."
);
} else {
if (data == null) {
this.isNull = true;
this.value = T.init;
} else {
this.isNull = false;
this.value = deserialize!T(data);
}
return null;
}
} }
return null;
}
/** /**
* Serializes an optional value to allow for the automatic serialization * Serializes an optional value to allow for the automatic serialization
* of Optionals when writing JSON or other data types. * of Optionals when writing JSON or other data types.
* Params: * Params:
* serializer = The serializer to use (provided by ASDF). * serializer = The serializer to use (provided by ASDF).
*/ */
void serialize(S)(ref S serializer) { void serialize(S)(ref S serializer) const {
if (this.isNull) { if (this.isNull) {
serializer.putValue(null); serializer.putValue(null);
} else { } else {
serializer.putValue(this.value); serializeValue(serializer, this.value);
}
} }
} }
} }
@ -136,6 +147,18 @@ auto mapIfPresent(alias fn, T)(Optional!T opt) {
return Optional!U.of(fn(opt.value)); return Optional!U.of(fn(opt.value));
} }
/**
* Helper function to get an Optional value for an existing value. Due to D's
* type inference, you can simply write `auto opt = toOptional(x);` to avoid
* having to write out types when constructing optionals.
* Params:
* t = The value to construct an optional from.
* Returns: The optional with the given value.
*/
Optional!T toOptional(T)(T t) {
return Optional!T.of(t);
}
unittest { unittest {
Optional!string s = Optional!string.of("hello"); Optional!string s = Optional!string.of("hello");
assert(!s.isNull); assert(!s.isNull);
@ -179,5 +202,29 @@ unittest {
assert(sa.b && sa.b.value == "hello world!"); assert(sa.b && sa.b.value == "hello world!");
assert(sa.c && sa.c.value == 3.14f); assert(sa.c && sa.c.value == 3.14f);
assert(sa.d && sa.d.value == Sd(42, 67)); assert(sa.d && sa.d.value == Sd(42, 67));
// Check that optionals containing immutable data aren't supported for serialization & deserialization:
struct Invalid {
immutable int x;
}
Optional!Invalid opt = Optional!(Invalid).of(Invalid(42));
static assert(__traits(compiles, serializeToJson(opt)));
try {
deserialize!(Optional!(Invalid))(`{"x": 123}`);
assert(
false,
"Failed to ensure that an exception is thrown when attempting to deserialize an incompatible Optional."
);
} catch (SerdeException exc) {
// pass.
}
} }
} }
// Tests for toOptional.
unittest {
int x = 5;
auto optX = x.toOptional;
assert(!optX.isNull);
assert(optX.value == 5);
}