1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//! The canonical value and object model (OBJECT_MODEL.md §1, §6).
use crate::family::Family;
use crate::gid::Gid;
/// A canonical value.
///
/// Values are typed by the schema in which they appear; `Value` preserves the
/// exact canonical content. [`Value::Raw`] carries opaque canonical bytes for
/// extension fields (tags 0x80..=0xEF) so older readers can retain them
/// losslessly.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Value {
/// Unsigned integer (canonical LEB128).
U(u64),
/// Signed integer (zigzag).
I(i64),
/// Boolean (single byte 0x00/0x01).
B(bool),
/// Raw bytes.
Bytes(Vec<u8>),
/// UTF-8 string, byte-identical, never normalized.
Str(String),
/// Object reference (33 bytes).
Gid(Gid),
/// A canonical field sequence.
Record(Vec<Field>),
/// A canonical array.
Array(Vec<Value>),
/// Opaque canonical value bytes for an extension field.
Raw(Vec<u8>),
}
/// A single field: tag plus value.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Field {
pub tag: u8,
pub value: Value,
}
impl Field {
pub const fn new(tag: u8, value: Value) -> Field {
Field { tag, value }
}
}
/// The object body: raw bytes for `blob`, a field sequence otherwise.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Body {
/// Raw bytes (blob family only).
Blob(Vec<u8>),
/// A canonical field sequence.
Fields(Vec<Field>),
}
/// A canonical object: envelope metadata plus body.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Object {
pub family: Family,
pub schemever: u8,
pub body: Body,
}
impl Object {
/// A blob object with the given raw content.
pub fn blob(bytes: Vec<u8>) -> Object {
Object {
family: Family::Blob,
schemever: 1,
body: Body::Blob(bytes),
}
}
/// An object with a field-sequence body.
pub fn fields(family: Family, body: Vec<Field>) -> Object {
Object {
family,
schemever: 1,
body: Body::Fields(body),
}
}
/// The blob content of a blob object.
pub fn blob_bytes(&self) -> Option<&[u8]> {
match &self.body {
Body::Blob(b) => Some(b),
Body::Fields(_) => None,
}
}
/// The field sequence of a non-blob object.
pub fn field_sequence(&self) -> Option<&[Field]> {
match &self.body {
Body::Fields(f) => Some(f),
Body::Blob(_) => None,
}
}
}