fjall/batch/
item.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5use super::PartitionKey;
6use lsm_tree::{UserKey, UserValue, ValueType};
7
8///
9/// Inner Item
10///
11pub enum CompactItem<K, V> {
12    /// Value
13    Value {
14        /// Key
15        key: K,
16        /// Value
17        value: V,
18    },
19    /// Tombstone
20    Tombstone(K),
21    /// Weak tombstone
22    WeakTombstone(K),
23}
24
25impl<K: Ord, V> Ord for CompactItem<K, V> {
26    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
27        self.key().cmp(other.key())
28    }
29}
30
31impl<K: Ord, V> PartialOrd for CompactItem<K, V> {
32    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
33        Some(self.cmp(other))
34    }
35}
36
37impl<K: Eq, V> PartialEq for CompactItem<K, V> {
38    fn eq(&self, other: &Self) -> bool {
39        self.key() == other.key()
40    }
41}
42
43impl<K: Eq, V> Eq for CompactItem<K, V> {}
44
45impl<K, V> CompactItem<K, V> {
46    fn key(&self) -> &K {
47        match self {
48            Self::Value { key, .. } | Self::Tombstone(key) | Self::WeakTombstone(key) => key,
49        }
50    }
51}
52
53#[derive(Clone, PartialEq, Eq)]
54pub struct Item {
55    /// Partition key - an arbitrary byte array
56    ///
57    /// Supports up to 2^8 bytes
58    pub partition: PartitionKey,
59
60    /// User-defined key - an arbitrary byte array
61    ///
62    /// Supports up to 2^16 bytes
63    pub key: UserKey,
64
65    /// User-defined value - an arbitrary byte array
66    ///
67    /// Supports up to 65535 bytes
68    pub value: UserValue,
69
70    /// Tombstone marker - if this is true, the value has been deleted
71    pub value_type: ValueType,
72}
73
74impl std::fmt::Debug for Item {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(
77            f,
78            "{}:{:?}:{} => {:?}",
79            self.partition,
80            self.key,
81            match self.value_type {
82                ValueType::Value => "V",
83                ValueType::Tombstone => "T",
84                ValueType::WeakTombstone => "W",
85            },
86            self.value
87        )
88    }
89}
90
91impl Item {
92    ///
93    /// New item
94    ///
95    pub fn new<P: Into<PartitionKey>, K: Into<UserKey>, V: Into<UserValue>>(
96        partition: P,
97        key: K,
98        value: V,
99        value_type: ValueType,
100    ) -> Self {
101        let p = partition.into();
102        let k = key.into();
103        let v = value.into();
104
105        assert!(!p.is_empty());
106        assert!(!k.is_empty());
107
108        assert!(u8::try_from(p.len()).is_ok(), "Partition name too long");
109        assert!(
110            u16::try_from(k.len()).is_ok(),
111            "Keys can be up to 65535 bytes long"
112        );
113        assert!(
114            u32::try_from(v.len()).is_ok(),
115            "Values can be up to 2^32 bytes long"
116        );
117
118        Self {
119            partition: p,
120            key: k,
121            value: v,
122            value_type,
123        }
124    }
125}