1pub mod admin;
9pub mod authorship;
10pub mod chunks;
11pub mod code_fields;
12pub mod codes;
13pub mod coordinates;
14pub mod device_gone;
15pub mod dismissal;
16pub mod error;
17pub mod file;
18pub mod file_reference;
19pub mod floor;
20pub mod invite_end;
21pub mod key;
22mod kinds;
23pub mod loss;
24pub mod merge_fields;
25mod merge_wire;
26pub mod objects;
27pub mod path;
28mod sealed;
29pub mod sealed_floor;
30pub mod sealed_key;
31pub mod sealed_single;
32pub mod sealed_slot;
33pub mod sealed_snapshot;
34pub mod sealed_stream;
35pub mod sealed_write;
36pub mod sequence;
37pub mod snapshot;
38pub mod snapshot_rows;
39pub mod snapshot_stream;
40pub mod value;
41mod version;
42mod wire;
43pub mod write;
44pub mod write_sources;
45pub mod write_stream;
46pub mod writes_slot;
47
48#[cfg(any(test, feature = "test-utils"))]
49pub mod test_utils;
50
51pub use error::Error;
52pub use sealed::STORED_CHUNK_OVERHEAD;
53pub use version::{FormatVersion, RequiredUpdate};
54
55use admin::StoreChange;
56use error::bound;
57use objects::JoinRequest;
58use wire::{decode_frame, Encoder, Wire, MAX_OBJECT};
59
60pub const FORMAT_VERSION: u16 = FormatVersion::CURRENT.number();
62pub const FRAME_PREFIX_LEN: usize = 7;
64
65#[derive(Clone, Debug, PartialEq, Eq)]
69pub enum Object {
70 Admin(StoreChange),
72 JoinRequest(JoinRequest),
74}
75
76impl Object {
77 pub fn encode(&self) -> Result<Vec<u8>, Error> {
79 self.encode_in(FormatVersion::CURRENT)
80 }
81
82 pub fn encode_in(&self, format: FormatVersion) -> Result<Vec<u8>, Error> {
84 self.validate()?;
85 let FormatVersion::V1 = format;
86 match self {
87 Self::Admin(v) => encode_frame_in(kinds::ADMIN, format, |out| v.put(out)),
88 Self::JoinRequest(v) => {
89 encode_frame_in(kinds::JOIN_REQUEST_FRAME, format, |out| v.put(out))
90 }
91 }
92 }
93 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
97 let (kind, mut input) = decode_frame(bytes)?;
98 let object = match kind {
99 kinds::ADMIN => Self::Admin(Wire::get(&mut input)?),
100 kinds::JOIN_REQUEST_FRAME => Self::JoinRequest(Wire::get(&mut input)?),
101 tag => return Err(Error::UnknownTag { field: "object kind", tag }),
102 };
103 input.finish()?;
104 object.validate()?;
105 Ok(object)
106 }
107 fn validate(&self) -> Result<(), Error> {
108 match self {
109 Self::Admin(v) => v.validate(),
110 Self::JoinRequest(v) => v.validate(),
111 }
112 }
113}
114
115pub fn frame_length(prefix: &[u8]) -> Result<usize, Error> {
119 let bytes = prefix.get(..3).ok_or(Error::Truncated)?;
120 if !kinds::is_frame(bytes[0]) {
121 return Err(Error::UnknownTag { field: "object kind", tag: bytes[0] });
122 }
123 let FormatVersion::V1 = FormatVersion::decode(bytes)?;
124 let bytes = prefix.get(..FRAME_PREFIX_LEN).ok_or(Error::Truncated)?;
125 let size = u32::from_be_bytes([bytes[3], bytes[4], bytes[5], bytes[6]]) as usize;
126 bound(size, MAX_OBJECT - FRAME_PREFIX_LEN, "frame payload")?;
127 Ok(size + FRAME_PREFIX_LEN)
128}
129
130pub(crate) fn encode_frame<T: Wire>(kind: u8, value: &T) -> Result<Vec<u8>, Error> {
131 encode_frame_with(kind, |out| value.put(out))
132}
133
134pub(crate) fn encode_frame_with(
135 kind: u8,
136 put: impl FnOnce(&mut Encoder) -> Result<(), Error>,
137) -> Result<Vec<u8>, Error> {
138 encode_frame_in(kind, FormatVersion::CURRENT, put)
139}
140
141pub(crate) fn frame_prefix(
143 kind: u8,
144 format: FormatVersion,
145 payload: u32,
146) -> [u8; FRAME_PREFIX_LEN] {
147 let [a, b, c] = format.prefix(kind);
148 let [d, e, f, g] = payload.to_be_bytes();
149 [a, b, c, d, e, f, g]
150}
151
152fn encode_frame_in(
153 kind: u8,
154 format: FormatVersion,
155 put: impl FnOnce(&mut Encoder) -> Result<(), Error>,
156) -> Result<Vec<u8>, Error> {
157 let mut out = Encoder::new();
158 out.bytes(&frame_prefix(kind, format, 0))?;
159 put(&mut out)?;
160 let size = (out.bytes.len() - FRAME_PREFIX_LEN) as u32;
161 out.bytes[3..7].copy_from_slice(&size.to_be_bytes());
162 Ok(out.bytes)
163}
164
165#[cfg(test)]
166#[path = "lib_tests.rs"]
167mod tests;
168
169mod member_access;
170pub use member_access::MemberAccess;