1use crate::lsm_tree::{PersistentLayerHeader, PersistentLayerInfo};
6use crate::object_store::allocator::{AllocatorInfo, AllocatorKey, AllocatorValue};
7use crate::object_store::journal::super_block::{
8 SuperBlockHeader, SuperBlockRecord, SuperBlockRecordV40, SuperBlockRecordV41,
9 SuperBlockRecordV43, SuperBlockRecordV46, SuperBlockRecordV47, SuperBlockRecordV49,
10};
11use crate::object_store::journal::{
12 JournalRecord, JournalRecordV40, JournalRecordV41, JournalRecordV42, JournalRecordV43,
13 JournalRecordV46, JournalRecordV47, JournalRecordV49,
14};
15use crate::object_store::object_record::{
16 FsverityMetadata, FsverityMetadataV33, ObjectKey, ObjectKeyV40, ObjectValue, ObjectValueV40,
17 ObjectValueV41, ObjectValueV46, ObjectValueV47, ObjectValueV49,
18};
19use crate::object_store::transaction::{
20 Mutation, MutationV40, MutationV41, MutationV43, MutationV46, MutationV47, MutationV49,
21};
22use crate::object_store::{EncryptedMutations, EncryptedMutationsV40, StoreInfo, StoreInfoV40};
23use crate::serialized_types::{Version, Versioned, VersionedLatest, versioned_type};
24
25pub const LATEST_VERSION: Version = Version { major: 50, minor: 0 };
35
36pub const EARLIEST_SUPPORTED_VERSION: Version = Version { major: 40, minor: 0 };
45
46pub const SMALL_SUPERBLOCK_VERSION: Version = Version { major: 44, minor: 0 };
49
50pub const FIRST_EXTENT_IN_SUPERBLOCK_VERSION: Version = Version { major: 45, minor: 0 };
53
54versioned_type! {
55 32.. => AllocatorInfo,
56}
57versioned_type! {
58 32.. => AllocatorKey,
59}
60versioned_type! {
61 32.. => AllocatorValue,
62}
63versioned_type! {
64 49.. => EncryptedMutations,
65 40.. => EncryptedMutationsV40,
66}
67versioned_type! {
68 50.. => FsverityMetadata,
69 33.. => FsverityMetadataV33,
70}
71versioned_type! {
72 50.. => JournalRecord,
73 49.. => JournalRecordV49,
74 47.. => JournalRecordV47,
75 46.. => JournalRecordV46,
76 43.. => JournalRecordV43,
77 42.. => JournalRecordV42,
78 41.. => JournalRecordV41,
79 40.. => JournalRecordV40,
80}
81versioned_type! {
82 50.. => Mutation,
83 49.. => MutationV49,
84 47.. => MutationV47,
85 46.. => MutationV46,
86 43.. => MutationV43,
87 41.. => MutationV41,
88 40.. => MutationV40,
89}
90versioned_type! {
91 43.. => ObjectKey,
92 40.. => ObjectKeyV40,
93}
94versioned_type! {
95 50.. => ObjectValue,
96 49.. => ObjectValueV49,
97 47.. => ObjectValueV47,
98 46.. => ObjectValueV46,
99 41.. => ObjectValueV41,
100 40.. => ObjectValueV40,
101}
102versioned_type! {
103 39.. => PersistentLayerHeader,
104}
105versioned_type! {
106 39.. => PersistentLayerInfo,
107}
108versioned_type! {
109 49.. => StoreInfo,
110 40.. => StoreInfoV40,
111}
112versioned_type! {
113 32.. => SuperBlockHeader,
114}
115versioned_type! {
116 50.. => SuperBlockRecord,
117 49.. => SuperBlockRecordV49,
118 47.. => SuperBlockRecordV47,
119 46.. => SuperBlockRecordV46,
120 43.. => SuperBlockRecordV43,
121 41.. => SuperBlockRecordV41,
122 40.. => SuperBlockRecordV40,
123}
124
125#[cfg(test)]
126mod tests {
127 use crate::lsm_tree::{
128 PersistentLayerHeader, PersistentLayerHeaderV39, PersistentLayerInfo,
129 PersistentLayerInfoV39,
130 };
131 use crate::object_store::allocator::{
132 AllocatorInfo, AllocatorInfoV32, AllocatorKey, AllocatorKeyV32, AllocatorValue,
133 AllocatorValueV32,
134 };
135 use crate::object_store::journal::super_block::{
136 SuperBlockHeader, SuperBlockHeaderV32, SuperBlockRecord, SuperBlockRecordV40,
137 SuperBlockRecordV41, SuperBlockRecordV43, SuperBlockRecordV46, SuperBlockRecordV47,
138 SuperBlockRecordV49, SuperBlockRecordV50,
139 };
140 use crate::object_store::journal::{
141 JournalRecord, JournalRecordV40, JournalRecordV41, JournalRecordV42, JournalRecordV43,
142 JournalRecordV46, JournalRecordV47, JournalRecordV49, JournalRecordV50,
143 };
144 use crate::object_store::object_record::{
145 FsverityMetadataV33, FsverityMetadataV50, ObjectKey, ObjectKeyV40, ObjectKeyV43,
146 ObjectValue, ObjectValueV40, ObjectValueV41, ObjectValueV46, ObjectValueV47,
147 ObjectValueV49, ObjectValueV50,
148 };
149 use crate::object_store::transaction::{
150 MutationV40, MutationV41, MutationV43, MutationV46, MutationV47, MutationV49, MutationV50,
151 };
152 use crate::object_store::{
153 EncryptedMutations, EncryptedMutationsV40, EncryptedMutationsV49, FsverityMetadata,
154 Mutation, StoreInfo, StoreInfoV40, StoreInfoV49,
155 };
156
157 fn assert_type_fprint<T: fprint::TypeFingerprint>(fp: &str) -> bool {
158 if T::fingerprint() != fp {
159 eprintln!(
160 " success &= assert_type_fprint::<{}>(\"{}\");",
161 std::any::type_name::<T>(),
162 T::fingerprint()
163 );
164 false
165 } else {
166 true
167 }
168 }
169
170 #[test]
171 fn type_fprint_latest_version() {
172 eprintln!("latest_version fingerprints:");
173 let mut success = true;
177 success &= assert_type_fprint::<AllocatorInfo>(
178 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
179 );
180 success &= assert_type_fprint::<AllocatorKey>("struct {device_range:Range<u64>}");
181 success &=
182 assert_type_fprint::<AllocatorValue>("enum {None,Abs(count:u64,owner_object_id:u64)}");
183 success &= assert_type_fprint::<EncryptedMutations>(
184 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes},)>}",
185 );
186 success &= assert_type_fprint::<JournalRecord>(
187 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
188 );
189 success &= assert_type_fprint::<FsverityMetadata>(
190 "enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)}",
191 );
192 success &= assert_type_fprint::<Mutation>(
193 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
194 );
195 success &= assert_type_fprint::<ObjectKey>(
196 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
197 );
198 success &= assert_type_fprint::<ObjectValue>(
199 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})}",
200 );
201 success &=
202 assert_type_fprint::<PersistentLayerHeader>("struct {magic:[u8;8],block_size:u64}");
203 success &= assert_type_fprint::<PersistentLayerInfo>(
204 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
205 );
206 success &= assert_type_fprint::<StoreInfo>(
207 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
208 );
209 success &= assert_type_fprint::<SuperBlockHeader>(
210 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
211 );
212 success &= assert_type_fprint::<SuperBlockRecord>(
213 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64}),End}",
214 );
215 assert!(success, "One or more versioned types have different type fingerprint.");
216 }
217
218 #[test]
219 fn type_fprint_v50() {
220 let mut success = true;
221 success &= assert_type_fprint::<AllocatorInfoV32>(
222 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
223 );
224 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
225 success &= assert_type_fprint::<AllocatorValueV32>(
226 "enum {None,Abs(count:u64,owner_object_id:u64)}",
227 );
228
229 success &= assert_type_fprint::<EncryptedMutationsV49>(
230 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes},)>}",
231 );
232 success &= assert_type_fprint::<JournalRecordV50>(
233 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
234 );
235 success &= assert_type_fprint::<FsverityMetadataV50>(
236 "enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)}",
237 );
238 success &= assert_type_fprint::<MutationV50>(
239 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
240 );
241 success &= assert_type_fprint::<ObjectValueV50>(
242 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})}",
243 );
244 success &= assert_type_fprint::<SuperBlockRecordV50>(
245 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64}),End}",
246 );
247 success &= assert_type_fprint::<ObjectKeyV43>(
248 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
249 );
250 success &= assert_type_fprint::<ObjectValueV50>(
251 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})}",
252 );
253 success &=
254 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
255 success &= assert_type_fprint::<PersistentLayerInfoV39>(
256 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
257 );
258 success &= assert_type_fprint::<StoreInfoV49>(
259 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
260 );
261 success &= assert_type_fprint::<SuperBlockHeaderV32>(
262 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
263 );
264 success &= assert_type_fprint::<SuperBlockRecordV50>(
265 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:enum {Internal(enum {Sha256([u8;32]),Sha512(Vec<u8>)},Vec<u8>),F2fs(Range<u64>)})},sequence:u64}),End}",
266 );
267 assert!(success, "One or more versioned types have different type fingerprint.");
268 }
269
270 #[test]
271 fn type_fprint_v49() {
272 let mut success = true;
273 success &= assert_type_fprint::<AllocatorInfoV32>(
274 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
275 );
276 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
277 success &= assert_type_fprint::<AllocatorValueV32>(
278 "enum {None,Abs(count:u64,owner_object_id:u64)}",
279 );
280
281 success &= assert_type_fprint::<EncryptedMutationsV49>(
282 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes},)>}",
283 );
284 success &= assert_type_fprint::<JournalRecordV49>(
285 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
286 );
287 success &= assert_type_fprint::<FsverityMetadataV33>(
288 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
289 );
290 success &= assert_type_fprint::<MutationV49>(
291 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
292 );
293 success &= assert_type_fprint::<ObjectKeyV43>(
294 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
295 );
296 success &= assert_type_fprint::<ObjectValueV49>(
297 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
298 );
299 success &=
300 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
301 success &= assert_type_fprint::<PersistentLayerInfoV39>(
302 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
303 );
304 success &= assert_type_fprint::<StoreInfoV49>(
305 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
306 );
307 success &= assert_type_fprint::<SuperBlockHeaderV32>(
308 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
309 );
310 success &= assert_type_fprint::<SuperBlockRecordV49>(
311 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<[u8;16]>,casefold:bool),Graveyard,Symlink(refs:u64,link:Box<[u8]>),EncryptedSymlink(refs:u64,link:Box<[u8]>)},attributes:struct {creation_time:struct {nanos:u64},modification_time:struct {nanos:u64},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {nanos:u64},change_time:struct {nanos:u64}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:[u8;16],key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
312 );
313 assert!(success, "One or more versioned types have different type fingerprint.");
314 }
315
316 #[test]
317 fn type_fprint_v47() {
318 let mut success = true;
319 success &= assert_type_fprint::<AllocatorInfoV32>(
320 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
321 );
322 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
323 success &= assert_type_fprint::<AllocatorValueV32>(
324 "enum {None,Abs(count:u64,owner_object_id:u64)}",
325 );
326 success &= assert_type_fprint::<EncryptedMutationsV40>(
327 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
328 );
329 success &= assert_type_fprint::<JournalRecordV47>(
330 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:u128,key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
331 );
332 success &= assert_type_fprint::<FsverityMetadataV33>(
333 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
334 );
335 success &= assert_type_fprint::<MutationV47>(
336 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:u128,key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
337 );
338 success &= assert_type_fprint::<ObjectKeyV43>(
339 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
340 );
341 success &= assert_type_fprint::<ObjectValueV47>(
342 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:u128,key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
343 );
344 success &=
345 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
346 success &= assert_type_fprint::<PersistentLayerInfoV39>(
347 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
348 );
349 success &= assert_type_fprint::<StoreInfoV40>(
350 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
351 );
352 success &= assert_type_fprint::<SuperBlockHeaderV32>(
353 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
354 );
355 success &= assert_type_fprint::<SuperBlockRecordV47>(
356 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(struct {Vec<(u64,enum {Fxfs(struct {wrapping_key_id:u128,key:WrappedKeyBytes}),FscryptInoLblk32File(key_identifier:[u8;16]),FscryptInoLblk32Dir(key_identifier:[u8;16],nonce:[u8;16])},)>}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
357 );
358 assert!(success, "One or more versioned types have different type fingerprint.");
359 }
360
361 #[test]
362 fn type_fprint_v46() {
363 let mut success = true;
364 success &= assert_type_fprint::<AllocatorInfoV32>(
365 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
366 );
367 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
368 success &= assert_type_fprint::<AllocatorValueV32>(
369 "enum {None,Abs(count:u64,owner_object_id:u64)}",
370 );
371 success &= assert_type_fprint::<EncryptedMutationsV40>(
372 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
373 );
374 success &= assert_type_fprint::<JournalRecordV46>(
375 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
376 );
377 success &= assert_type_fprint::<FsverityMetadataV33>(
378 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
379 );
380 success &= assert_type_fprint::<MutationV46>(
381 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
382 );
383 success &= assert_type_fprint::<ObjectKeyV43>(
384 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
385 );
386 success &= assert_type_fprint::<ObjectValueV46>(
387 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
388 );
389 success &=
390 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
391 success &= assert_type_fprint::<PersistentLayerInfoV39>(
392 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
393 );
394 success &= assert_type_fprint::<StoreInfoV40>(
395 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
396 );
397 success &= assert_type_fprint::<SuperBlockHeaderV32>(
398 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
399 );
400 success &= assert_type_fprint::<SuperBlockRecordV46>(
401 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>),EncryptedSymlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
402 );
403 assert!(success, "One or more versioned types have different type fingerprint.");
404 }
405
406 #[test]
407 fn type_fprint_v43() {
408 let mut success = true;
409 success &= assert_type_fprint::<AllocatorInfoV32>(
410 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
411 );
412 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
413 success &= assert_type_fprint::<AllocatorValueV32>(
414 "enum {None,Abs(count:u64,owner_object_id:u64)}",
415 );
416 success &= assert_type_fprint::<EncryptedMutationsV40>(
417 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
418 );
419 success &= assert_type_fprint::<JournalRecordV43>(
420 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
421 );
422 success &= assert_type_fprint::<FsverityMetadataV33>(
423 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
424 );
425 success &= assert_type_fprint::<MutationV43>(
426 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
427 );
428 success &= assert_type_fprint::<ObjectKeyV43>(
429 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}}",
430 );
431 success &= assert_type_fprint::<ObjectValueV41>(
432 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
433 );
434 success &=
435 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
436 success &= assert_type_fprint::<PersistentLayerInfoV39>(
437 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
438 );
439 success &= assert_type_fprint::<StoreInfoV40>(
440 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
441 );
442 success &= assert_type_fprint::<SuperBlockHeaderV32>(
443 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
444 );
445 success &= assert_type_fprint::<SuperBlockRecordV43>(
446 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(hash_code:u32,name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
447 );
448 assert!(success, "One or more versioned types have different type fingerprint.");
449 }
450
451 #[test]
452 fn type_fprint_v42() {
453 let mut success = true;
454
455 success &= assert_type_fprint::<AllocatorInfoV32>(
456 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
457 );
458 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
459 success &= assert_type_fprint::<AllocatorValueV32>(
460 "enum {None,Abs(count:u64,owner_object_id:u64)}",
461 );
462 success &= assert_type_fprint::<EncryptedMutationsV40>(
463 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
464 );
465 success &= assert_type_fprint::<JournalRecordV42>(
466 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>},bool)}",
467 );
468 success &= assert_type_fprint::<FsverityMetadataV33>(
469 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
470 );
471 success &= assert_type_fprint::<MutationV41>(
472 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
473 );
474 success &= assert_type_fprint::<ObjectKeyV40>(
475 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}}",
476 );
477 success &= assert_type_fprint::<ObjectValueV41>(
478 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
479 );
480 success &=
481 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
482 success &= assert_type_fprint::<PersistentLayerInfoV39>(
483 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
484 );
485 success &= assert_type_fprint::<StoreInfoV40>(
486 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
487 );
488 success &= assert_type_fprint::<SuperBlockHeaderV32>(
489 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
490 );
491 success &= assert_type_fprint::<SuperBlockRecordV41>(
492 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
493 );
494 assert!(success, "One or more versioned types have different type fingerprint.");
495 }
496
497 #[test]
498 fn type_fprint_v41() {
499 let mut success = true;
500
501 success &= assert_type_fprint::<AllocatorInfoV32>(
502 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
503 );
504 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
505 success &= assert_type_fprint::<AllocatorValueV32>(
506 "enum {None,Abs(count:u64,owner_object_id:u64)}",
507 );
508 success &= assert_type_fprint::<EncryptedMutationsV40>(
509 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
510 );
511 success &= assert_type_fprint::<JournalRecordV41>(
512 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>})}",
513 );
514 success &= assert_type_fprint::<FsverityMetadataV33>(
515 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
516 );
517 success &= assert_type_fprint::<MutationV41>(
518 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
519 );
520 success &= assert_type_fprint::<ObjectKeyV40>(
521 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}}",
522 );
523 success &= assert_type_fprint::<ObjectValueV41>(
524 "enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
525 );
526 success &=
527 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
528 success &= assert_type_fprint::<PersistentLayerInfoV39>(
529 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
530 );
531 success &= assert_type_fprint::<StoreInfoV40>(
532 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
533 );
534 success &= assert_type_fprint::<SuperBlockHeaderV32>(
535 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
536 );
537 success &= assert_type_fprint::<SuperBlockRecordV41>(
538 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64,has_overwrite_extents:bool),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
539 );
540 assert!(success, "One or more versioned types have different type fingerprint.");
541 }
542
543 #[test]
544 fn type_fprint_v40() {
545 let mut success = true;
546 success &= assert_type_fprint::<AllocatorInfoV32>(
547 "struct {layers:Vec<u64>,allocated_bytes:BTreeMap<u64,u64>,marked_for_deletion:HashSet<u64>,limit_bytes:BTreeMap<u64,u64>}",
548 );
549 success &= assert_type_fprint::<AllocatorKeyV32>("struct {device_range:Range<u64>}");
550 success &= assert_type_fprint::<AllocatorValueV32>(
551 "enum {None,Abs(count:u64,owner_object_id:u64)}",
552 );
553 success &= assert_type_fprint::<EncryptedMutationsV40>(
554 "struct {transactions:Vec<(struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},u64,)>,data:Vec<u8>,mutations_key_roll:Vec<(usize,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>}",
555 );
556 success &= assert_type_fprint::<JournalRecordV40>(
557 "enum {EndBlock,Mutation(object_id:u64,mutation:enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64,has_overwrite_extents:bool),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}),Commit,Discard(u64),DidFlushDevice(u64),DataChecksums(Range<u64>,struct {sums:Vec<u8>})}",
558 );
559 success &= assert_type_fprint::<FsverityMetadataV33>(
560 "struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>}",
561 );
562 success &= assert_type_fprint::<MutationV40>(
563 "enum {ObjectStore(struct {item:struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64,has_overwrite_extents:bool),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64},op:enum {Insert,ReplaceOrInsert,Merge}}),EncryptedObjectStore(Box<[u8]>),Allocator(enum {Allocate(device_range:struct {Range<u64>},owner_object_id:u64),Deallocate(device_range:struct {Range<u64>},owner_object_id:u64),SetLimit(owner_object_id:u64,bytes:u64),MarkForDeletion(u64)}),BeginFlush,EndFlush,DeleteVolume,UpdateBorrowed(u64),UpdateMutationsKey(struct {struct {wrapping_key_id:u128,key:WrappedKeyBytes}}),CreateInternalDir(u64)}",
564 );
565 success &= assert_type_fprint::<ObjectKeyV40>(
566 "struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}}",
567 );
568 success &= assert_type_fprint::<ObjectValueV40>(
569 "enum {None,Some,Object(kind:enum {File(refs:u64,has_overwrite_extents:bool),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})}",
570 );
571 success &=
572 assert_type_fprint::<PersistentLayerHeaderV39>("struct {magic:[u8;8],block_size:u64}");
573 success &= assert_type_fprint::<PersistentLayerInfoV39>(
574 "struct {num_items:usize,num_data_blocks:u64,bloom_filter_size_bytes:usize,bloom_filter_seed:u64,bloom_filter_num_hashes:usize}",
575 );
576 success &= assert_type_fprint::<StoreInfoV40>(
577 "struct {guid:[u8;16],last_object_id:u64,layers:Vec<u64>,root_directory_object_id:u64,graveyard_directory_object_id:u64,object_count:u64,mutations_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,mutations_cipher_offset:u64,encrypted_mutations_object_id:u64,object_id_key:Option<struct {wrapping_key_id:u128,key:WrappedKeyBytes}>,internal_directory_object_id:u64}",
578 );
579 success &= assert_type_fprint::<SuperBlockHeaderV32>(
580 "struct {guid:<[u8;16]>,generation:u64,root_parent_store_object_id:u64,root_parent_graveyard_directory_object_id:u64,root_store_object_id:u64,allocator_object_id:u64,journal_object_id:u64,journal_checkpoint:struct {file_offset:u64,checksum:u64,version:struct {major:u32,minor:u8}},super_block_journal_file_offset:u64,journal_file_offsets:HashMap<u64,u64>,borrowed_metadata_space:u64,earliest_version:struct {major:u32,minor:u8}}",
581 );
582 success &= assert_type_fprint::<SuperBlockRecordV40>(
583 "enum {Extent(Range<u64>),ObjectItem(struct {key:struct {object_id:u64,data:enum {Object,Keys,Attribute(u64,enum {Attribute,Extent(struct {range:Range<u64>})}),Child(name:String),GraveyardEntry(object_id:u64),Project(project_id:u64,property:enum {Limit,Usage}),ExtendedAttribute(name:Vec<u8>),GraveyardAttributeEntry(object_id:u64,attribute_id:u64),EncryptedChild(name:Vec<u8>),CasefoldChild(name:struct {String})}},value:enum {None,Some,Object(kind:enum {File(refs:u64,has_overwrite_extents:bool),Directory(sub_dirs:u64,wrapping_key_id:Option<u128>,casefold:bool),Graveyard,Symlink(refs:u64,link:Vec<u8>)},attributes:struct {creation_time:struct {secs:u64,nanos:u32},modification_time:struct {secs:u64,nanos:u32},project_id:u64,posix_attributes:Option<struct {mode:u32,uid:u32,gid:u32,rdev:u64}>,allocated_size:u64,access_time:struct {secs:u64,nanos:u32},change_time:struct {secs:u64,nanos:u32}}),Keys(enum {AES256XTS(struct {Vec<(u64,struct {wrapping_key_id:u128,key:WrappedKeyBytes},)>})}),Attribute(size:u64),Extent(enum {None,Some(device_offset:u64,mode:enum {Raw,Cow(struct {sums:Vec<u8>}),OverwritePartial(bit_vec :: BitVec<u32>),Overwrite},key_id:u64)}),Child(struct {object_id:u64,object_descriptor:enum {File,Directory,Volume,Symlink}}),Trim,BytesAndNodes(bytes:i64,nodes:i64),ExtendedAttribute(enum {Inline(Vec<u8>),AttributeId(u64)}),VerifiedAttribute(size:u64,fsverity_metadata:struct {root_digest:enum {Sha256([u8;32]),Sha512(Vec<u8>)},salt:Vec<u8>})},sequence:u64}),End}",
584 );
585 assert!(success, "One or more versioned types have different type fingerprint.");
586 }
587}