lib/preserves/src/text/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 //! A text syntax for values, with two readers and two writers. People write and read this form by
 2 //! hand, so a reader meets text that a person typed. A caller needs to know which text each reader
 3 //! accepts, what the decoded value owns, and what stops deeply nested input. Each level of nesting
 4 //! costs the readers a level of recursion, and text can nest as deep as its length allows.
 5 //! Hand-written text lists set elements and dictionary entries in any order, and can repeat them.
 6 //! The syntax is the text syntax of the [Preserves](https://preserves.dev/) data language, which
 7 //! the package keeps.
 8 //!
 9 //! Both readers stop at 256 levels of nesting (`max_nesting_depth`), and each record, sequence,
10 //! set, dictionary, annotation and `#:` embedded value adds a level. Depth is the one bound:
11 //! neither reader limits input size, item count or memory. Both readers reject a repeated set
12 //! element or dictionary key. The reader `parse` then sorts sets and dictionaries, and the reader
13 //! `decode` keeps the written order. The two writers are `encode`, which refuses discards,
14 //! captures, binds and rest patterns, and `toText`, which writes them. Both readers copy every
15 //! string they keep, so the decoded value owns all its memory and borrows nothing from the text.
16 //!
17 //! `parse` reads `# ` comments, and reads `#:` embedded values into `AnyEmbedded` values. `decode`
18 //! rejects `# ` comments, and rejects `#:` embedded values whose type is `NoEmbedded` or
19 //! `AnyEmbedded`. Both readers read a bare token with underscores between digits, such as `1_000`,
20 //! as a symbol. `encode` writes the symbol `1_000` bare, so `parse` reads it back as a symbol.
21 //! `encode` writes a `'` inside a quoted symbol as `\'`, `parse` accepts `\'` and `\"` in strings
22 //! and quoted symbols, and `decode` accepts `\'` in quoted symbols and `\"` in strings, and rejects
23 //! `\'` in strings and `\"` in quoted symbols with `BadEscape`. `decode` checks strings and symbols
24 //! as UTF-8, and `parse` returns `InvalidUtf8` for invalid UTF-8 in strings and symbols.
25 const preserves = @import("../root.zig");
26 const format = @import("format.zig");
27 const parser = @import("parser.zig");
28 const nesting = @import("nesting.zig");
29 pub const reader = @import("reader.zig");
30 pub const writer = @import("writer.zig");
31 
32 const value_mod = preserves.value;
33 const embedded_mod = preserves.embedded_mod;
34 const parse_error_mod = preserves.parse_error;
35 const integer_mod = preserves.integer_mod;
36 
37 /// An embedded value that points to a payload of the host program, with optional functions to
38 /// compare, hash, free and copy it. Code that builds embedded values for `parse`, `toText` or
39 /// `Value` names it. It is the type of the embedded values in the text namespace's values. `parse`
40 /// makes each `#:` embedded value one of these, owning the value it read.
41 pub const AnyEmbedded = embedded_mod.AnyEmbedded;
42 /// The value type `parse` returns and `toText` writes: `Value(AnyEmbedded)`. Code that reads data
43 /// files names it as the value each file decodes to. `Value.Domain` names the type of its embedded
44 /// values, so a caller can pass it to `decode`.
45 pub const Value = value_mod.Value(AnyEmbedded);
46 /// The error set `parse` returns, the same set as `preserves.ParseError`. Code that calls `parse`
47 /// switches on it.
48 pub const ParseError = parse_error_mod.ParseError;
49 pub const NestingError = nesting.Error;
50 pub const max_nesting_depth = nesting.maximum;
51 pub const toText = format.toText;
52 pub const parse = parser.parse;
53 pub const decode = reader.decode;
54 pub const encode = writer.encode;