style: adopt TigerStyle across src/; add docs/TIGER_STYLE.md
Wrap signatures and long expressions to the 100-column limit and make every file zig fmt clean. Semantics-preserving throughout: ignoring whitespace and the trailing commas that wrapping introduces, every file here is byte-identical to its predecessor, and the one apparent exception is a warning string split with `++`, which concatenates at comptime to the same bytes. src/index.zig and src/commands.zig are reformatted in the commits that follow, because their reformat is interleaved with in-flight changes to them and separating the two would need the reformat re-derived rather than moved.
This commit is contained in:
165
src/bson.zig
165
src/bson.zig
@@ -122,7 +122,11 @@ pub const Document = struct {
|
||||
}
|
||||
|
||||
/// Serialize the full document (length-prefixed) into `out`.
|
||||
pub fn to_bytes(self: *const Document, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
|
||||
pub fn to_bytes(
|
||||
self: *const Document,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) !void {
|
||||
try write_doc(self.pairs, gpa, out);
|
||||
}
|
||||
};
|
||||
@@ -157,7 +161,12 @@ const Parser = struct {
|
||||
|
||||
const ParseError = error{ InvalidBson, OutOfMemory };
|
||||
|
||||
fn parse_doc_into(allocator: std.mem.Allocator, bytes: []const u8, idx: *usize, borrow: bool) ParseError![]const Pair {
|
||||
fn parse_doc_into(
|
||||
allocator: std.mem.Allocator,
|
||||
bytes: []const u8,
|
||||
idx: *usize,
|
||||
borrow: bool,
|
||||
) ParseError![]const Pair {
|
||||
const p = Parser{ .allocator = allocator, .bytes = bytes, .borrow = borrow };
|
||||
return parse_doc_inner(p, idx);
|
||||
}
|
||||
@@ -356,7 +365,10 @@ fn parse_array(p: Parser, idx: *usize) ParseError![]const Value {
|
||||
/// A borrowed parse of `bytes` into an arena: keys, strings, binary and
|
||||
/// regex payloads point into `bytes`; only the pair/value skeleton is
|
||||
/// allocated. The result is valid while both `bytes` and `arena` live.
|
||||
pub fn spine(allocator: std.mem.Allocator, bytes: []const u8) error{ InvalidBson, OutOfMemory }![]const Pair {
|
||||
pub fn spine(
|
||||
allocator: std.mem.Allocator,
|
||||
bytes: []const u8,
|
||||
) error{ InvalidBson, OutOfMemory }![]const Pair {
|
||||
var idx: usize = 0;
|
||||
return parse_doc_into(allocator, bytes, &idx, true);
|
||||
}
|
||||
@@ -414,7 +426,12 @@ pub fn skip_value(bytes: []const u8, idx: *usize, tag: u8) error{InvalidBson}!vo
|
||||
/// Read one value of `tag` into a Value whose leaves borrow `bytes`; nested
|
||||
/// documents and arrays materialize their spines into `arena`. Advances
|
||||
/// `idx` past the value.
|
||||
pub fn read_value(allocator: std.mem.Allocator, bytes: []const u8, idx: *usize, tag: u8) error{ InvalidBson, OutOfMemory }!Value {
|
||||
pub fn read_value(
|
||||
allocator: std.mem.Allocator,
|
||||
bytes: []const u8,
|
||||
idx: *usize,
|
||||
tag: u8,
|
||||
) error{ InvalidBson, OutOfMemory }!Value {
|
||||
switch (tag) {
|
||||
0x01 => {
|
||||
try ensure_available(bytes, idx.*, 8);
|
||||
@@ -542,7 +559,11 @@ pub fn read_value(allocator: std.mem.Allocator, bytes: []const u8, idx: *usize,
|
||||
|
||||
/// The value stored under `key` in a document's bytes, or null when absent.
|
||||
/// Nested documents and arrays materialize their spines into `arena`.
|
||||
pub fn get_at(arena: std.mem.Allocator, bytes: []const u8, key: []const u8) error{ InvalidBson, OutOfMemory }!?Value {
|
||||
pub fn get_at(
|
||||
arena: std.mem.Allocator,
|
||||
bytes: []const u8,
|
||||
key: []const u8,
|
||||
) error{ InvalidBson, OutOfMemory }!?Value {
|
||||
var idx: usize = 4;
|
||||
while (idx + 1 < bytes.len and bytes[idx] != 0) {
|
||||
const tag = bytes[idx];
|
||||
@@ -565,7 +586,11 @@ pub const SerializeError = error{
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
pub fn write_value(v: Value, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
pub fn write_value(
|
||||
v: Value,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
switch (v) {
|
||||
.double => |d| {
|
||||
var buf: [8]u8 = undefined;
|
||||
@@ -618,13 +643,21 @@ pub fn write_value(v: Value, gpa: std.mem.Allocator, out: *std.ArrayListUnmanage
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_cstring(s: []const u8, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
pub fn write_cstring(
|
||||
s: []const u8,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
if (std.mem.indexOfScalar(u8, s, 0) != null) return error.BsonNulInKey;
|
||||
try out.appendSlice(gpa, s);
|
||||
try out.append(gpa, 0);
|
||||
}
|
||||
|
||||
pub fn write_string(s: []const u8, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
pub fn write_string(
|
||||
s: []const u8,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
if (s.len + 1 > std.math.maxInt(u32)) return error.BsonTooLarge;
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeInt(u32, &buf, @intCast(s.len + 1), .little);
|
||||
@@ -633,7 +666,11 @@ pub fn write_string(s: []const u8, gpa: std.mem.Allocator, out: *std.ArrayListUn
|
||||
try out.append(gpa, 0);
|
||||
}
|
||||
|
||||
pub fn write_element(pair: Pair, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
pub fn write_element(
|
||||
pair: Pair,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
try out.append(gpa, pair.value.type_tag());
|
||||
try write_cstring(pair.key, gpa, out);
|
||||
try write_value(pair.value, gpa, out);
|
||||
@@ -648,7 +685,11 @@ fn begin_frame(gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) Seriali
|
||||
}
|
||||
|
||||
/// Terminate the frame opened at `len_pos` and patch in its total length.
|
||||
fn end_frame(gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), len_pos: usize) SerializeError!void {
|
||||
fn end_frame(
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
len_pos: usize,
|
||||
) SerializeError!void {
|
||||
try out.append(gpa, 0);
|
||||
const total = out.items.len - len_pos;
|
||||
if (total > std.math.maxInt(u32)) return error.BsonTooLarge;
|
||||
@@ -656,13 +697,21 @@ fn end_frame(gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), len_pos:
|
||||
}
|
||||
|
||||
/// Write a length-prefixed document. Length is patched in after the body.
|
||||
pub fn write_doc(pairs: []const Pair, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
pub fn write_doc(
|
||||
pairs: []const Pair,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
const len_pos = try begin_frame(gpa, out);
|
||||
for (pairs) |p| try write_element(p, gpa, out);
|
||||
try end_frame(gpa, out, len_pos);
|
||||
}
|
||||
|
||||
fn write_array(items: []const Value, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) SerializeError!void {
|
||||
fn write_array(
|
||||
items: []const Value,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) SerializeError!void {
|
||||
const len_pos = try begin_frame(gpa, out);
|
||||
var buf: [16]u8 = undefined;
|
||||
for (items, 0..) |item, i| {
|
||||
@@ -686,7 +735,11 @@ pub fn serialize_value(gpa: std.mem.Allocator, v: Value) ![]u8 {
|
||||
/// Append the serialized-key bytes of `v` (type tag + payload) to `out`. The
|
||||
/// appending form of serialize_value, for callers reusing one scratch buffer
|
||||
/// across many keys.
|
||||
pub fn write_serialized_value(v: Value, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
|
||||
pub fn write_serialized_value(
|
||||
v: Value,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) !void {
|
||||
try out.append(gpa, v.type_tag());
|
||||
try write_value(v, gpa, out);
|
||||
}
|
||||
@@ -709,7 +762,10 @@ pub fn copy_value(arena: std.mem.Allocator, v: Value) std.mem.Allocator.Error!Va
|
||||
};
|
||||
}
|
||||
|
||||
pub fn copy_pairs(arena: std.mem.Allocator, pairs: []const Pair) std.mem.Allocator.Error![]const Pair {
|
||||
pub fn copy_pairs(
|
||||
arena: std.mem.Allocator,
|
||||
pairs: []const Pair,
|
||||
) std.mem.Allocator.Error![]const Pair {
|
||||
const out = try arena.alloc(Pair, pairs.len);
|
||||
for (pairs, 0..) |p, i| {
|
||||
out[i] = .{ .key = try arena.dupe(u8, p.key), .value = try copy_value(arena, p.value) };
|
||||
@@ -717,7 +773,10 @@ pub fn copy_pairs(arena: std.mem.Allocator, pairs: []const Pair) std.mem.Allocat
|
||||
return out;
|
||||
}
|
||||
|
||||
fn copy_values(arena: std.mem.Allocator, items: []const Value) std.mem.Allocator.Error![]const Value {
|
||||
fn copy_values(
|
||||
arena: std.mem.Allocator,
|
||||
items: []const Value,
|
||||
) std.mem.Allocator.Error![]const Value {
|
||||
const out = try arena.alloc(Value, items.len);
|
||||
for (items, 0..) |item, i| out[i] = try copy_value(arena, item);
|
||||
return out;
|
||||
@@ -879,7 +938,11 @@ pub fn encoded_leading_datetime(key: []const u8) ?i64 {
|
||||
/// ambiguous. Escaping `00` as `00 FF` fixes both problems at once: a real
|
||||
/// NUL encodes above the `00 00` terminator, and any byte >= 01 is above it
|
||||
/// too, so "shorter is less" falls out to match `std.mem.order`.
|
||||
fn encode_escaped(bytes: []const u8, gpa: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
|
||||
fn encode_escaped(
|
||||
bytes: []const u8,
|
||||
gpa: std.mem.Allocator,
|
||||
out: *std.ArrayListUnmanaged(u8),
|
||||
) !void {
|
||||
for (bytes) |b| {
|
||||
try out.append(gpa, b);
|
||||
if (b == 0x00) try out.append(gpa, 0xFF);
|
||||
@@ -1128,23 +1191,47 @@ test "encode_key order matches bson.compare on every pair" {
|
||||
.min_key,
|
||||
.null,
|
||||
// Numbers: cross-type equality, sign, zero, extremes, NaN.
|
||||
.{ .int32 = -2147483648 }, .{ .int32 = -1 }, .{ .int32 = 0 },
|
||||
.{ .int32 = 1 }, .{ .int32 = 2 }, .{ .int32 = 2147483647 },
|
||||
.{ .int64 = -9223372036854775807 }, .{ .int64 = -1 }, .{ .int64 = 0 },
|
||||
.{ .int64 = 1 }, .{ .int64 = 9223372036854775807 },
|
||||
.{ .double = -std.math.inf(f64) }, .{ .double = -1.5 }, .{ .double = -0.0 },
|
||||
.{ .double = 0.0 }, .{ .double = 0.5 }, .{ .double = 1.0 },
|
||||
.{ .double = 1.5 }, .{ .double = std.math.inf(f64) },
|
||||
.{ .int32 = -2147483648 },
|
||||
.{ .int32 = -1 },
|
||||
.{ .int32 = 0 },
|
||||
.{ .int32 = 1 },
|
||||
.{ .int32 = 2 },
|
||||
.{ .int32 = 2147483647 },
|
||||
.{ .int64 = -9223372036854775807 },
|
||||
.{ .int64 = -1 },
|
||||
.{ .int64 = 0 },
|
||||
.{ .int64 = 1 },
|
||||
.{ .int64 = 9223372036854775807 },
|
||||
.{ .double = -std.math.inf(f64) },
|
||||
.{ .double = -1.5 },
|
||||
.{ .double = -0.0 },
|
||||
.{ .double = 0.0 },
|
||||
.{ .double = 0.5 },
|
||||
.{ .double = 1.0 },
|
||||
.{ .double = 1.5 },
|
||||
.{ .double = std.math.inf(f64) },
|
||||
.{ .double = std.math.nan(f64) },
|
||||
// Strings, including embedded NUL and prefix relationships.
|
||||
.{ .string = "" }, .{ .string = "\x00" }, .{ .string = "\x00b" },
|
||||
.{ .string = "a" }, .{ .string = "a\x00" }, .{ .string = "a\x00b" },
|
||||
.{ .string = "ab" }, .{ .string = "b" }, .{ .string = "\xff" },
|
||||
.{ .string = "" },
|
||||
.{ .string = "\x00" },
|
||||
.{ .string = "\x00b" },
|
||||
.{ .string = "a" },
|
||||
.{ .string = "a\x00" },
|
||||
.{ .string = "a\x00b" },
|
||||
.{ .string = "ab" },
|
||||
.{ .string = "b" },
|
||||
.{ .string = "\xff" },
|
||||
// Same rank as string, so these must interleave with them.
|
||||
.{ .symbol = "a" }, .{ .code = "ab" },
|
||||
.{ .doc = &.{} }, .{ .doc = &nested }, .{ .doc = &nested2 },
|
||||
.{ .doc = &nested_l }, .{ .doc = &two_pairs },
|
||||
.{ .array = &.{} }, .{ .array = &arr1 }, .{ .array = &arr2 },
|
||||
.{ .symbol = "a" },
|
||||
.{ .code = "ab" },
|
||||
.{ .doc = &.{} },
|
||||
.{ .doc = &nested },
|
||||
.{ .doc = &nested2 },
|
||||
.{ .doc = &nested_l },
|
||||
.{ .doc = &two_pairs },
|
||||
.{ .array = &.{} },
|
||||
.{ .array = &arr1 },
|
||||
.{ .array = &arr2 },
|
||||
.{ .array = &arr_str },
|
||||
// Binary orders by length first, then bytes, then subtype.
|
||||
.{ .binary = .{ .subtype = 0, .data = "" } },
|
||||
@@ -1155,11 +1242,15 @@ test "encode_key order matches bson.compare on every pair" {
|
||||
.{ .object_id = [_]u8{0} ** 12 },
|
||||
.{ .object_id = [_]u8{0} ** 11 ++ [_]u8{1} },
|
||||
.{ .object_id = [_]u8{255} ** 12 },
|
||||
.{ .bool = false }, .{ .bool = true },
|
||||
.{ .datetime = std.math.minInt(i64) }, .{ .datetime = -1 },
|
||||
.{ .datetime = 0 }, .{ .datetime = 1 },
|
||||
.{ .bool = false },
|
||||
.{ .bool = true },
|
||||
.{ .datetime = std.math.minInt(i64) },
|
||||
.{ .datetime = -1 },
|
||||
.{ .datetime = 0 },
|
||||
.{ .datetime = 1 },
|
||||
.{ .datetime = std.math.maxInt(i64) },
|
||||
.{ .timestamp = 0 }, .{ .timestamp = 1 },
|
||||
.{ .timestamp = 0 },
|
||||
.{ .timestamp = 1 },
|
||||
.{ .timestamp = std.math.maxInt(u64) },
|
||||
.{ .regex = .{ .pattern = "a", .options = "" } },
|
||||
.{ .regex = .{ .pattern = "a", .options = "i" } },
|
||||
@@ -1199,9 +1290,9 @@ test "encode_key concatenates into unambiguous compound keys" {
|
||||
// against the component-wise order they are supposed to reproduce.
|
||||
const gpa = testing.allocator;
|
||||
const parts = [_]Value{
|
||||
.{ .string = "" }, .{ .string = "a" }, .{ .string = "a\x00" },
|
||||
.{ .string = "ab" }, .{ .int32 = 1 }, .{ .int32 = 2 },
|
||||
.null, .{ .array = &.{} }, .{ .bool = true },
|
||||
.{ .string = "" }, .{ .string = "a" }, .{ .string = "a\x00" },
|
||||
.{ .string = "ab" }, .{ .int32 = 1 }, .{ .int32 = 2 },
|
||||
.null, .{ .array = &.{} }, .{ .bool = true },
|
||||
};
|
||||
|
||||
for (parts) |a1| {
|
||||
|
||||
Reference in New Issue
Block a user