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

neon-sunset / U8String / 5980222482

25 Aug 2023 08:35PM UTC coverage: 19.654% (-0.1%) from 19.773%
5980222482

push

github

neon-sunset
feat: finish updating to new abstraction, fix invalid reference in .Move

134 of 968 branches covered (0.0%)

Branch coverage included in aggregate %.

38 of 38 new or added lines in 8 files covered. (100.0%)

479 of 2151 relevant lines covered (22.27%)

38276.27 hits per line

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

0.0
/src/U8String.Splitting.cs
1
using System.Text;
2

3
#pragma warning disable RCS1085, RCS1085FadeOut, IDE0032 // Use auto-implemented property. Why: readable fields.
4
namespace U8Primitives;
5

6
public readonly partial struct U8String
7
{
8
    public U8SplitPair SplitFirst(byte separator)
9
    {
10
        if (!U8Info.IsAsciiByte(separator))
×
11
        {
12
            // TODO: EH UX
13
            ThrowHelpers.ArgumentOutOfRange();
×
14
        }
15

16
        var source = this;
×
17
        if (!source.IsEmpty)
×
18
        {
19
            var span = source.UnsafeSpan;
×
20
            var index = span.IndexOf(separator);
×
21
            if (index >= 0)
×
22
            {
23
                return new(source, index, 1);
×
24
            }
25

26
            return U8SplitPair.NotFound(source);
×
27
        }
28

29
        return default;
×
30
    }
31

32
    public U8SplitPair SplitFirst(char separator) => char.IsAscii(separator)
×
33
        ? SplitFirst((byte)separator)
×
34
        : SplitFirstUnchecked(U8Scalar.Create(separator, checkAscii: false).AsSpan());
×
35

36
    public U8SplitPair SplitFirst(Rune separator) => separator.IsAscii
×
37
        ? SplitFirst((byte)separator.Value)
×
38
        : SplitFirstUnchecked(U8Scalar.Create(separator, checkAscii: false).AsSpan());
×
39

40
    public U8SplitPair SplitFirst(U8String separator)
41
    {
42
        var source = this;
×
43
        if (!source.IsEmpty)
×
44
        {
45
            if (!separator.IsEmpty)
×
46
            {
47
                var span = source.UnsafeSpan;
×
48
                var index = span.IndexOf(separator.UnsafeSpan);
×
49
                if (index >= 0)
×
50
                {
51
                    return new(source, index, separator.Length);
×
52
                }
53
            }
54

55
            return U8SplitPair.NotFound(source);
×
56
        }
57

58
        return default;
×
59
    }
60

61
    // It would be *really nice* to aggressively inline this method
62
    // but the way validation is currently implemented does not significantly
63
    // benefit from splitting on UTF-8 literals while possibly risking
64
    // running out of inlining budget significantly regressing performance everywhere else.
65
    public U8SplitPair SplitFirst(ReadOnlySpan<byte> separator)
66
    {
67
        var source = this;
×
68
        if (!source.IsEmpty)
×
69
        {
70
            if (!separator.IsEmpty)
×
71
            {
72
                var span = source.UnsafeSpan;
×
73
                var index = span.IndexOf(separator);
×
74
                if (index >= 0)
×
75
                {
76
                    // Same as with Slice(int, int), this might dereference past the end of the string.
77
                    // TODO: Do something about it if it's ever an issue.
78
                    if (U8Info.IsContinuationByte(source.UnsafeRefAdd(index)) ||
×
79
                        U8Info.IsContinuationByte(source.UnsafeRefAdd(index + separator.Length)))
×
80
                    {
81
                        ThrowHelpers.InvalidSplit();
×
82
                    }
83

84
                    return new(source, index, separator.Length);
×
85
                }
86
            }
87

88
            return U8SplitPair.NotFound(source);
×
89
        }
90

91
        return default;
×
92
    }
93

94
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
95
    public U8SplitPair SplitFirstUnchecked(ReadOnlySpan<byte> separator)
96
    {
97
        var source = this;
×
98
        if (!source.IsEmpty)
×
99
        {
100
            if (!separator.IsEmpty)
×
101
            {
102
                var span = source.UnsafeSpan;
×
103
                var index = span.IndexOf(separator);
×
104
                if (index >= 0)
×
105
                {
106
                    return new(source, index, separator.Length);
×
107
                }
108
            }
109

110
            return U8SplitPair.NotFound(source);
×
111
        }
112

113
        return default;
×
114
    }
115

116
    public U8SplitPair SplitLast(byte separator)
117
    {
118
        if (!U8Info.IsAsciiByte(separator))
×
119
        {
120
            // TODO: EH UX
121
            ThrowHelpers.ArgumentOutOfRange();
×
122
        }
123

124
        var source = this;
×
125
        if (!source.IsEmpty)
×
126
        {
127
            var span = source.UnsafeSpan;
×
128
            var index = span.LastIndexOf(separator);
×
129
            if (index >= 0)
×
130
            {
131
                return new(source, index, 1);
×
132
            }
133

134
            return U8SplitPair.NotFound(source);
×
135
        }
136

137
        return default;
×
138
    }
139

140
    public U8SplitPair SplitLast(char separator) => char.IsAscii(separator)
×
141
        ? SplitLast((byte)separator)
×
142
        : SplitLastUnchecked(U8Scalar.Create(separator, checkAscii: false).AsSpan());
×
143

144
    public U8SplitPair SplitLast(Rune separator) => separator.IsAscii
×
145
        ? SplitLast((byte)separator.Value)
×
146
        : SplitLastUnchecked(U8Scalar.Create(separator, checkAscii: false).AsSpan());
×
147

148
    public U8SplitPair SplitLast(U8String separator)
149
    {
150
        var source = this;
×
151
        if (!source.IsEmpty)
×
152
        {
153
            if (!separator.IsEmpty)
×
154
            {
155
                var span = source.UnsafeSpan;
×
156
                var index = span.LastIndexOf(separator.UnsafeSpan);
×
157
                if (index >= 0)
×
158
                {
159
                    return new(source, index, separator.Length);
×
160
                }
161
            }
162

163
            return U8SplitPair.NotFound(source);
×
164
        }
165

166
        return default;
×
167
    }
168

169
    public U8SplitPair SplitLast(ReadOnlySpan<byte> separator)
170
    {
171
        var source = this;
×
172
        if (!source.IsEmpty)
×
173
        {
174
            if (!separator.IsEmpty)
×
175
            {
176
                var span = source.UnsafeSpan;
×
177
                var index = span.LastIndexOf(separator);
×
178
                if (index >= 0)
×
179
                {
180
                    if (U8Info.IsContinuationByte(source.UnsafeRefAdd(index)) ||
×
181
                        U8Info.IsContinuationByte(source.UnsafeRefAdd(index + separator.Length)))
×
182
                    {
183
                        ThrowHelpers.InvalidSplit();
×
184
                    }
185

186
                    return new(source, index, separator.Length);
×
187
                }
188
            }
189

190
            return U8SplitPair.NotFound(source);
×
191
        }
192

193
        return default;
×
194
    }
195

196
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
197
    public U8SplitPair SplitLastUnchecked(ReadOnlySpan<byte> separator)
198
    {
199
        var source = this;
×
200
        if (!source.IsEmpty)
×
201
        {
202
            if (!separator.IsEmpty)
×
203
            {
204
                var span = source.UnsafeSpan;
×
205
                var index = span.LastIndexOf(separator);
×
206
                if (index >= 0)
×
207
                {
208
                    return new(source, index, separator.Length);
×
209
                }
210
            }
211

212
            return U8SplitPair.NotFound(source);
×
213
        }
214

215
        return default;
×
216
    }
217

218
    public U8Split<byte> Split(byte separator)
219
    {
220
        if (!U8Info.IsAsciiByte(separator))
×
221
        {
222
            ThrowHelpers.ArgumentOutOfRange();
×
223
        }
224

225
        return new(this, separator);
×
226
    }
227

228
    public U8Split<char> Split(char separator)
229
    {
230
        if (char.IsSurrogate(separator))
×
231
        {
232
            ThrowHelpers.ArgumentOutOfRange();
×
233
        }
234

235
        return new(this, separator);
×
236
    }
237

238
    public U8Split<Rune> Split(Rune separator) => new(this, separator);
×
239

240
    public U8Split Split(U8String separator)
241
    {
242
        return new(this, separator);
×
243
    }
244

245
    public U8RefSplit Split(ReadOnlySpan<byte> separator)
246
    {
247
        if (!IsValid(separator))
×
248
        {
249
            ThrowHelpers.InvalidSplit();
×
250
        }
251

252
        return new(this, separator);
×
253
    }
254

255
    public ConfiguredU8Split<byte> Split(byte separator, U8SplitOptions options)
256
    {
257
        if (!U8Info.IsAsciiByte(separator))
×
258
        {
259
            ThrowHelpers.ArgumentOutOfRange();
×
260
        }
261

262
        return new(this, separator, options);
×
263
    }
264

265
    public ConfiguredU8Split<char> Split(char separator, U8SplitOptions options)
266
    {
267
        if (char.IsSurrogate(separator))
×
268
        {
269
            ThrowHelpers.ArgumentOutOfRange();
×
270
        }
271

272
        return new(this, separator, options);
×
273
    }
274

275
    public ConfiguredU8Split<Rune> Split(Rune separator, U8SplitOptions options) => new(this, separator, options);
×
276

277
    public ConfiguredU8Split Split(U8String separator, U8SplitOptions options)
278
    {
279
        return new(this, separator, options);
×
280
    }
281
}
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