lib/preserves/src/text/nesting.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub const Level = u16;
4 /// The deepest nesting the text readers accept: 256 levels. Tests and callers that build deep input
5 /// read it for that bound. The top value sits at level 0, and each record, sequence, set,
6 /// dictionary, annotation and `#:` embedded value adds a level. Opening a level at 256 fails, so
7 /// 256 nested levels read and 257 fail. `parse` and `decode` stop at the same depth for the same
8 /// text.
9 pub const maximum: Level = 256;
10 pub const root: Level = 0;
11 /// The error both text readers return when input nests past `maximum`. Code calling either text
12 /// reader matches on it, so input nested too deeply stands apart from other bad input. The error
13 /// set holds one tag, `NestingLimitExceeded`, which also belongs to `ParseError` and to the text
14 /// reader's `DecodeError`.
15 pub const Error = error{NestingLimitExceeded};
16
17 pub fn descend(level: Level) Error!Level {
18 if (level >= maximum) return error.NestingLimitExceeded;
19 return level + 1;
20 }
21
22 test "nesting budget admits the maximum and rejects the next level" {
23 var level = root;
24 for (0..maximum) |_| level = try descend(level);
25 try std.testing.expectEqual(maximum, level);
26 try std.testing.expectError(error.NestingLimitExceeded, descend(level));
27 }