lance_table/format/
row_ids.rs1use std::ops::Deref;
5use std::sync::{Arc, OnceLock};
6
7use bytes::Bytes;
8
9use lance_core::deepsize::{Context, DeepSizeOf};
10use lance_core::{Error, Result};
11use serde::{Deserialize, Deserializer, Serialize, Serializer};
12
13use super::pb;
14
15pub use lance_core::{
16 ROW_CREATED_AT_VERSION_FIELD_ID, ROW_ID_FIELD_ID, ROW_LAST_UPDATED_AT_VERSION_FIELD_ID,
17};
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeepSizeOf)]
21pub struct ExternalFile {
22 pub path: String,
23 pub offset: u64,
24 pub size: u64,
25}
26
27#[derive(Clone)]
50pub struct InlineRowIds {
51 inner: Arc<InlineRowIdsInner>,
52}
53
54struct InlineRowIdsInner {
55 data: Bytes,
58 digest: OnceLock<[u8; 32]>,
59}
60
61impl InlineRowIds {
62 pub fn digest(&self) -> &[u8; 32] {
64 self.inner
65 .digest
66 .get_or_init(|| blake3::hash(&self.inner.data).into())
67 }
68
69 pub fn bytes(&self) -> &Bytes {
71 &self.inner.data
72 }
73}
74
75impl From<Bytes> for InlineRowIds {
76 fn from(data: Bytes) -> Self {
77 Self {
78 inner: Arc::new(InlineRowIdsInner {
79 data,
80 digest: OnceLock::new(),
81 }),
82 }
83 }
84}
85
86impl From<Vec<u8>> for InlineRowIds {
87 fn from(data: Vec<u8>) -> Self {
88 Self::from(Bytes::from(data))
89 }
90}
91
92impl Deref for InlineRowIds {
93 type Target = [u8];
94
95 fn deref(&self) -> &Self::Target {
96 &self.inner.data
97 }
98}
99
100impl std::fmt::Debug for InlineRowIds {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 self.inner.data.fmt(f)
105 }
106}
107
108impl PartialEq for InlineRowIds {
109 fn eq(&self, other: &Self) -> bool {
110 Arc::ptr_eq(&self.inner, &other.inner) || self.inner.data == other.inner.data
111 }
112}
113
114impl Eq for InlineRowIds {}
115
116impl Serialize for InlineRowIds {
117 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
118 self.inner.data.serialize(serializer)
119 }
120}
121
122impl<'de> Deserialize<'de> for InlineRowIds {
123 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Self, D::Error> {
124 Vec::<u8>::deserialize(deserializer).map(Self::from)
125 }
126}
127
128impl DeepSizeOf for InlineRowIds {
129 fn deep_size_of_children(&self, context: &mut Context) -> usize {
130 self.inner.deep_size_of_children(context)
132 }
133}
134
135impl DeepSizeOf for InlineRowIdsInner {
136 fn deep_size_of_children(&self, context: &mut Context) -> usize {
137 self.data.deep_size_of_children(context)
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, DeepSizeOf)]
143pub enum RowIdMeta {
144 Inline(InlineRowIds),
145 Column,
155}
156
157impl TryFrom<pb::data_fragment::RowIdSequence> for RowIdMeta {
158 type Error = Error;
159
160 fn try_from(value: pb::data_fragment::RowIdSequence) -> Result<Self> {
161 match value {
162 pb::data_fragment::RowIdSequence::InlineRowIds(data) => Ok(Self::Inline(data.into())),
163 pb::data_fragment::RowIdSequence::ColumnRowIds(_) => Ok(Self::Column),
164 }
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 use crate::format::Fragment;
172
173 #[test]
174 fn inline_row_ids_digest_identifies_contents() {
175 let first = InlineRowIds::from(vec![1, 2, 3]);
176 let same = InlineRowIds::from(vec![1, 2, 3]);
177 let other = InlineRowIds::from(vec![1, 2, 4]);
178
179 assert_eq!(first.digest(), same.digest());
182 assert_ne!(first.digest(), other.digest());
183 assert_eq!(first, same);
184 assert_ne!(first, other);
185
186 let memoized = *first.digest();
188 assert_eq!(first.digest(), &memoized);
189 }
190
191 #[test]
192 fn inline_row_ids_clones_share_bytes_and_memo() {
193 let first = InlineRowIds::from(vec![1, 2, 3]);
194 let cloned = first.clone();
195
196 assert!(std::ptr::eq(first.as_ptr(), cloned.as_ptr()));
201 assert!(std::ptr::eq(first.digest(), cloned.digest()));
202
203 let separate = InlineRowIds::from(vec![1, 2, 3]);
206 assert_eq!(first, separate);
207 assert!(!std::ptr::eq(first.as_ptr(), separate.as_ptr()));
208
209 let fresh = InlineRowIds::from(vec![4, 5, 6]);
211 let fresh_clone = fresh.clone();
212 let via_clone = *fresh_clone.digest();
213 assert_eq!(fresh.digest(), &via_clone);
214 }
215
216 #[test]
217 fn inline_row_ids_from_bytes_shares_the_allocation() {
218 let buffer = Bytes::from((0..64u8).collect::<Vec<u8>>());
219 let slice = buffer.slice(16..48);
220 let inline = InlineRowIds::from(slice.clone());
221 assert_eq!(&*inline, &buffer[16..48]);
222 assert_eq!(inline.bytes().as_ptr(), slice.as_ptr());
223 let shorter = InlineRowIds::from(buffer.slice(0..8));
225 assert_eq!(inline.deep_size_of() - shorter.deep_size_of(), 32 - 8);
226 }
227
228 #[test]
229 fn inline_row_ids_serializes_as_bare_bytes() {
230 let meta = RowIdMeta::Inline(InlineRowIds::from(vec![7, 8, 9]));
232 let json = serde_json::to_string(&meta).unwrap();
233 assert_eq!(json, r#"{"Inline":[7,8,9]}"#);
234 assert_eq!(serde_json::from_str::<RowIdMeta>(&json).unwrap(), meta);
235
236 let fragment = Fragment {
238 row_id_meta: Some(meta.clone()),
239 ..Fragment::new(0)
240 };
241 let restored = Fragment::try_from(pb::DataFragment::from(&fragment)).unwrap();
242 assert_eq!(restored.row_id_meta, Some(meta));
243 }
244}