Fauna .NET Driver 0.1.0-beta
 
Loading...
Searching...
No Matches
ClassDeserializer.cs
Go to the documentation of this file.
1using Fauna.Mapping;
2using System.Diagnostics;
3
4namespace Fauna.Serialization;
5
6internal interface IClassDeserializer : IDeserializer
7{
8 public object DeserializeDocument(MappingContext context, string? id, string? name, ref Utf8FaunaReader reader);
9}
10
11internal class ClassDeserializer<T> : BaseDeserializer<T>, IClassDeserializer
12{
13 private static readonly string _idField = "id";
14 private static readonly string _nameField = "name";
15
16 private readonly MappingInfo _info;
17
18 public ClassDeserializer(MappingInfo info)
19 {
20 Debug.Assert(info.Type == typeof(T));
21 _info = info;
22 }
23
24 public object DeserializeDocument(MappingContext context, string? id, string? name, ref Utf8FaunaReader reader)
25 {
26 var instance = CreateInstance();
27 if (id is not null) TrySetId(instance, id);
28 if (name is not null) TrySetName(instance, name);
29 SetFields(instance, context, ref reader, TokenType.EndDocument);
30 return instance;
31 }
32
33 public override T Deserialize(MappingContext context, ref Utf8FaunaReader reader)
34 {
35 var endToken = reader.CurrentTokenType switch
36 {
37 TokenType.StartDocument => TokenType.EndDocument,
38 TokenType.StartObject => TokenType.EndObject,
39 var other => throw UnexpectedToken(other),
40 };
41
42 var instance = CreateInstance();
43 SetFields(instance, context, ref reader, endToken);
44 return (T)instance;
45 }
46
47 private object CreateInstance() => Activator.CreateInstance(_info.Type)!;
48
49 private void SetFields(object instance, MappingContext context, ref Utf8FaunaReader reader, TokenType endToken)
50 {
51 while (reader.Read() && reader.CurrentTokenType != endToken)
52 {
53 if (reader.CurrentTokenType != TokenType.FieldName)
54 throw UnexpectedToken(reader.CurrentTokenType);
55
56 var fieldName = reader.GetString()!;
57 reader.Read();
58
59 if (fieldName == _idField && reader.CurrentTokenType == TokenType.String)
60 {
61 TrySetId(instance, reader.GetString()!);
62 }
63 else if (fieldName == _nameField && reader.CurrentTokenType == TokenType.String)
64 {
65 TrySetName(instance, reader.GetString()!);
66 }
67 else if (_info.FieldsByName.TryGetValue(fieldName, out var field))
68 {
69 field.Property.SetValue(instance, field.Deserializer.Deserialize(context, ref reader));
70 }
71 else
72 {
73 reader.Skip();
74 }
75 }
76 }
77
78 private void TrySetId(object instance, string id)
79 {
80 if (_info.FieldsByName.TryGetValue(_idField, out var field))
81 {
82 if (field.Type == typeof(long))
83 {
84 field.Property.SetValue(instance, long.Parse(id));
85 }
86 else if (field.Type == typeof(string))
87 {
88 field.Property.SetValue(instance, id);
89 }
90 else
91 {
92 throw UnexpectedToken(TokenType.String);
93 }
94 }
95 }
96
97 private void TrySetName(object instance, string name)
98 {
99 if (_info.FieldsByName.TryGetValue(_nameField, out var field))
100 {
101 if (field.Type == typeof(string))
102 {
103 field.Property.SetValue(instance, name);
104 }
105 else
106 {
107 throw UnexpectedToken(TokenType.String);
108 }
109 }
110 }
111
112 private SerializationException UnexpectedToken(TokenType tokenType) =>
113 new SerializationException(
114 $"Unexpected token while deserializing into class {_info.Type.Name}: {tokenType}");
115}
new T Deserialize(MappingContext context, ref Utf8FaunaReader reader)
TokenType
Enumerates the types of tokens used in Fauna serialization.
Definition TokenType.cs:7