acyclic_fs/kernel/
generation.rs1use super::codec::{CanonicalDecodeError, DecodeLimits, Decoder, Encoder};
4use super::types::digest_object;
5use crate::foundation::{Digest, FileId, GenerationId, VolumeId};
6use crate::storage::{ObjectId, ObjectKind, object_digest};
7
8const DOMAIN: &[u8; 8] = b"ACYFSGEN";
9const VERSION: u16 = 1;
10const MAXIMUM_PARENTS: u32 = 2;
11pub const MAXIMUM_GENERATION_ROOT_BYTES: u64 = 150;
13
14#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct GenerationRoot {
17 pub volume_id: VolumeId,
19 pub root_file_id: FileId,
21 pub file_table: ObjectId,
23 pub parents: Vec<GenerationId>,
25 pub required_features: u64,
27}
28
29impl GenerationRoot {
30 fn validate(&self) -> Result<(), CanonicalDecodeError> {
31 if self.file_table.kind != ObjectKind::FileTablePage {
32 return Err(invariant("generation file table has the wrong object kind"));
33 }
34 if self.parents.len() > usize::try_from(MAXIMUM_PARENTS).unwrap_or(usize::MAX) {
35 return Err(invariant("generation has too many parents"));
36 }
37 if let [first, second] = self.parents.as_slice()
38 && first == second
39 {
40 return Err(invariant("generation parents are duplicated"));
41 }
42 if self.required_features != 0 {
43 return Err(invariant("generation requires unsupported format features"));
44 }
45 Ok(())
46 }
47}
48
49pub fn encode_generation_root(root: &GenerationRoot) -> Result<Vec<u8>, CanonicalDecodeError> {
56 root.validate()?;
57 let mut encoder = Encoder::new(DOMAIN, VERSION);
58 encoder.fixed(&root.volume_id.into_bytes());
59 encoder.fixed(&root.root_file_id.into_bytes());
60 encoder.fixed(root.file_table.digest.as_bytes());
61 encoder
62 .u32(u32::try_from(root.parents.len()).map_err(|_| CanonicalDecodeError::LengthOverflow)?);
63 for parent in &root.parents {
64 encoder.fixed(parent.digest().as_bytes());
65 }
66 encoder.u64(root.required_features);
67 Ok(encoder.finish())
68}
69
70pub fn decode_generation_root(
77 bytes: &[u8],
78 limits: DecodeLimits,
79) -> Result<GenerationRoot, CanonicalDecodeError> {
80 let mut decoder = Decoder::new(bytes, DOMAIN, VERSION, limits.maximum_object_bytes)?;
81 let volume_id = VolumeId::from_bytes(decoder.fixed()?);
82 let root_file_id = FileId::from_bytes(decoder.fixed()?);
83 let file_table = digest_object(ObjectKind::FileTablePage, decoder.fixed()?);
84 let parent_count = decoder.u32()?;
85 if parent_count > MAXIMUM_PARENTS {
86 return Err(CanonicalDecodeError::FieldTooLarge {
87 observed: parent_count,
88 maximum: MAXIMUM_PARENTS,
89 });
90 }
91 let parent_count =
92 usize::try_from(parent_count).map_err(|_| CanonicalDecodeError::LengthOverflow)?;
93 let mut parents = Vec::new();
94 parents
95 .try_reserve_exact(parent_count)
96 .map_err(|_| CanonicalDecodeError::AllocationFailed)?;
97 for _ in 0..parent_count {
98 parents.push(GenerationId::new(Digest::from_bytes(decoder.fixed()?)));
99 }
100 let required_features = decoder.u64()?;
101 decoder.finish()?;
102 let root = GenerationRoot {
103 volume_id,
104 root_file_id,
105 file_table,
106 parents,
107 required_features,
108 };
109 root.validate()?;
110 Ok(root)
111}
112
113pub(crate) fn generation_root_parent_count(
114 bytes: &[u8],
115 limits: DecodeLimits,
116) -> Result<usize, CanonicalDecodeError> {
117 let mut decoder = Decoder::new(bytes, DOMAIN, VERSION, limits.maximum_object_bytes)?;
118 let _: [u8; 16] = decoder.fixed()?;
119 let _: [u8; 16] = decoder.fixed()?;
120 let _: [u8; 32] = decoder.fixed()?;
121 let parent_count = decoder.u32()?;
122 if parent_count > MAXIMUM_PARENTS {
123 return Err(CanonicalDecodeError::FieldTooLarge {
124 observed: parent_count,
125 maximum: MAXIMUM_PARENTS,
126 });
127 }
128 usize::try_from(parent_count).map_err(|_| CanonicalDecodeError::LengthOverflow)
129}
130
131pub fn generation_root_id(
137 root: &GenerationRoot,
138) -> Result<(ObjectId, GenerationId), CanonicalDecodeError> {
139 let bytes = encode_generation_root(root)?;
140 let object = ObjectId {
141 kind: ObjectKind::GenerationRoot,
142 digest: object_digest(ObjectKind::GenerationRoot, &bytes),
143 };
144 Ok((object, GenerationId::new(object.digest)))
145}
146
147fn invariant(message: &str) -> CanonicalDecodeError {
148 CanonicalDecodeError::Invariant(message.to_owned())
149}
150
151#[cfg(test)]
152#[path = "tests/generation.rs"]
153mod tests;