Skip to content

Commit

Permalink
make library fully usable in @safe code
Browse files Browse the repository at this point in the history
  • Loading branch information
Herringway committed Nov 15, 2022
1 parent f331c4c commit 1847bdc
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 30 deletions.
4 changes: 4 additions & 0 deletions source/siryul/common.d
Expand Up @@ -354,3 +354,7 @@ bool isSkippableValue(BitFlags!Siryulize flags, T)(const scope ref T value) @saf
assert(!isSkippableValue!skipNulls(f2));
assert(!isSkippableValue!skipNothing(f2));
}

package void trustedAssign(T, T2)(out T dest, T2 val) @trusted {
dest = val;
}
2 changes: 1 addition & 1 deletion source/siryul/dyaml.d
Expand Up @@ -110,7 +110,7 @@ template deserialize(Serializer : YAML, BitFlags!DeSiryulize flags) {
try {
Type tmp;
deserialize(value, path, tmp);
result = tmp;
trustedAssign(result, tmp); //result has not been initialized yet, so this is safe
return;
} catch (YAMLDException e) {}
}
Expand Down
20 changes: 9 additions & 11 deletions source/siryul/json.d
Expand Up @@ -64,7 +64,7 @@ template deserialize(Serializer : JSON, BitFlags!DeSiryulize flags) {
try {
Type tmp;
deserialize(value, path, tmp);
result = tmp;
trustedAssign(result, tmp); //result has not been initialized yet, so this is safe
return;
} catch (JSONDException e) {}
}
Expand Down Expand Up @@ -228,9 +228,9 @@ template serialize(Serializer : JSON, BitFlags!Siryulize flags) {
}
enum memberName = getMemberName!(__traits(getMember, T, member));
static if (hasConvertToFunc!(T, __traits(getMember, T, member))) {
output.object[memberName] = serialize(getConvertToFunc!(T, __traits(getMember, T, member))(__traits(getMember, value, member)));
output[memberName] = serialize(getConvertToFunc!(T, __traits(getMember, T, member))(__traits(getMember, value, member)));
} else {
output.object[memberName] = serialize(__traits(getMember, value, member));
output[memberName] = serialize(__traits(getMember, value, member));
}
}
}
Expand Down Expand Up @@ -271,20 +271,18 @@ template serialize(Serializer : JSON, BitFlags!Siryulize flags) {
return JSONValue(value);
}
private JSONValue serialize(T)(ref T values) if (isSimpleList!T && !isNullable!T && !isStaticString!T && !isNullable!T) {
string[] arr;
auto output = JSONValue(arr);
JSONValue[] output;
foreach (value; values) {
output.array ~= serialize(value);
output ~= serialize(value);
}
return output;
return JSONValue(output);
}
private JSONValue serialize(T)(ref T values) if (isAssociativeArray!T) {
string[string] arr;
auto output = JSONValue(arr);
JSONValue[string] output;
foreach (key, value; values) {
output.object[key] = serialize(value);
output[key] = serialize(value);
}
return output;
return JSONValue(output);
}
private JSONValue serialize(T)(ref T value) if (isAggregateType!T && hasSerializationMethod!T) {
return serialize(__traits(getMember, value, __traits(identifier, serializationMethod!T)));
Expand Down
38 changes: 20 additions & 18 deletions source/siryul/siryul.d
Expand Up @@ -43,13 +43,13 @@ T fromFile(T, Format = AutoDetect, DeSiryulize flags = DeSiryulize.none)(string
}
} else { //Not autodetecting
import std.algorithm : joiner;
import std.file : read;
auto lines = () @trusted { return cast(string)read(path); }();
import std.file : readText;
auto lines = readText(path);
return Format.parseInput!(T, flags)(lines, path);
}
}
///
@system unittest {
@safe unittest {
import std.exception : assertThrown;
import std.file : exists, remove;
import std.stdio : File;
Expand Down Expand Up @@ -100,7 +100,7 @@ T fromString(T, Format, DeSiryulize flags = DeSiryulize.none,U)(U str) if (isSir
return Format.parseInput!(T, flags)(str, "<string>");
}
///
unittest {
@safe unittest {
struct TestStruct {
string a;
}
Expand All @@ -126,7 +126,7 @@ unittest {
return Format.asString!flags(data);
}
///
unittest {
@safe unittest {
//3 as a JSON object
assert(3.toString!JSON == `3`);
//"str" as a JSON object
Expand Down Expand Up @@ -169,7 +169,7 @@ alias toFormattedString = toString;
}
}
///
unittest {
@safe unittest {
import std.exception : assertThrown;
import std.file : exists, remove;
struct TestStruct {
Expand Down Expand Up @@ -234,24 +234,20 @@ version(unittest) {
string aString;
uint[] emptyArray;
Nullable!uint aNullable;
Nullable!(uint,0) anotherNullable;
Nullable!(uint, 0) anotherNullable;
Nullable!SysTime noDate;
Nullable!TestEnum noEnum;
void toString(W)(ref W sink) @safe const {
void toString(W)(ref W sink) @trusted const { //@trusted because of a Nullable!(T, typeof(T)).toString. also it's just for test purposes and doesn't matter
import std.format : formattedWrite;
sink("TestNull(");
formattedWrite(sink, "%s, ", notNull);
formattedWrite(sink, "%s, ", aString);
formattedWrite(sink, "%s, ", emptyArray);
formattedWrite(sink, "%s, ", aNullable);
formattedWrite(sink, "%s, ", anotherNullable);
formattedWrite(sink, "%s, ", noDate);
formattedWrite(sink, "%s, ", noEnum);
sink(")");
formattedWrite!"TestNull(%s, %s, %s, %s, %s, %s, %s)"(sink, notNull, aString, emptyArray, aNullable, anotherNullable, noDate, noEnum);
}
void foo() {
NullSink s;
toString(s);
}
}
}
@system unittest {
@safe unittest {
import std.algorithm : canFind, filter;
import std.conv : text, to;
import std.datetime : Date, DateTime, SysTime, TimeOfDay;
Expand Down Expand Up @@ -531,6 +527,12 @@ version(unittest) {
bool opEquals(const SerializableClass rhs) {
return x == rhs.x;
}
override string toString() @safe{
import std.format : format;
return format!"SerializableClass(%s)"(x);
}
alias opEquals = Object.opEquals;
bool opEquals(SerializableClass c) @safe { return c.x == x; }
}
runTest2(new SerializableClass(true), false);
runTest2(false, new SerializableClass(true));
Expand Down

0 comments on commit 1847bdc

Please sign in to comment.