• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / MediatR.CommandQuery / 14067111219

25 Mar 2025 06:14PM UTC coverage: 59.397% (-0.5%) from 59.879%
14067111219

push

github

pwelter34
Update MediatorServiceExtensions.cs

495 of 971 branches covered (50.98%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 1 file covered. (0.0%)

113 existing lines in 15 files now uncovered.

1474 of 2344 relevant lines covered (62.88%)

22.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.03
/src/MediatR.CommandQuery/Services/QueryStringEncoder.cs
1
using System.Buffers;
2
using System.IO.Compression;
3
using System.Text.Json;
4

5
namespace MediatR.CommandQuery.Services;
6

7
public static class QueryStringEncoder
8
{
9
    public static string? Encode<T>(T value, JsonSerializerOptions? options = null)
10
    {
11
        if (value is null)
2!
12
            return null;
×
13

14
        options ??= new JsonSerializerOptions(JsonSerializerDefaults.Web);
2✔
15

16
        using var outputStream = new MemoryStream();
2✔
17
        using var compressionStream = new GZipStream(outputStream, CompressionMode.Compress);
2✔
18
        using var jsonWriter = new Utf8JsonWriter(compressionStream);
2✔
19

20
        JsonSerializer.Serialize(jsonWriter, value, options);
2✔
21

22
        var jsonBytes = outputStream.ToArray();
2✔
23

24
        return Base64UrlEncode(jsonBytes);
2✔
25
    }
2✔
26

27
    public static T? Decode<T>(string? encodedQueryString, JsonSerializerOptions? options = null)
28
    {
29
        if (string.IsNullOrWhiteSpace(encodedQueryString))
2!
30
            return default;
×
31

32
        var jsonBytes = Base64UrlDecode(encodedQueryString);
2✔
33

34
        options ??= new JsonSerializerOptions(JsonSerializerDefaults.Web);
2✔
35

36
        using var inputStream = new MemoryStream(jsonBytes);
2✔
37
        using var compressionStream = new GZipStream(inputStream, CompressionMode.Decompress);
2✔
38

39
        return JsonSerializer.Deserialize<T>(compressionStream, options);
2✔
40
    }
2✔
41

42

43
    public static string Base64UrlEncode(ReadOnlySpan<byte> input)
44
    {
45
        const int StackAllocThreshold = 128;
46

47
        if (input.IsEmpty)
2!
48
            return string.Empty;
×
49

50
        int bufferSize = GetArraySizeRequiredToEncode(input.Length);
2✔
51

52
        char[]? bufferToReturnToPool = null;
2✔
53

54
        Span<char> buffer = bufferSize <= StackAllocThreshold
2!
55
            ? stackalloc char[StackAllocThreshold]
2✔
56
            : bufferToReturnToPool = ArrayPool<char>.Shared.Rent(bufferSize);
2✔
57

58
        var numBase64Chars = Base64UrlEncode(input, buffer);
2✔
59
        var base64Url = new string(buffer.Slice(0, numBase64Chars));
2✔
60

61
        if (bufferToReturnToPool != null)
2✔
62
            ArrayPool<char>.Shared.Return(bufferToReturnToPool);
2✔
63

64
        return base64Url;
2✔
65
    }
66

67
    public static byte[] Base64UrlDecode(string input)
68
    {
69
        ArgumentNullException.ThrowIfNull(input);
2✔
70

71
        var count = input.Length;
2✔
72
        if (count == 0)
2!
73
            return [];
×
74

75
        var offset = 0;
2✔
76
        var buffer = new char[GetArraySizeRequiredToDecode(count)];
2✔
77
        var bufferOffset = 0;
2✔
78

79
        var paddingCharsToAdd = GetNumBase64PaddingCharsToAddForDecode(count);
2✔
80
        var arraySizeRequired = checked(count + paddingCharsToAdd);
2✔
81

82
        // Copy input into buffer, fixing up '-' -> '+' and '_' -> '/'.
83
        var i = bufferOffset;
2✔
84
        for (var j = offset; i - bufferOffset < count; i++, j++)
826✔
85
        {
86
            var ch = input[j];
274✔
87
            if (ch == '-')
274!
UNCOV
88
                buffer[i] = '+';
×
89
            else if (ch == '_')
274✔
90
                buffer[i] = '/';
10✔
91
            else
92
                buffer[i] = ch;
264✔
93
        }
94

95
        // Add the padding characters back.
96
        for (; paddingCharsToAdd > 0; i++, paddingCharsToAdd--)
8✔
97
            buffer[i] = '=';
2✔
98

99
        return Convert.FromBase64CharArray(buffer, bufferOffset, arraySizeRequired);
2✔
100
    }
101

102

103
    private static int Base64UrlEncode(ReadOnlySpan<byte> input, Span<char> output)
104
    {
105
        if (input.IsEmpty)
2!
106
            return 0;
×
107

108
        Convert.TryToBase64Chars(input, output, out int charsWritten);
2✔
109

110
        // Fix up '+' -> '-' and '/' -> '_'. Drop padding characters.
111
        for (var i = 0; i < charsWritten; i++)
552✔
112
        {
113
            var ch = output[i];
275✔
114
            if (ch == '+')
275!
UNCOV
115
                output[i] = '-';
×
116
            else if (ch == '/')
275✔
117
                output[i] = '_';
10✔
118
            else if (ch == '=')
265✔
119
                return i; // We've reached a padding character; truncate the remainder.
1✔
120
        }
121

122
        return charsWritten;
1✔
123
    }
124

125
    private static int GetArraySizeRequiredToEncode(int count)
126
    {
127
        var numWholeOrPartialInputBlocks = checked(count + 2) / 3;
2✔
128
        return checked(numWholeOrPartialInputBlocks * 4);
2✔
129
    }
130

131

132
    private static int GetArraySizeRequiredToDecode(int count)
133
    {
134
        if (count == 0)
2!
135
            return 0;
×
136

137
        var numPaddingCharsToAdd = GetNumBase64PaddingCharsToAddForDecode(count);
2✔
138

139
        return checked(count + numPaddingCharsToAdd);
2✔
140
    }
141

142
    private static int GetNumBase64PaddingCharsToAddForDecode(int inputLength)
143
    {
144
        return (inputLength % 4) switch
4!
145
        {
4✔
146
            0 => 0,
2✔
147
            2 => 2,
2✔
UNCOV
148
            3 => 1,
×
149
            _ => throw new FormatException($"Malformed input: {inputLength} is an invalid input length."),
×
150
        };
4✔
151
    }
152
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc