vortex_btrblocks/schemes/string/
onpair.rs1use vortex_array::ArrayId;
7use vortex_array::ArrayRef;
8use vortex_array::Canonical;
9use vortex_array::ExecutionCtx;
10use vortex_array::IntoArray;
11use vortex_array::VTable;
12use vortex_array::arrays::PrimitiveArray;
13use vortex_array::arrays::primitive::PrimitiveArrayExt;
14use vortex_compressor::scheme::CompressionEstimate;
15use vortex_compressor::scheme::DeferredEstimate;
16use vortex_compressor::scheme::SchemeId;
17use vortex_error::VortexResult;
18use vortex_onpair::DEFAULT_CONFIG;
19use vortex_onpair::OnPair;
20use vortex_onpair::OnPairArrayExt;
21use vortex_onpair::OnPairArraySlotsExt;
22use vortex_onpair::onpair_compress;
23
24use crate::ArrayAndStats;
25use crate::CascadingCompressor;
26use crate::CompressorContext;
27use crate::Scheme;
28use crate::SchemeExt;
29
30#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40pub struct OnPairScheme;
41
42impl Scheme for OnPairScheme {
43 fn scheme_name(&self) -> &'static str {
44 "vortex.string.onpair"
45 }
46
47 fn matches(&self, canonical: &Canonical) -> bool {
48 canonical.dtype().is_utf8()
49 }
50
51 fn produced_encodings(&self) -> Vec<ArrayId> {
52 vec![OnPair.id()]
53 }
54
55 fn num_children(&self) -> usize {
61 4
62 }
63
64 fn expected_compression_ratio(
65 &self,
66 _data: &ArrayAndStats,
67 _compress_ctx: CompressorContext,
68 _exec_ctx: &mut ExecutionCtx,
69 ) -> CompressionEstimate {
70 CompressionEstimate::Deferred(DeferredEstimate::Sample)
71 }
72
73 fn compress(
74 &self,
75 compressor: &CascadingCompressor,
76 data: &ArrayAndStats,
77 compress_ctx: CompressorContext,
78 exec_ctx: &mut ExecutionCtx,
79 ) -> VortexResult<ArrayRef> {
80 let utf8 = data.array_as_varbinview().into_owned();
81 let encoded = onpair_compress(utf8.as_array(), DEFAULT_CONFIG, exec_ctx)?;
82 let Some(onpair_array) = encoded.as_opt::<OnPair>() else {
83 return Ok(encoded);
84 };
85
86 let dict_offsets = compress_primitive_child(
87 compressor,
88 onpair_array.dict_offsets(),
89 &compress_ctx,
90 self.id(),
91 0,
92 exec_ctx,
93 )?;
94 let codes = compress_primitive_child(
95 compressor,
96 onpair_array.codes(),
97 &compress_ctx,
98 self.id(),
99 1,
100 exec_ctx,
101 )?;
102 let codes_offsets = compress_primitive_child(
103 compressor,
104 onpair_array.codes_offsets(),
105 &compress_ctx,
106 self.id(),
107 2,
108 exec_ctx,
109 )?;
110 let uncompressed_lengths = compress_primitive_child(
111 compressor,
112 onpair_array.uncompressed_lengths(),
113 &compress_ctx,
114 self.id(),
115 3,
116 exec_ctx,
117 )?;
118
119 Ok(OnPair::try_new_with_data(
120 onpair_array.dtype().clone(),
121 onpair_array.data().clone(),
122 dict_offsets,
123 codes,
124 codes_offsets,
125 uncompressed_lengths,
126 onpair_array.array_validity(),
127 )?
128 .into_array())
129 }
130}
131
132fn compress_primitive_child(
135 compressor: &CascadingCompressor,
136 child: &ArrayRef,
137 compress_ctx: &CompressorContext,
138 scheme_id: SchemeId,
139 child_idx: usize,
140 exec_ctx: &mut ExecutionCtx,
141) -> VortexResult<ArrayRef> {
142 let narrowed = child
143 .clone()
144 .execute::<PrimitiveArray>(exec_ctx)?
145 .narrow(exec_ctx)?
146 .into_array();
147 compressor.compress_child(&narrowed, compress_ctx, scheme_id, child_idx, exec_ctx)
148}
149
150