reifydb_value/value/container/
digest_array.rs1use std::borrow::Borrow;
5
6use arrow_array::{Array, LargeBinaryArray, builder::LargeBinaryBuilder};
7
8use crate::value::{Value, container::varlen_array, digest::Digest};
9
10fn decode(row: &[u8]) -> Digest {
11 Digest::decode(row).unwrap_or_else(|error| panic!("corrupt Digest row {row:02x?}: {error}"))
12}
13
14pub fn digest_array<B: Borrow<Digest>>(values: impl IntoIterator<Item = Option<B>>) -> LargeBinaryArray {
15 let mut builder = LargeBinaryBuilder::new();
16 for value in values {
17 match value {
18 Some(digest) => push_digest(&mut builder, digest.borrow()),
19 None => builder.append_null(),
20 }
21 }
22 builder.finish()
23}
24
25pub fn push_digest(builder: &mut LargeBinaryBuilder, digest: &Digest) {
26 builder.append_value(digest.encode());
27}
28
29pub fn get(array: &LargeBinaryArray, index: usize) -> Option<Digest> {
30 varlen_array::get(array, index).filter(|_| array.is_valid(index)).map(decode)
31}
32
33pub fn iter(array: &LargeBinaryArray) -> impl Iterator<Item = Option<Digest>> + '_ {
34 (0..array.len()).map(move |index| get(array, index))
35}
36
37pub fn is_defined(array: &LargeBinaryArray, index: usize) -> bool {
38 index < array.len() && array.is_valid(index)
39}
40
41pub fn get_value(array: &LargeBinaryArray, index: usize) -> Value {
42 match get(array, index) {
43 Some(digest) => Value::Digest(Box::new(digest)),
44 None => Value::none(),
45 }
46}
47
48pub fn as_string(array: &LargeBinaryArray, index: usize) -> String {
49 get_value(array, index).to_string()
50}
51
52#[cfg(test)]
53mod tests {
54
55 use super::*;
56 use crate::value::digest::tests::built;
57
58 #[test]
59 fn an_empty_row_is_the_none_slot() {
60 let digest = built(10_000, &[1.0, 2.5, -4.0]);
62 let array = digest_array([Some(&digest), None]);
63 assert!(array.is_null(1));
64 assert_eq!(array.null_count(), 1);
65 assert!(is_defined(&array, 0));
66 assert!(!is_defined(&array, 1));
67 assert!(!is_defined(&array, 2));
68 assert_eq!(get(&array, 0), Some(digest.clone()));
69 assert_eq!(get(&array, 1), None);
70 assert_eq!(get_value(&array, 0), Value::Digest(Box::new(digest)));
71 assert_eq!(get_value(&array, 1), Value::none());
72 assert_eq!(as_string(&array, 1), Value::none().to_string());
73 assert_eq!(iter(&array).filter(Option::is_some).count(), 1);
74 }
75
76 #[test]
77 fn reorder_past_the_end_fails() {
78 let error = varlen_array::reorder(&digest_array([Some(built(10_000, &[1.0]))]), &[4, 0]).unwrap_err();
80 assert_eq!(error.diagnostic().message, "row index 4 out of range for a column of 1 rows");
81 }
82}