lib/zen/src/frontmatter/parse.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const model = @import("model.zig");
 3 const scan = @import("scan.zig");
 4 const storage_mod = @import("storage.zig");
 5 
 6 pub fn parse(storage: *storage_mod.Storage, markdown: []const u8) model.Error!model.Parsed {
 7     const regions = try storage.acquire(markdown);
 8     var iterator = scan.Iterator.init(markdown[regions.plan.metadata_start..regions.plan.metadata_end]);
 9     var pair_index: usize = 0;
10     var byte_index: usize = 0;
11     var current: ?usize = null;
12     var continuation_start: usize = 0;
13     var continuing = false;
14 
15     while (iterator.next()) |field| switch (field) {
16         .pair => |pair| {
17             std.debug.assert(pair_index < regions.pairs.len);
18             regions.pairs[pair_index] = .{ .key = pair.key, .value = pair.value };
19             current = pair_index;
20             continuing = false;
21             pair_index += 1;
22         },
23         .continuation => |value| if (current) |index| {
24             const active = &regions.pairs[index];
25             if (!continuing) {
26                 continuation_start = byte_index;
27                 append(regions.continuation, &byte_index, active.value);
28                 if (active.value.len != 0) append(regions.continuation, &byte_index, " ");
29                 continuing = true;
30             } else {
31                 append(regions.continuation, &byte_index, " ");
32             }
33             append(regions.continuation, &byte_index, value);
34             active.value = regions.continuation[continuation_start..byte_index];
35         },
36     };
37     std.debug.assert(pair_index == regions.pairs.len);
38     std.debug.assert(byte_index == regions.continuation.len);
39     return .{
40         .metadata = .{ .pairs = regions.pairs },
41         .body = markdown[regions.plan.body_start..],
42     };
43 }
44 
45 fn append(destination: []u8, index: *usize, bytes: []const u8) void {
46     std.debug.assert(index.* <= destination.len);
47     std.debug.assert(bytes.len <= destination.len - index.*);
48     @memcpy(destination[index.*..][0..bytes.len], bytes);
49     index.* += bytes.len;
50 }