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

me-viper / OpaDotNet / 11512106788

25 Oct 2024 04:51AM CUT coverage: 84.386%. Remained the same
11512106788

push

github

me-viper
ci: Add CI inputs

1820 of 2364 branches covered (76.99%)

Branch coverage included in aggregate %.

3817 of 4316 relevant lines covered (88.44%)

1737.21 hits per line

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

61.68
/src/Wasm/src/Internal/ValueStringBuilder.cs
1
using System.Buffers;
2
using System.Globalization;
3
using System.Runtime.CompilerServices;
4

5
namespace OpaDotNet.Wasm.Internal;
6

7
// Borrowed from https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Text/ValueStringBuilder.cs
8
internal ref struct ValueStringBuilder
9
{
10
    private char[]? _arrayToReturnToPool;
11

12
    private Span<char> _chars;
13

14
    private int _pos;
15

16
    public ValueStringBuilder(Span<char> buffer)
17
    {
18
        _arrayToReturnToPool = null;
84✔
19
        _chars = buffer;
84✔
20
        _pos = 0;
84✔
21
    }
84✔
22

23
    // public ValueStringBuilder(ReadOnlySpan<char> initialBuffer)
24
    // {
25
    //     _arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialBuffer.Length);
26
    //     _chars = _arrayToReturnToPool;
27
    //     initialBuffer.CopyTo(_chars[..]);
28
    //     _pos = initialBuffer.Length;
29
    // }
30

31
    public ValueStringBuilder(int initialCapacity)
32
    {
33
        _arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
94✔
34
        _chars = _arrayToReturnToPool;
94✔
35
        _pos = 0;
94✔
36
    }
94✔
37

38
    public int Length
39
    {
40
        get => _pos;
30✔
41
        set => _pos = value;
×
42
    }
43

44
    public int Capacity => _chars.Length;
×
45

46
    public ref char this[int index]
47
    {
48
        get => ref _chars[index];
30✔
49
    }
50

51
    public override string ToString()
52
    {
53
        var s = _chars[.._pos].ToString();
94✔
54
        Dispose();
94✔
55
        return s;
94✔
56
    }
57

58
    /// <summary>Returns the underlying storage of the builder.</summary>
59
    public Span<char> RawChars => _chars;
×
60

61
    public ReadOnlySpan<char> AsSpan() => _chars[.._pos];
84✔
62

63
    public ReadOnlySpan<char> AsSpan(int start) => _chars.Slice(start, _pos - start);
×
64

65
    public ReadOnlySpan<char> AsSpan(int start, int length) => _chars.Slice(start, length);
×
66

67
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
68
    public void Append(char c)
69
    {
70
        var pos = _pos;
68✔
71
        var chars = _chars;
68✔
72

73
        if ((uint)pos < (uint)chars.Length)
68!
74
        {
75
            chars[pos] = c;
68✔
76
            _pos = pos + 1;
68✔
77
        }
78
        else
79
        {
80
            Grow(1);
×
81
            Append(c);
×
82
        }
83
    }
×
84

85
    public void Append(int n)
86
    {
87
        Append(n, ReadOnlySpan<char>.Empty);
20✔
88
    }
20✔
89

90
    public void Append(int n, ReadOnlySpan<char> format)
91
    {
92
        var len = (int)Math.Floor(Math.Log10(Math.Abs(n))) + 1;
36✔
93
        var pos = _pos;
36✔
94

95
        if (pos > _chars.Length - len)
36!
96
            Grow(len);
×
97

98
        n.TryFormat(_chars[_pos..], out var bw, format, CultureInfo.InvariantCulture);
36✔
99
        _pos += bw;
36✔
100
    }
36✔
101

102
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
103
    public void Append(string? s)
104
    {
105
        if (s == null)
18!
106
            return;
×
107

108
        var pos = _pos;
18✔
109

110
        // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
111
        if (s.Length == 1 && (uint)pos < (uint)_chars.Length)
18!
112
        {
113
            _chars[pos] = s[0];
×
114
            _pos = pos + 1;
×
115
        }
116
        else
117
        {
118
            AppendSlow(s);
18✔
119
        }
120
    }
18✔
121

122
    private void AppendSlow(string s)
123
    {
124
        var pos = _pos;
18✔
125

126
        if (pos > _chars.Length - s.Length)
18!
127
            Grow(s.Length);
×
128

129
        s.CopyTo(_chars[pos..]);
18✔
130
        _pos += s.Length;
18✔
131
    }
18✔
132

133
    public void AppendQuoted(scoped ReadOnlySpan<char> value)
134
    {
135
        var pos = _pos;
640✔
136

137
        if (pos > _chars.Length - value.Length - 2)
640!
138
        {
139
            Grow(value.Length + 2);
×
140
        }
141

142
        _chars[_pos] = '"';
640✔
143
        _pos++;
640✔
144

145
        value.CopyTo(_chars[_pos..]);
640✔
146
        _pos += value.Length;
640✔
147

148
        _chars[_pos] = '"';
640✔
149
        _pos++;
640✔
150
    }
640✔
151

152
    public void Append(scoped ReadOnlySpan<char> value)
153
    {
154
        var pos = _pos;
836✔
155

156
        if (pos > _chars.Length - value.Length)
836!
157
        {
158
            Grow(value.Length);
×
159
        }
160

161
        value.CopyTo(_chars[_pos..]);
836✔
162
        _pos += value.Length;
836✔
163
    }
836✔
164

165
    [UsedImplicitly]
166
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
167
    public void Dispose()
168
    {
169
        var toReturn = _arrayToReturnToPool;
272✔
170

171
        // for safety, to avoid using pooled array if this instance is erroneously appended to again
172
        this = default;
272✔
173

174
        if (toReturn != null)
272✔
175
            ArrayPool<char>.Shared.Return(toReturn);
94✔
176
    }
272✔
177

178
    [MethodImpl(MethodImplOptions.NoInlining)]
179
    private void Grow(int additionalCapacityBeyondPos)
180
    {
181
        if (_arrayToReturnToPool == null)
×
182
            throw new InvalidOperationException("Have been initialized from Span and can't grow");
×
183

184
        const uint arrayMaxLength = 0x7FFFFFC7; // same as Array.MaxLength
185

186
        // Increase to at least the required size (_pos + additionalCapacityBeyondPos), but try
187
        // to double the size if possible, bounding the doubling to not go beyond the max array length.
188
        var newCapacity = (int)Math.Max(
×
189
            (uint)(_pos + additionalCapacityBeyondPos),
×
190
            Math.Min((uint)_chars.Length * 2, arrayMaxLength)
×
191
            );
×
192

193
        // Make sure to let Rent throw an exception if the caller has a bug and the desired capacity is negative.
194
        // This could also go negative if the actual required length wraps around.
195
        var poolArray = ArrayPool<char>.Shared.Rent(newCapacity);
×
196

197
        _chars[.._pos].CopyTo(poolArray);
×
198

199
        var toReturn = _arrayToReturnToPool;
×
200

201
        _chars = poolArray;
×
202
        _arrayToReturnToPool = poolArray;
×
203

204
        if (toReturn != null)
×
205
            ArrayPool<char>.Shared.Return(toReturn);
×
206
    }
×
207
}
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

© 2025 Coveralls, Inc