Skip to content

Commit

Permalink
Merge pull request #2774 from vibe-d/fix_string_enum_deserialization
Browse files Browse the repository at this point in the history
Fix deserialization of string based enum types
  • Loading branch information
s-ludwig authored Feb 7, 2024
2 parents 9b9b192 + 3227f04 commit 8e35c8c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
53 changes: 51 additions & 2 deletions data/vibe/data/serialization.d
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ import vibe.internal.meta.traits;
import vibe.internal.meta.uda;

import std.array : Appender, appender;
import std.conv : to;
import std.conv : ConvException, to;
import std.exception : enforce;
import std.range.primitives : ElementType, isInputRange;
import std.traits;
Expand Down Expand Up @@ -718,7 +718,13 @@ private template deserializeValueImpl(Serializer, alias Policy) {
static if (hasPolicyAttributeL!(ByNameAttribute, Policy, ATTRIBUTES)) {
return ser.deserializeValue!(string, ATTRIBUTES).to!T();
} else {
return cast(T)ser.deserializeValue!(OriginalType!T);
auto value = ser.deserializeValue!(OriginalType!T);
switch (value) {
default:
throw new ConvException("Unexpected enum value " ~ value.to!string);
static foreach (enumvalue; NoDuplicates!(EnumMembers!T))
case enumvalue: return enumvalue;
}
}
} else static if (Serializer.isSupportedValueType!T) {
return ser.readValue!(Traits, T)();
Expand Down Expand Up @@ -2212,3 +2218,46 @@ unittest { // issue #2110 - single-element tuples
assert(serialize!TestSerializer(s) == expected);
assert(deserialize!(TestSerializer, S)(expected) == s);
}

unittest {
import std.conv : ConvException;
import std.exception : assertThrown, assertNotThrown;

enum Testable : string {
foo = "foo",
bar = "bar",
baz = "bar"
}

Testable deserializeString(string value) {
return deserialize!(TestSerializer, Testable)("V(Aya)(" ~ value ~ ")");
}

foreach (string val; ["foo", "bar"])
assert(deserializeString(val) == val.to!Testable);

assertThrown!ConvException(deserializeString("foobar"));
}

unittest {
import std.conv : ConvException;
import std.exception : assertThrown, assertNotThrown;

enum Foo {
foobar
};

struct Testable {
@byName
Foo bar;
}

void deserializeString(string value) {
auto d = "D(" ~ Testable.mangleof ~ ")";
auto de = "DE(" ~ Foo.mangleof ~ ",bar)";
deserialize!(TestSerializer, Testable)(d ~ "{" ~ de ~ "(V(Aya)(" ~ value ~ "))" ~ de ~ "}" ~ d);
}

assertNotThrown(deserializeString("foobar"));
assertThrown!ConvException(deserializeString("baz"));
}
2 changes: 1 addition & 1 deletion mongodb/vibe/db/mongo/collection.d
Original file line number Diff line number Diff line change
Expand Up @@ -1477,7 +1477,7 @@ struct MaxWireVersion
MaxWireVersion until(WireVersion v) @safe { return MaxWireVersion(v); }

/// Unsets nullable fields not matching the server version as defined per UDAs.
void enforceWireVersionConstraints(T)(ref T field, WireVersion serverVersion,
void enforceWireVersionConstraints(T)(ref T field, int serverVersion,
string file = __FILE__, size_t line = __LINE__)
@safe {
import std.traits : getUDAs;
Expand Down
5 changes: 3 additions & 2 deletions mongodb/vibe/db/mongo/connection.d
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ struct ServerDescription
Nullable!BsonDate lastWriteDate;
Nullable!BsonObjectID opTime;
ServerType type = ServerType.unknown;
WireVersion minWireVersion, maxWireVersion;
int minWireVersion, maxWireVersion;
string me;
string[] hosts, passives, arbiters;
string[string] tags;
Expand Down Expand Up @@ -1153,7 +1153,8 @@ enum WireVersion : int
v50 = 13,
v51 = 14,
v52 = 15,
v53 = 16
v53 = 16,
v60 = 17
}

private string getHostArchitecture()
Expand Down

0 comments on commit 8e35c8c

Please sign in to comment.