| ... | ... | @@ -235,6 +235,22 @@ pub const Utf8Iterator = struct { |
| 235 | 235 | else => unreachable, |
| 236 | 236 | } |
| 237 | 237 | } |
| 238 | |
| 239 | /// Look ahead at the next n codepoints without advancing the iterator. |
| 240 | /// If fewer than n codepoints are available, then return the remainder of the string. |
| 241 | pub fn peek(it: *Utf8Iterator, n: usize) []const u8 { |
| 242 | const original_i = it.i; |
| 243 | defer it.i = original_i; |
| 244 | |
| 245 | var end_ix = original_i; |
| 246 | var found: usize = 0; |
| 247 | while (found < n) : (found += 1) { |
| 248 | const next_codepoint = it.nextCodepointSlice() orelse return it.bytes[original_i..]; |
| 249 | end_ix += next_codepoint.len; |
| 250 | } |
| 251 | |
| 252 | return it.bytes[original_i..end_ix]; |
| 253 | } |
| 238 | 254 | }; |
| 239 | 255 | |
| 240 | 256 | pub const Utf16LeIterator = struct { |
| ... | ... | @@ -451,6 +467,31 @@ fn testMiscInvalidUtf8() void { |
| 451 | 467 | testValid("\xee\x80\x80", 0xe000); |
| 452 | 468 | } |
| 453 | 469 | |
| 470 | test "utf8 iterator peeking" { |
| 471 | comptime testUtf8Peeking(); |
| 472 | testUtf8Peeking(); |
| 473 | } |
| 474 | |
| 475 | fn testUtf8Peeking() void { |
| 476 | const s = Utf8View.initComptime("noël"); |
| 477 | var it = s.iterator(); |
| 478 | |
| 479 | testing.expect(std.mem.eql(u8, "n", it.nextCodepointSlice().?)); |
| 480 | |
| 481 | testing.expect(std.mem.eql(u8, "o", it.peek(1))); |
| 482 | testing.expect(std.mem.eql(u8, "oë", it.peek(2))); |
| 483 | testing.expect(std.mem.eql(u8, "oël", it.peek(3))); |
| 484 | testing.expect(std.mem.eql(u8, "oël", it.peek(4))); |
| 485 | testing.expect(std.mem.eql(u8, "oël", it.peek(10))); |
| 486 | |
| 487 | testing.expect(std.mem.eql(u8, "o", it.nextCodepointSlice().?)); |
| 488 | testing.expect(std.mem.eql(u8, "ë", it.nextCodepointSlice().?)); |
| 489 | testing.expect(std.mem.eql(u8, "l", it.nextCodepointSlice().?)); |
| 490 | testing.expect(it.nextCodepointSlice() == null); |
| 491 | |
| 492 | testing.expect(std.mem.eql(u8, &[_]u8{}, it.peek(1))); |
| 493 | } |
| 494 | |
| 454 | 495 | fn testError(bytes: []const u8, expected_err: anyerror) void { |
| 455 | 496 | testing.expectError(expected_err, testDecode(bytes)); |
| 456 | 497 | } |