-
Notifications
You must be signed in to change notification settings - Fork 0
/
HashSetMemoryStreamConverter.cs
121 lines (103 loc) · 4.32 KB
/
HashSetMemoryStreamConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
namespace NServiceBus.Persistence.DynamoDB
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
sealed class HashSetMemoryStreamConverter : JsonConverterFactory
{
// This is a cryptic property name to make sure we never class with the user data
const string PropertyName = "HashSetMemoryStreamContent838D2F22-0D5B-4831-8C04-17C7A6329B31";
public override bool CanConvert(Type typeToConvert)
=> typeToConvert.IsGenericType && typeof(ISet<MemoryStream>).IsAssignableFrom(typeToConvert);
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var converter = (JsonConverter)Activator.CreateInstance(
typeof(SetConverter<>)
.MakeGenericType(new Type[] { typeToConvert }),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: new[] { options },
culture: null)!;
return converter;
}
sealed class SetConverter<TSet> : JsonConverter<TSet> where TSet : ISet<MemoryStream>
{
public SetConverter(JsonSerializerOptions options)
{
var streamConverter = (JsonConverter<MemoryStream>)options.GetConverter(typeof(MemoryStream));
memoryStreamOptions = new JsonSerializerOptions { Converters = { streamConverter } };
}
public override TSet? Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
reader.Read();
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string? propertyName = reader.GetString();
if (propertyName != PropertyName)
{
throw new JsonException();
}
reader.Read();
if (reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException();
}
var set = JsonSerializer.Deserialize<TSet>(ref reader, memoryStreamOptions);
reader.Read();
if (reader.TokenType != JsonTokenType.EndObject)
{
throw new JsonException();
}
return set;
}
public override void Write(Utf8JsonWriter writer, TSet value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName(PropertyName);
JsonSerializer.Serialize(writer, value, memoryStreamOptions);
writer.WriteEndObject();
}
readonly JsonSerializerOptions memoryStreamOptions;
}
public static bool TryExtract(JsonProperty property, out List<MemoryStream?>? memoryStreams)
{
memoryStreams = null;
if (!property.NameEquals(PropertyName))
{
return false;
}
foreach (var innerElement in property.Value.EnumerateArray())
{
memoryStreams ??= new List<MemoryStream?>(property.Value.GetArrayLength());
foreach (var streamElement in innerElement.EnumerateObject())
{
memoryStreams.Add(new MemoryStream(streamElement.Value.GetBytesFromBase64()));
}
}
memoryStreams ??= new List<MemoryStream?>(0);
return true;
}
public static JsonNode ToNode(List<MemoryStream> memoryStreams)
{
var jsonObject = new JsonObject();
var streamHashSetContent = new JsonArray();
foreach (var memoryStream in memoryStreams)
{
streamHashSetContent.Add(MemoryStreamConverter.ToNode(memoryStream));
}
jsonObject.Add(PropertyName, streamHashSetContent);
return jsonObject;
}
}
}