1mod legacy;
6
7pub use legacy::*;
8
9use crate::checksum::Checksums;
11use crate::log::error;
12use crate::lsm_tree::types::{
13 FuzzyHash, Item, ItemRef, LayerKey, MergeType, OrdLowerBound, OrdUpperBound, RangeKey,
14 SortByU64, Value,
15};
16use crate::object_store::extent_record::{
17 ExtentKey, ExtentKeyPartitionIterator, ExtentKeyV32, ExtentValue, ExtentValueV38,
18};
19use crate::serialized_types::{Migrate, Versioned, migrate_nodefault, migrate_to_version};
20use fprint::TypeFingerprint;
21use fxfs_crypto::{WrappedKey, WrappingKeyId};
22use fxfs_unicode::CasefoldString;
23use serde::{Deserialize, Serialize};
24use std::collections::BTreeMap;
25use std::default::Default;
26use std::hash::Hash;
27use std::time::{Duration, SystemTime, UNIX_EPOCH};
28
29pub type ObjectDescriptor = ObjectDescriptorV32;
31
32#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
33#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
34pub enum ObjectDescriptorV32 {
35 File,
37 Directory,
39 Volume,
41 Symlink,
43}
44
45pub type ProjectProperty = ProjectPropertyV32;
47
48#[derive(
49 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
50)]
51#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
52pub enum ProjectPropertyV32 {
53 Limit,
55 Usage,
57}
58
59pub type ObjectKeyData = ObjectKeyDataV43;
60
61#[derive(
62 Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, TypeFingerprint,
63)]
64#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
65pub enum ObjectKeyDataV43 {
66 Object,
69 Keys,
71 Attribute(u64, AttributeKeyV32),
73 Child { name: String },
75 GraveyardEntry { object_id: u64 },
77 Project { project_id: u64, property: ProjectPropertyV32 },
81 ExtendedAttribute { name: Vec<u8> },
84 GraveyardAttributeEntry { object_id: u64, attribute_id: u64 },
86 EncryptedChild { hash_code: u32, name: Vec<u8> },
92 CasefoldChild { name: CasefoldString },
95}
96
97pub type AttributeKey = AttributeKeyV32;
98
99#[derive(
100 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
101)]
102#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
103pub enum AttributeKeyV32 {
104 Attribute,
106 Extent(ExtentKeyV32),
107}
108
109pub type ObjectKey = ObjectKeyV43;
111
112#[derive(
113 Clone,
114 Debug,
115 Eq,
116 Ord,
117 Hash,
118 PartialEq,
119 PartialOrd,
120 Serialize,
121 Deserialize,
122 TypeFingerprint,
123 Versioned,
124)]
125#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
126pub struct ObjectKeyV43 {
127 pub object_id: u64,
129 pub data: ObjectKeyDataV43,
131}
132
133impl SortByU64 for ObjectKey {
134 fn get_leading_u64(&self) -> u64 {
135 self.object_id
136 }
137}
138
139impl ObjectKey {
140 pub fn object(object_id: u64) -> Self {
142 Self { object_id: object_id, data: ObjectKeyData::Object }
143 }
144
145 pub fn keys(object_id: u64) -> Self {
147 Self { object_id, data: ObjectKeyData::Keys }
148 }
149
150 pub fn attribute(object_id: u64, attribute_id: u64, key: AttributeKey) -> Self {
152 Self { object_id, data: ObjectKeyData::Attribute(attribute_id, key) }
153 }
154
155 pub fn extent(object_id: u64, attribute_id: u64, range: std::ops::Range<u64>) -> Self {
157 Self {
158 object_id,
159 data: ObjectKeyData::Attribute(
160 attribute_id,
161 AttributeKey::Extent(ExtentKey::new(range)),
162 ),
163 }
164 }
165
166 pub fn from_extent(object_id: u64, attribute_id: u64, extent: ExtentKey) -> Self {
168 Self {
169 object_id,
170 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(extent)),
171 }
172 }
173
174 pub fn child(object_id: u64, name: &str, casefold: bool) -> Self {
176 if casefold {
177 Self { object_id, data: ObjectKeyData::CasefoldChild { name: name.into() } }
178 } else {
179 Self { object_id, data: ObjectKeyData::Child { name: name.into() } }
180 }
181 }
182
183 pub fn encrypted_child(object_id: u64, name: Vec<u8>, hash_code: u32) -> Self {
193 Self { object_id, data: ObjectKeyData::EncryptedChild { hash_code, name } }
194 }
195
196 pub fn graveyard_entry(graveyard_object_id: u64, object_id: u64) -> Self {
198 Self { object_id: graveyard_object_id, data: ObjectKeyData::GraveyardEntry { object_id } }
199 }
200
201 pub fn graveyard_attribute_entry(
203 graveyard_object_id: u64,
204 object_id: u64,
205 attribute_id: u64,
206 ) -> Self {
207 Self {
208 object_id: graveyard_object_id,
209 data: ObjectKeyData::GraveyardAttributeEntry { object_id, attribute_id },
210 }
211 }
212
213 pub fn project_limit(object_id: u64, project_id: u64) -> Self {
215 Self {
216 object_id,
217 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Limit },
218 }
219 }
220
221 pub fn project_usage(object_id: u64, project_id: u64) -> Self {
223 Self {
224 object_id,
225 data: ObjectKeyData::Project { project_id, property: ProjectProperty::Usage },
226 }
227 }
228
229 pub fn extended_attribute(object_id: u64, name: Vec<u8>) -> Self {
230 Self { object_id, data: ObjectKeyData::ExtendedAttribute { name } }
231 }
232
233 pub fn key_for_merge_into(&self) -> Self {
236 if let Self {
237 object_id,
238 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
239 } = self
240 {
241 Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.key_for_merge_into()))
242 } else {
243 self.clone()
244 }
245 }
246}
247
248impl OrdUpperBound for ObjectKey {
249 fn cmp_upper_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
250 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
251 (
252 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
253 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
254 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_upper_bound(right_extent)),
255 _ => self.data.cmp(&other.data),
256 })
257 }
258}
259
260impl OrdLowerBound for ObjectKey {
261 fn cmp_lower_bound(&self, other: &ObjectKey) -> std::cmp::Ordering {
262 self.object_id.cmp(&other.object_id).then_with(|| match (&self.data, &other.data) {
263 (
264 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_extent)),
265 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_extent)),
266 ) => left_attr_id.cmp(right_attr_id).then(left_extent.cmp_lower_bound(right_extent)),
267 _ => self.data.cmp(&other.data),
268 })
269 }
270}
271
272impl LayerKey for ObjectKey {
273 fn merge_type(&self) -> MergeType {
274 match self.data {
277 ObjectKeyData::Object
278 | ObjectKeyData::Keys
279 | ObjectKeyData::Attribute(..)
280 | ObjectKeyData::Child { .. }
281 | ObjectKeyData::EncryptedChild { .. }
282 | ObjectKeyData::CasefoldChild { .. }
283 | ObjectKeyData::GraveyardEntry { .. }
284 | ObjectKeyData::GraveyardAttributeEntry { .. }
285 | ObjectKeyData::Project { property: ProjectProperty::Limit, .. }
286 | ObjectKeyData::ExtendedAttribute { .. } => MergeType::OptimizedMerge,
287 ObjectKeyData::Project { property: ProjectProperty::Usage, .. } => MergeType::FullMerge,
288 }
289 }
290
291 fn next_key(&self) -> Option<Self> {
292 match self.data {
293 ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => {
294 let mut key = self.clone();
295 if let ObjectKey {
296 data: ObjectKeyData::Attribute(_, AttributeKey::Extent(ExtentKey { range })),
297 ..
298 } = &mut key
299 {
300 *range = range.end..range.end + 1;
304 }
305 Some(key)
306 }
307 _ => None,
308 }
309 }
310
311 fn search_key(&self) -> Self {
312 if let Self {
313 object_id,
314 data: ObjectKeyData::Attribute(attribute_id, AttributeKey::Extent(e)),
315 } = self
316 {
317 Self::attribute(*object_id, *attribute_id, AttributeKey::Extent(e.search_key()))
318 } else {
319 self.clone()
320 }
321 }
322}
323
324impl RangeKey for ObjectKey {
325 fn overlaps(&self, other: &Self) -> bool {
326 if self.object_id != other.object_id {
327 return false;
328 }
329 match (&self.data, &other.data) {
330 (
331 ObjectKeyData::Attribute(left_attr_id, AttributeKey::Extent(left_key)),
332 ObjectKeyData::Attribute(right_attr_id, AttributeKey::Extent(right_key)),
333 ) if *left_attr_id == *right_attr_id => {
334 left_key.range.end > right_key.range.start
335 && left_key.range.start < right_key.range.end
336 }
337 (a, b) => a == b,
338 }
339 }
340}
341
342pub enum ObjectKeyFuzzyHashIterator {
343 ExtentKey(u64, u64, ExtentKeyPartitionIterator),
344 NotExtentKey(Option<u64>),
345}
346
347impl Iterator for ObjectKeyFuzzyHashIterator {
348 type Item = u64;
349
350 fn next(&mut self) -> Option<Self::Item> {
351 match self {
352 Self::ExtentKey(oid, attr_id, extent_keys) => extent_keys.next().map(|range| {
353 let key = ObjectKey::extent(*oid, *attr_id, range);
354 crate::stable_hash::stable_hash(key)
355 }),
356 Self::NotExtentKey(hash) => hash.take(),
357 }
358 }
359}
360
361impl FuzzyHash for ObjectKey {
362 fn fuzzy_hash(&self) -> impl Iterator<Item = u64> {
363 match &self.data {
364 ObjectKeyData::Attribute(attr_id, AttributeKey::Extent(extent)) => {
365 ObjectKeyFuzzyHashIterator::ExtentKey(
366 self.object_id,
367 *attr_id,
368 extent.fuzzy_hash_partition(),
369 )
370 }
371 _ => {
372 let hash = crate::stable_hash::stable_hash(self);
373 ObjectKeyFuzzyHashIterator::NotExtentKey(Some(hash))
374 }
375 }
376 }
377
378 fn is_range_key(&self) -> bool {
379 match &self.data {
380 ObjectKeyData::Attribute(_, AttributeKey::Extent(_)) => true,
381 _ => false,
382 }
383 }
384}
385
386pub type Timestamp = TimestampV49;
388
389#[derive(
390 Copy,
391 Clone,
392 Debug,
393 Default,
394 Eq,
395 PartialEq,
396 Ord,
397 PartialOrd,
398 Serialize,
399 Deserialize,
400 TypeFingerprint,
401)]
402#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
403pub struct TimestampV49 {
404 nanos: u64,
405}
406
407impl Timestamp {
408 const NSEC_PER_SEC: u64 = 1_000_000_000;
409
410 pub fn now() -> Self {
411 SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::ZERO).into()
412 }
413
414 pub const fn zero() -> Self {
415 Self { nanos: 0 }
416 }
417
418 pub const fn from_nanos(nanos: u64) -> Self {
419 Self { nanos }
420 }
421
422 pub fn from_secs_and_nanos(secs: u64, nanos: u32) -> Self {
423 let Some(secs_in_nanos) = secs.checked_mul(Self::NSEC_PER_SEC) else {
424 error!("Fxfs doesn't support dates past 2554-07-21");
425 return Self { nanos: u64::MAX };
426 };
427 let Some(nanos) = secs_in_nanos.checked_add(nanos as u64) else {
428 error!("Fxfs doesn't support dates past 2554-07-21");
429 return Self { nanos: u64::MAX };
430 };
431 Self { nanos }
432 }
433
434 pub fn as_nanos(&self) -> u64 {
437 self.nanos
438 }
439
440 pub fn subsec_nanos(&self) -> u32 {
442 (self.nanos % Self::NSEC_PER_SEC) as u32
443 }
444
445 pub fn as_secs(&self) -> u64 {
448 self.nanos / Self::NSEC_PER_SEC
449 }
450}
451
452impl From<std::time::Duration> for Timestamp {
453 fn from(duration: std::time::Duration) -> Self {
454 Self::from_secs_and_nanos(duration.as_secs(), duration.subsec_nanos())
455 }
456}
457
458impl From<Timestamp> for std::time::Duration {
459 fn from(timestamp: Timestamp) -> std::time::Duration {
460 Duration::from_nanos(timestamp.nanos)
461 }
462}
463
464pub type ObjectKind = ObjectKindV49;
465
466#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
467#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
468pub enum ObjectKindV49 {
469 File {
470 refs: u64,
472 },
473 Directory {
474 sub_dirs: u64,
476 wrapping_key_id: Option<WrappingKeyId>,
479 casefold: bool,
482 },
483 Graveyard,
484 Symlink {
485 refs: u64,
487 link: Box<[u8]>,
490 },
491 EncryptedSymlink {
492 refs: u64,
494 link: Box<[u8]>,
499 },
500}
501
502pub type PosixAttributes = PosixAttributesV32;
505
506#[derive(Clone, Debug, Copy, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
507#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
508pub struct PosixAttributesV32 {
509 pub mode: u32,
511 pub uid: u32,
513 pub gid: u32,
515 pub rdev: u64,
517}
518
519pub type ObjectAttributes = ObjectAttributesV49;
523
524#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, TypeFingerprint)]
525#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
526pub struct ObjectAttributesV49 {
527 pub creation_time: TimestampV49,
529 pub modification_time: TimestampV49,
531 pub project_id: u64,
533 pub posix_attributes: Option<PosixAttributesV32>,
535 pub allocated_size: u64,
537 pub access_time: TimestampV49,
539 pub change_time: TimestampV49,
541}
542
543pub type ExtendedAttributeValue = ExtendedAttributeValueV32;
544
545#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
546#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
547pub enum ExtendedAttributeValueV32 {
548 Inline(Vec<u8>),
551 AttributeId(u64),
554}
555
556pub type ChildValue = ChildValueV32;
558
559#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint)]
560#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
561pub struct ChildValueV32 {
562 pub object_id: u64,
564 pub object_descriptor: ObjectDescriptorV32,
566}
567
568pub type RootDigest = RootDigestV33;
569
570#[derive(
571 Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize, TypeFingerprint,
572)]
573#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
574pub enum RootDigestV33 {
575 Sha256([u8; 32]),
576 Sha512(Vec<u8>),
577}
578
579pub type FsverityMetadata = FsverityMetadataV50;
580
581#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypeFingerprint, Versioned)]
582#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
583pub enum FsverityMetadataV50 {
584 Internal(RootDigestV33, Vec<u8>),
586 F2fs(std::ops::Range<u64>),
588}
589
590pub type EncryptionKey = EncryptionKeyV49;
591pub type EncryptionKeyV49 = fxfs_crypto::EncryptionKey;
592
593pub type EncryptionKeys = EncryptionKeysV49;
594
595#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
596#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
597pub struct EncryptionKeysV49(Vec<(u64, EncryptionKeyV49)>);
598
599impl EncryptionKeys {
600 pub fn get(&self, id: u64) -> Option<&EncryptionKey> {
601 self.0.iter().find_map(|(i, key)| (*i == id).then_some(key))
602 }
603
604 pub fn insert(&mut self, id: u64, key: EncryptionKey) {
605 self.0.push((id, key))
606 }
607
608 pub fn remove(&mut self, id: u64) -> Option<EncryptionKey> {
609 if let Some(ix) = self.0.iter().position(|(k, _)| *k == id) {
610 Some(self.0.remove(ix).1)
611 } else {
612 None
613 }
614 }
615}
616
617impl From<EncryptionKeys> for BTreeMap<u64, WrappedKey> {
618 fn from(keys: EncryptionKeys) -> Self {
619 keys.0.into_iter().map(|(id, key)| (id, key.into())).collect()
620 }
621}
622
623impl From<Vec<(u64, EncryptionKey)>> for EncryptionKeys {
624 fn from(value: Vec<(u64, EncryptionKey)>) -> Self {
625 Self(value)
626 }
627}
628
629impl std::ops::Deref for EncryptionKeys {
630 type Target = Vec<(u64, EncryptionKey)>;
631 fn deref(&self) -> &Self::Target {
632 &self.0
633 }
634}
635
636pub type ObjectValue = ObjectValueV50;
640impl Value for ObjectValue {
641 const DELETED_MARKER: Self = Self::None;
642}
643
644#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, TypeFingerprint, Versioned)]
645#[cfg_attr(fuzz, derive(arbitrary::Arbitrary))]
646pub enum ObjectValueV50 {
647 None,
651 Some,
654 Object { kind: ObjectKindV49, attributes: ObjectAttributesV49 },
656 Keys(EncryptionKeysV49),
658 Attribute { size: u64, has_overwrite_extents: bool },
660 Extent(ExtentValueV38),
662 Child(ChildValueV32),
664 Trim,
668 BytesAndNodes { bytes: i64, nodes: i64 },
670 ExtendedAttribute(ExtendedAttributeValueV32),
673 VerifiedAttribute { size: u64, fsverity_metadata: FsverityMetadataV50 },
676}
677
678impl ObjectValue {
679 pub fn file(
681 refs: u64,
682 allocated_size: u64,
683 creation_time: Timestamp,
684 modification_time: Timestamp,
685 access_time: Timestamp,
686 change_time: Timestamp,
687 project_id: u64,
688 posix_attributes: Option<PosixAttributes>,
689 ) -> ObjectValue {
690 ObjectValue::Object {
691 kind: ObjectKind::File { refs },
692 attributes: ObjectAttributes {
693 creation_time,
694 modification_time,
695 project_id,
696 posix_attributes,
697 allocated_size,
698 access_time,
699 change_time,
700 },
701 }
702 }
703 pub fn keys(encryption_keys: EncryptionKeys) -> ObjectValue {
704 ObjectValue::Keys(encryption_keys)
705 }
706 pub fn attribute(size: u64, has_overwrite_extents: bool) -> ObjectValue {
708 ObjectValue::Attribute { size, has_overwrite_extents }
709 }
710 pub fn verified_attribute(size: u64, fsverity_metadata: FsverityMetadata) -> ObjectValue {
712 ObjectValue::VerifiedAttribute { size, fsverity_metadata }
713 }
714 pub fn extent(device_offset: u64, key_id: u64) -> ObjectValue {
716 ObjectValue::Extent(ExtentValue::new_raw(device_offset, key_id))
717 }
718 pub fn extent_with_checksum(
720 device_offset: u64,
721 checksum: Checksums,
722 key_id: u64,
723 ) -> ObjectValue {
724 ObjectValue::Extent(ExtentValue::with_checksum(device_offset, checksum, key_id))
725 }
726 pub fn deleted_extent() -> ObjectValue {
728 ObjectValue::Extent(ExtentValue::deleted_extent())
729 }
730 pub fn child(object_id: u64, object_descriptor: ObjectDescriptor) -> ObjectValue {
732 ObjectValue::Child(ChildValue { object_id, object_descriptor })
733 }
734 pub fn symlink(
736 link: impl Into<Box<[u8]>>,
737 creation_time: Timestamp,
738 modification_time: Timestamp,
739 project_id: u64,
740 ) -> ObjectValue {
741 ObjectValue::Object {
742 kind: ObjectKind::Symlink { refs: 1, link: link.into() },
743 attributes: ObjectAttributes {
744 creation_time,
745 modification_time,
746 project_id,
747 ..Default::default()
748 },
749 }
750 }
751 pub fn encrypted_symlink(
753 link: impl Into<Box<[u8]>>,
754 creation_time: Timestamp,
755 modification_time: Timestamp,
756 project_id: u64,
757 ) -> ObjectValue {
758 ObjectValue::Object {
759 kind: ObjectKind::EncryptedSymlink { refs: 1, link: link.into() },
760 attributes: ObjectAttributes {
761 creation_time,
762 modification_time,
763 project_id,
764 ..Default::default()
765 },
766 }
767 }
768 pub fn inline_extended_attribute(value: impl Into<Vec<u8>>) -> ObjectValue {
769 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::Inline(value.into()))
770 }
771 pub fn extended_attribute(attribute_id: u64) -> ObjectValue {
772 ObjectValue::ExtendedAttribute(ExtendedAttributeValue::AttributeId(attribute_id))
773 }
774}
775
776pub type ObjectItem = ObjectItemV50;
777pub type ObjectItemV50 = Item<ObjectKeyV43, ObjectValueV50>;
778
779impl ObjectItem {
780 pub fn is_tombstone(&self) -> bool {
781 matches!(
782 self,
783 Item {
784 key: ObjectKey { data: ObjectKeyData::Object, .. },
785 value: ObjectValue::None,
786 ..
787 }
788 )
789 }
790}
791
792impl<'a> From<ItemRef<'a, ObjectKey, ObjectValue>>
794 for Option<(u64, u64, &'a ExtentKey, &'a ExtentValue)>
795{
796 fn from(item: ItemRef<'a, ObjectKey, ObjectValue>) -> Self {
797 match item {
798 ItemRef {
799 key:
800 ObjectKey {
801 object_id,
802 data:
803 ObjectKeyData::Attribute(
804 attribute_id, AttributeKey::Extent(extent_key),
806 ),
807 },
808 value: ObjectValue::Extent(extent_value),
809 ..
810 } => Some((*object_id, *attribute_id, extent_key, extent_value)),
811 _ => None,
812 }
813 }
814}
815
816pub type FxfsKey = FxfsKeyV49;
817pub type FxfsKeyV49 = fxfs_crypto::FxfsKey;
818
819#[cfg(test)]
820mod tests {
821 use super::{ObjectKey, ObjectKeyV43, TimestampV49};
822 use crate::lsm_tree::types::{
823 FuzzyHash as _, LayerKey, OrdLowerBound, OrdUpperBound, RangeKey,
824 };
825 use std::cmp::Ordering;
826 use std::ops::Add;
827 use std::time::{Duration, SystemTime, UNIX_EPOCH};
828
829 #[test]
834 fn test_hash_stability() {
835 assert_eq!(
839 &ObjectKeyV43::object(100).fuzzy_hash().collect::<Vec<_>>()[..],
840 &[11885326717398844384]
841 );
842 assert_eq!(
843 &ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).fuzzy_hash().collect::<Vec<_>>()[..],
844 &[11090579907097549012, 2814892992701560424]
845 );
846 }
847
848 #[test]
849 fn test_next_key() {
850 let next_key = ObjectKey::extent(1, 0, 0..100).next_key().unwrap();
851 assert_eq!(ObjectKey::extent(1, 0, 101..200).cmp_lower_bound(&next_key), Ordering::Greater);
852 assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_lower_bound(&next_key), Ordering::Equal);
853 assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_lower_bound(&next_key), Ordering::Equal);
854 assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_lower_bound(&next_key), Ordering::Less);
855 assert_eq!(ObjectKey::extent(1, 0, 0..100).cmp_upper_bound(&next_key), Ordering::Less);
856 assert_eq!(ObjectKey::extent(1, 0, 99..100).cmp_upper_bound(&next_key), Ordering::Less);
857 assert_eq!(ObjectKey::extent(1, 0, 100..101).cmp_upper_bound(&next_key), Ordering::Equal);
858 assert_eq!(ObjectKey::extent(1, 0, 100..200).cmp_upper_bound(&next_key), Ordering::Greater);
859 assert_eq!(ObjectKey::extent(1, 0, 50..101).cmp_upper_bound(&next_key), Ordering::Equal);
860 assert_eq!(ObjectKey::extent(1, 0, 50..200).cmp_upper_bound(&next_key), Ordering::Greater);
861 }
862 #[test]
863 fn test_range_key() {
864 assert!(ObjectKeyV43::extent(1, 0, 0..2 * 1024 * 1024).is_range_key());
867 assert!(!ObjectKeyV43::object(100).is_range_key());
868
869 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(1)), true);
870 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::object(2)), false);
871 assert_eq!(ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::object(1)), false);
872 assert_eq!(ObjectKey::object(1).overlaps(&ObjectKey::extent(1, 0, 0..100)), false);
873 assert_eq!(
874 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(2, 0, 0..100)),
875 false
876 );
877 assert_eq!(
878 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 1, 0..100)),
879 false
880 );
881 assert_eq!(
882 ObjectKey::extent(1, 0, 0..100).overlaps(&ObjectKey::extent(1, 0, 0..100)),
883 true
884 );
885
886 assert_eq!(
887 ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 49..100)),
888 true
889 );
890 assert_eq!(
891 ObjectKey::extent(1, 0, 49..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
892 true
893 );
894
895 assert_eq!(
896 ObjectKey::extent(1, 0, 0..50).overlaps(&ObjectKey::extent(1, 0, 50..100)),
897 false
898 );
899 assert_eq!(
900 ObjectKey::extent(1, 0, 50..100).overlaps(&ObjectKey::extent(1, 0, 0..50)),
901 false
902 );
903 }
904
905 #[test]
906 fn test_timestamp() {
907 fn compare_time(std_time: Duration) {
908 let ts_time: TimestampV49 = std_time.into();
909 assert_eq!(<TimestampV49 as Into<Duration>>::into(ts_time), std_time);
910 assert_eq!(ts_time.subsec_nanos(), std_time.subsec_nanos());
911 assert_eq!(ts_time.as_secs(), std_time.as_secs());
912 assert_eq!(ts_time.as_nanos() as u128, std_time.as_nanos());
913 }
914 compare_time(Duration::from_nanos(0));
915 compare_time(Duration::from_nanos(u64::MAX));
916 compare_time(SystemTime::now().duration_since(UNIX_EPOCH).unwrap());
917
918 let ts: TimestampV49 = Duration::from_secs(u64::MAX - 1).into();
919 assert_eq!(ts.nanos, u64::MAX);
920
921 let ts: TimestampV49 = (Duration::from_nanos(u64::MAX).add(Duration::from_nanos(1))).into();
922 assert_eq!(ts.nanos, u64::MAX);
923 }
924}