1use std::sync::Arc;
21
22use linkrs_core::types::VertexId;
23use linkrs_core::{EdgeHeader, Value};
24
25#[derive(Debug, Clone)]
31pub struct EdgeHeaderColumn {
32 src: Vec<VertexId>,
33 dst: Vec<VertexId>,
34 edge_type: Vec<Arc<str>>,
35 ranking: Vec<i64>,
36}
37
38impl EdgeHeaderColumn {
39 pub(crate) fn from_parts(
42 src: Vec<VertexId>,
43 dst: Vec<VertexId>,
44 edge_type: Vec<String>,
45 ranking: Vec<i64>,
46 ) -> Self {
47 debug_assert!(
48 src.len() == dst.len() && src.len() == edge_type.len() && src.len() == ranking.len(),
49 "edge identity vectors must share one length"
50 );
51 let edge_type = edge_type
52 .into_iter()
53 .map(|s| Arc::from(s.as_str()))
54 .collect();
55 Self {
56 src,
57 dst,
58 edge_type,
59 ranking,
60 }
61 }
62
63 pub(crate) fn len(&self) -> usize {
64 self.src.len()
65 }
66
67 pub(crate) fn estimated_size(&self) -> usize {
68 self.src.capacity() * std::mem::size_of::<VertexId>()
69 + self.dst.capacity() * std::mem::size_of::<VertexId>()
70 + self.edge_type.iter().map(|s| s.len()).sum::<usize>()
71 + self.ranking.capacity() * std::mem::size_of::<i64>()
72 }
73
74 pub(crate) fn header_at(&self, idx: usize) -> Option<EdgeHeader> {
76 match (
77 self.src.get(idx),
78 self.dst.get(idx),
79 self.edge_type.get(idx),
80 self.ranking.get(idx),
81 ) {
82 (Some(&src), Some(&dst), Some(edge_type), Some(&ranking)) => {
83 Some(EdgeHeader::new(src, dst, edge_type.to_string(), ranking))
84 }
85 _ => None,
86 }
87 }
88
89 pub(crate) fn to_values(&self) -> Vec<Value> {
91 self.src
92 .iter()
93 .zip(self.dst.iter())
94 .zip(self.edge_type.iter())
95 .zip(self.ranking.iter())
96 .map(|(((src, dst), edge_type), ranking)| {
97 Value::edge_header(EdgeHeader::new(*src, *dst, edge_type.to_string(), *ranking))
98 })
99 .collect()
100 }
101
102 pub(crate) fn gather(&self, indices: &[usize]) -> Self {
104 Self {
105 src: indices.iter().map(|&i| self.src[i]).collect(),
106 dst: indices.iter().map(|&i| self.dst[i]).collect(),
107 edge_type: indices.iter().map(|&i| self.edge_type[i].clone()).collect(),
108 ranking: indices.iter().map(|&i| self.ranking[i]).collect(),
109 }
110 }
111
112 pub(crate) fn truncate(&mut self, len: usize) {
113 self.src.truncate(len);
114 self.dst.truncate(len);
115 self.edge_type.truncate(len);
116 self.ranking.truncate(len);
117 }
118
119 pub(crate) fn permute(&mut self, perm: &[usize]) {
121 let old = std::mem::replace(
122 self,
123 Self {
124 src: Vec::new(),
125 dst: Vec::new(),
126 edge_type: Vec::new(),
127 ranking: Vec::new(),
128 },
129 );
130 self.src = perm.iter().map(|&i| old.src[i]).collect();
131 self.dst = perm.iter().map(|&i| old.dst[i]).collect();
132 self.edge_type = perm.iter().map(|&i| old.edge_type[i].clone()).collect();
133 self.ranking = perm.iter().map(|&i| old.ranking[i]).collect();
134 }
135
136 pub(crate) fn extend_indexed(&mut self, other: &Self, indices: &[usize]) {
138 self.src.extend(indices.iter().map(|&i| other.src[i]));
139 self.dst.extend(indices.iter().map(|&i| other.dst[i]));
140 self.edge_type
141 .extend(indices.iter().map(|&i| other.edge_type[i].clone()));
142 self.ranking
143 .extend(indices.iter().map(|&i| other.ranking[i]));
144 }
145
146 pub(crate) fn push(&mut self, src: VertexId, dst: VertexId, edge_type: &str, ranking: i64) {
148 self.src.push(src);
149 self.dst.push(dst);
150 self.edge_type.push(Arc::from(edge_type));
151 self.ranking.push(ranking);
152 }
153}
154
155#[inline]
157pub(crate) fn bitmap_is_valid(bitmap: &[u64], idx: usize) -> bool {
158 bitmap[idx / 64] & (1u64 << (idx % 64)) != 0
159}
160
161#[inline]
163pub(crate) fn bitmap_set_bit(bitmap: &mut [u64], idx: usize, valid: bool) {
164 if valid {
165 bitmap[idx / 64] |= 1u64 << (idx % 64);
166 } else {
167 bitmap[idx / 64] &= !(1u64 << (idx % 64));
168 }
169}
170
171pub(crate) fn gather_bitmap(bitmap: &[u64], indices: &[usize]) -> Vec<u64> {
173 let mut out = vec![0u64; indices.len().div_ceil(64)];
174 for (j, &i) in indices.iter().enumerate() {
175 bitmap_set_bit(&mut out, j, bitmap_is_valid(bitmap, i));
176 }
177 out
178}
179
180macro_rules! column_variants {
192 ($name:ident $(, $extra:ident)*) => {
193 #[derive(Debug, Clone)]
194 pub enum $name {
195 $($extra,)*
196 I64(Vec<i64>),
197 F64(Vec<f64>),
198 I32(Vec<i32>),
199 Bool(Vec<bool>),
200 Date(Vec<i64>),
202 DateTime(Vec<i64>),
204 Utf8(Vec<Arc<str>>),
205 Decimal(Vec<Decimal128Value>),
207 NullableI64(Vec<i64>, Vec<u64>),
209 NullableF64(Vec<f64>, Vec<u64>),
211 NullableI32(Vec<i32>, Vec<u64>),
213 NullableBool(Vec<bool>, Vec<u64>),
215 NullableDate(Vec<i64>, Vec<u64>),
217 NullableDateTime(Vec<i64>, Vec<u64>),
219 NullableUtf8(Vec<Arc<str>>, Vec<u64>),
221 NullableDecimal(Vec<Decimal128Value>, Vec<u64>),
223 VertexIdentity(Vec<linkrs_core::types::VertexId>),
225 EdgeHeader(EdgeHeaderColumn),
227 Fallback(Vec<Value>),
228 }
229
230 impl $name {
231 pub fn len(&self) -> usize {
232 match self {
233 $($name::$extra => 0,)*
234 $name::I64(v) => v.len(),
235 $name::F64(v) => v.len(),
236 $name::I32(v) => v.len(),
237 $name::Bool(v) => v.len(),
238 $name::Date(v) => v.len(),
239 $name::DateTime(v) => v.len(),
240 $name::Utf8(v) => v.len(),
241 $name::Decimal(v) => v.len(),
242 $name::NullableI64(v, _) => v.len(),
243 $name::NullableF64(v, _) => v.len(),
244 $name::NullableI32(v, _) => v.len(),
245 $name::NullableBool(v, _) => v.len(),
246 $name::NullableDate(v, _) => v.len(),
247 $name::NullableDateTime(v, _) => v.len(),
248 $name::NullableUtf8(v, _) => v.len(),
249 $name::NullableDecimal(v, _) => v.len(),
250 $name::VertexIdentity(v) => v.len(),
251 $name::EdgeHeader(v) => v.len(),
252 $name::Fallback(v) => v.len(),
253 }
254 }
255
256 pub fn is_empty(&self) -> bool {
257 self.len() == 0
258 }
259
260 pub fn estimated_size(&self) -> usize {
262 match self {
263 $($name::$extra => 0,)*
264 $name::I64(v) => v.capacity() * std::mem::size_of::<i64>(),
265 $name::F64(v) => v.capacity() * std::mem::size_of::<f64>(),
266 $name::I32(v) => v.capacity() * std::mem::size_of::<i32>(),
267 $name::Bool(v) => v.capacity() * std::mem::size_of::<bool>(),
268 $name::Date(v) => v.capacity() * std::mem::size_of::<i64>(),
269 $name::DateTime(v) => v.capacity() * std::mem::size_of::<i64>(),
270 $name::Utf8(v) => v.iter().map(|s| s.len()).sum(),
271 $name::Decimal(v) => v.capacity() * std::mem::size_of::<Decimal128Value>(),
272 $name::NullableI64(v, b) => {
273 v.capacity() * std::mem::size_of::<i64>()
274 + b.capacity() * std::mem::size_of::<u64>()
275 }
276 $name::NullableF64(v, b) => {
277 v.capacity() * std::mem::size_of::<f64>()
278 + b.capacity() * std::mem::size_of::<u64>()
279 }
280 $name::NullableI32(v, b) => {
281 v.capacity() * std::mem::size_of::<i32>()
282 + b.capacity() * std::mem::size_of::<u64>()
283 }
284 $name::NullableBool(v, b) => {
285 v.capacity() * std::mem::size_of::<bool>()
286 + b.capacity() * std::mem::size_of::<u64>()
287 }
288 $name::NullableDate(v, b) => {
289 v.capacity() * std::mem::size_of::<i64>()
290 + b.capacity() * std::mem::size_of::<u64>()
291 }
292 $name::NullableDateTime(v, b) => {
293 v.capacity() * std::mem::size_of::<i64>()
294 + b.capacity() * std::mem::size_of::<u64>()
295 }
296 $name::NullableUtf8(v, b) => {
297 v.iter().map(|s| s.len()).sum::<usize>()
298 + b.capacity() * std::mem::size_of::<u64>()
299 }
300 $name::NullableDecimal(v, b) => {
301 v.capacity() * std::mem::size_of::<Decimal128Value>()
302 + b.capacity() * std::mem::size_of::<u64>()
303 }
304 $name::VertexIdentity(v) => {
305 v.capacity() * std::mem::size_of::<linkrs_core::types::VertexId>()
306 }
307 $name::EdgeHeader(v) => v.estimated_size(),
308 $name::Fallback(v) => v.iter().map(Value::estimated_size).sum(),
309 }
310 }
311 }
312 };
313}
314
315pub(crate) use column_variants;
316
317macro_rules! gather_column {
323 ($out:ident, $col:expr, $indices:expr) => {{
324 let indices: &[usize] = $indices;
325 match $col {
326 TypedColumn::I64(v) => $out::I64(indices.iter().map(|&i| v[i]).collect()),
327 TypedColumn::F64(v) => $out::F64(indices.iter().map(|&i| v[i]).collect()),
328 TypedColumn::I32(v) => $out::I32(indices.iter().map(|&i| v[i]).collect()),
329 TypedColumn::Bool(v) => $out::Bool(indices.iter().map(|&i| v[i]).collect()),
330 TypedColumn::Date(v) => $out::Date(indices.iter().map(|&i| v[i]).collect()),
331 TypedColumn::DateTime(v) => $out::DateTime(indices.iter().map(|&i| v[i]).collect()),
332 TypedColumn::Utf8(v) => $out::Utf8(indices.iter().map(|&i| v[i].clone()).collect()),
333 TypedColumn::Decimal(v) => {
334 $out::Decimal(indices.iter().map(|&i| v[i].clone()).collect())
335 }
336 TypedColumn::NullableI64(v, b) => $out::NullableI64(
337 indices.iter().map(|&i| v[i]).collect(),
338 gather_bitmap(b, indices),
339 ),
340 TypedColumn::NullableF64(v, b) => $out::NullableF64(
341 indices.iter().map(|&i| v[i]).collect(),
342 gather_bitmap(b, indices),
343 ),
344 TypedColumn::NullableI32(v, b) => $out::NullableI32(
345 indices.iter().map(|&i| v[i]).collect(),
346 gather_bitmap(b, indices),
347 ),
348 TypedColumn::NullableBool(v, b) => $out::NullableBool(
349 indices.iter().map(|&i| v[i]).collect(),
350 gather_bitmap(b, indices),
351 ),
352 TypedColumn::NullableDate(v, b) => $out::NullableDate(
353 indices.iter().map(|&i| v[i]).collect(),
354 gather_bitmap(b, indices),
355 ),
356 TypedColumn::NullableDateTime(v, b) => $out::NullableDateTime(
357 indices.iter().map(|&i| v[i]).collect(),
358 gather_bitmap(b, indices),
359 ),
360 TypedColumn::NullableUtf8(v, b) => $out::NullableUtf8(
361 indices.iter().map(|&i| v[i].clone()).collect(),
362 gather_bitmap(b, indices),
363 ),
364 TypedColumn::NullableDecimal(v, b) => $out::NullableDecimal(
365 indices.iter().map(|&i| v[i].clone()).collect(),
366 gather_bitmap(b, indices),
367 ),
368 TypedColumn::VertexIdentity(v) => {
369 $out::VertexIdentity(indices.iter().map(|&i| v[i]).collect())
370 }
371 TypedColumn::EdgeHeader(v) => $out::EdgeHeader(v.gather(indices)),
372 TypedColumn::Fallback(v) => {
373 $out::Fallback(indices.iter().map(|&i| v[i].clone()).collect())
374 }
375 }
376 }};
377}
378
379pub(crate) use gather_column;