vortex_btrblocks/schemes/string/
fsst.rs1use std::sync::Arc;
7
8use vortex_array::ArrayId;
9use vortex_array::ArrayRef;
10use vortex_array::Canonical;
11use vortex_array::ExecutionCtx;
12use vortex_array::IntoArray;
13use vortex_array::VTable;
14use vortex_array::arrays::PrimitiveArray;
15use vortex_array::arrays::VarBin;
16use vortex_array::arrays::VarBinArray;
17use vortex_array::arrays::primitive::PrimitiveArrayExt;
18use vortex_array::arrays::varbin::VarBinArraySlotsExt;
19use vortex_compressor::scheme::CompressionEstimate;
20use vortex_compressor::scheme::DeferredEstimate;
21use vortex_error::VortexResult;
22use vortex_fsst::FSST;
23use vortex_fsst::FSSTArrayExt;
24use vortex_fsst::FSSTArraySlotsExt;
25use vortex_fsst::FSSTSymbolTable;
26use vortex_fsst::fsst_compress;
27use vortex_fsst::fsst_train_compressor;
28
29use crate::ArrayAndStats;
30use crate::CascadingCompressor;
31use crate::CompressorContext;
32use crate::Scheme;
33use crate::SchemeExt;
34
35#[derive(Debug, Copy, Clone, PartialEq, Eq)]
42pub struct FSSTScheme;
43
44impl Scheme for FSSTScheme {
45 fn scheme_name(&self) -> &'static str {
46 "vortex.string.fsst"
47 }
48
49 fn matches(&self, canonical: &Canonical) -> bool {
50 canonical.dtype().is_utf8()
51 }
52
53 fn produced_encodings(&self) -> Vec<ArrayId> {
54 vec![FSST.id(), VarBin.id()]
55 }
56
57 fn num_children(&self) -> usize {
59 2
60 }
61
62 fn expected_compression_ratio(
63 &self,
64 _data: &ArrayAndStats,
65 _compress_ctx: CompressorContext,
66 _exec_ctx: &mut ExecutionCtx,
67 ) -> CompressionEstimate {
68 CompressionEstimate::Deferred(DeferredEstimate::Sample)
69 }
70
71 fn compress(
72 &self,
73 compressor: &CascadingCompressor,
74 data: &ArrayAndStats,
75 compress_ctx: CompressorContext,
76 exec_ctx: &mut ExecutionCtx,
77 ) -> VortexResult<ArrayRef> {
78 let utf8 = data.array_as_varbinview().into_owned().into_array();
79 let compressor_fsst = fsst_train_compressor(&utf8, exec_ctx)?;
80 let fsst = fsst_compress(&utf8, &compressor_fsst, exec_ctx)?;
81
82 let uncompressed_lengths_primitive = fsst
83 .uncompressed_lengths()
84 .clone()
85 .execute::<PrimitiveArray>(exec_ctx)?
86 .narrow(exec_ctx)?;
87 let compressed_original_lengths = compressor.compress_child(
88 &uncompressed_lengths_primitive.into_array(),
89 &compress_ctx,
90 self.id(),
91 0,
92 exec_ctx,
93 )?;
94
95 let codes_offsets_primitive = fsst
96 .codes()
97 .offsets()
98 .clone()
99 .execute::<PrimitiveArray>(exec_ctx)?
100 .narrow(exec_ctx)?;
101 let compressed_codes_offsets = compressor.compress_child(
102 &codes_offsets_primitive.into_array(),
103 &compress_ctx,
104 self.id(),
105 1,
106 exec_ctx,
107 )?;
108 let compressed_codes = VarBinArray::try_new(
109 compressed_codes_offsets,
110 fsst.codes().bytes().clone(),
111 fsst.codes().dtype().clone(),
112 fsst.codes().validity()?,
113 )?;
114
115 let fsst = FSST::try_new_with_symbol_table(
117 fsst.dtype().clone(),
118 Arc::new(FSSTSymbolTable::new_padded(
119 fsst.padded_symbols().clone(),
120 fsst.padded_symbol_lengths().clone(),
121 fsst.n_symbols(),
122 )?),
123 compressed_codes,
124 compressed_original_lengths,
125 exec_ctx,
126 )?;
127
128 Ok(fsst.into_array())
129 }
130}