lance_encoding/encodings/physical/
constant.rs1use crate::{
7 buffer::LanceBuffer,
8 compression::{BlockDecompressor, FixedPerValueDecompressor, require_no_block_payload},
9 data::{AllNullDataBlock, ConstantDataBlock, DataBlock, FixedWidthDataBlock},
10};
11
12use lance_core::Result;
13
14#[derive(Debug)]
16pub struct ConstantDecompressor {
17 scalar: Option<LanceBuffer>,
18}
19
20impl ConstantDecompressor {
21 pub fn new(scalar: Option<LanceBuffer>) -> Self {
22 Self { scalar }
23 }
24}
25
26impl BlockDecompressor for ConstantDecompressor {
27 fn decompress(&self, data: Option<LanceBuffer>, num_values: u64) -> Result<DataBlock> {
28 require_no_block_payload(data, "Constant")?;
29 if let Some(scalar) = self.scalar.clone() {
30 Ok(DataBlock::Constant(ConstantDataBlock {
31 data: scalar,
32 num_values,
33 }))
34 } else {
35 Ok(DataBlock::AllNull(AllNullDataBlock { num_values }))
36 }
37 }
38
39 fn requires_payload(&self) -> bool {
40 false
41 }
42}
43
44impl FixedPerValueDecompressor for ConstantDecompressor {
45 fn decompress(&self, _data: FixedWidthDataBlock, num_values: u64) -> Result<DataBlock> {
46 if let Some(scalar) = self.scalar.clone() {
47 Ok(DataBlock::Constant(ConstantDataBlock {
48 data: scalar,
49 num_values,
50 }))
51 } else {
52 Ok(DataBlock::AllNull(AllNullDataBlock { num_values }))
53 }
54 }
55
56 fn bits_per_value(&self) -> u64 {
57 self.scalar
58 .as_ref()
59 .map(|s| s.len() as u64 * 8)
60 .unwrap_or(0)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn block_constant_requires_no_payload() {
70 let decompressor = ConstantDecompressor::new(None);
71
72 assert!(!decompressor.requires_payload());
73 assert!(matches!(
74 BlockDecompressor::decompress(&decompressor, None, 3).unwrap(),
75 DataBlock::AllNull(AllNullDataBlock { num_values: 3 })
76 ));
77 assert!(
78 BlockDecompressor::decompress(&decompressor, Some(LanceBuffer::empty()), 3).is_err()
79 );
80 }
81}