-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUtf8TransactionParser.cs
More file actions
64 lines (57 loc) · 1.95 KB
/
Copy pathUtf8TransactionParser.cs
File metadata and controls
64 lines (57 loc) · 1.95 KB
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
using CSharpMastery.FraudEngine.Models;
using System.Numerics;
using System.Text.Json;
namespace CSharpMastery.FraudEngine.Services;
public static class Utf8TransactionParser
{
/// <summary>
/// Parses a JSON payload directly from a UTF-8 ReadOnlySpan<byte> with ZERO heap allocations.
/// Expected format: {"id":"00000000-0000-0000-0000-000000000000","account":1001,"amount":15000.50}
/// </summary>
public static bool TryParseUtf8Payload<TAmount>(
ReadOnlySpan<byte> utf8Json,
ref ValidationContext<TAmount> context)
where TAmount : struct, INumber<TAmount>
{
var reader = new Utf8JsonReader(utf8Json);
Guid transactionId = Guid.Empty;
long accountId = 0;
TAmount amount = TAmount.Zero;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
if (reader.ValueTextEquals("id"u8))
{
reader.Read();
if (!reader.TryGetGuid(out transactionId)) return false;
}
else if (reader.ValueTextEquals("account"u8))
{
reader.Read();
if (!reader.TryGetInt64(out accountId)) return false;
}
else if (reader.ValueTextEquals("amount"u8))
{
reader.Read();
ReadOnlySpan<byte> rawValue = reader.ValueSpan;
if (!TAmount.TryParse(rawValue, provider: null, out amount))
{
return false;
}
}
}
}
if (transactionId == Guid.Empty || accountId == 0)
{
return false;
}
context.SetParsed(new Transaction<TAmount>(
transactionId,
accountId,
amount,
DateTime.UtcNow.Ticks
));
return true;
}
}