vortex_array/stats/
flatbuffers.rs1use flatbuffers::{FlatBufferBuilder, Follow, WIPOffset};
5use vortex_dtype::{DType, Nullability, PType};
6use vortex_error::{VortexError, vortex_bail};
7use vortex_flatbuffers::{ReadFlatBuffer, WriteFlatBuffer, array as fba};
8use vortex_scalar::ScalarValue;
9
10use crate::stats::{Precision, Stat, StatsSet, StatsSetRef};
11
12impl WriteFlatBuffer for StatsSetRef<'_> {
13 type Target<'t> = fba::ArrayStats<'t>;
14
15 fn write_flatbuffer<'fb>(
17 &self,
18 fbb: &mut FlatBufferBuilder<'fb>,
19 ) -> WIPOffset<Self::Target<'fb>> {
20 self.with_typed_stats_set(|stats_set| stats_set.values.write_flatbuffer(fbb))
21 }
22}
23
24impl WriteFlatBuffer for StatsSet {
25 type Target<'t> = fba::ArrayStats<'t>;
26
27 fn write_flatbuffer<'fb>(
29 &self,
30 fbb: &mut FlatBufferBuilder<'fb>,
31 ) -> WIPOffset<Self::Target<'fb>> {
32 let (min_precision, min) = self
33 .get(Stat::Min)
34 .map(|min| {
35 (
36 if min.is_exact() {
37 fba::Precision::Exact
38 } else {
39 fba::Precision::Inexact
40 },
41 Some(fbb.create_vector(&min.into_inner().to_protobytes::<Vec<u8>>())),
42 )
43 })
44 .unwrap_or_else(|| (fba::Precision::Inexact, None));
45
46 let (max_precision, max) = self
47 .get(Stat::Max)
48 .map(|max| {
49 (
50 if max.is_exact() {
51 fba::Precision::Exact
52 } else {
53 fba::Precision::Inexact
54 },
55 Some(fbb.create_vector(&max.into_inner().to_protobytes::<Vec<u8>>())),
56 )
57 })
58 .unwrap_or_else(|| (fba::Precision::Inexact, None));
59
60 let sum = self
61 .get(Stat::Sum)
62 .and_then(Precision::as_exact)
63 .map(|sum| fbb.create_vector(&sum.to_protobytes::<Vec<u8>>()));
64
65 let stat_args = &fba::ArrayStatsArgs {
66 min,
67 min_precision,
68 max,
69 max_precision,
70 sum,
71 is_sorted: self
72 .get_as::<bool>(Stat::IsSorted, &DType::Bool(Nullability::NonNullable))
73 .and_then(Precision::as_exact),
74 is_strict_sorted: self
75 .get_as::<bool>(Stat::IsStrictSorted, &DType::Bool(Nullability::NonNullable))
76 .and_then(Precision::as_exact),
77 is_constant: self
78 .get_as::<bool>(Stat::IsConstant, &DType::Bool(Nullability::NonNullable))
79 .and_then(Precision::as_exact),
80 null_count: self
81 .get_as::<u64>(Stat::NullCount, &PType::U64.into())
82 .and_then(Precision::as_exact),
83 uncompressed_size_in_bytes: self
84 .get_as::<u64>(Stat::UncompressedSizeInBytes, &PType::U64.into())
85 .and_then(Precision::as_exact),
86 nan_count: self
87 .get_as::<u64>(Stat::NaNCount, &PType::U64.into())
88 .and_then(Precision::as_exact),
89 };
90
91 fba::ArrayStats::create(fbb, stat_args)
92 }
93}
94
95impl ReadFlatBuffer for StatsSet {
96 type Source<'a> = fba::ArrayStats<'a>;
97 type Error = VortexError;
98
99 fn read_flatbuffer<'buf>(
100 fb: &<Self::Source<'buf> as Follow<'buf>>::Inner,
101 ) -> Result<Self, Self::Error> {
102 let mut stats_set = StatsSet::default();
103
104 for stat in Stat::all() {
105 match stat {
106 Stat::IsConstant => {
107 if let Some(is_constant) = fb.is_constant() {
108 stats_set.set(Stat::IsConstant, Precision::Exact(is_constant.into()));
109 }
110 }
111 Stat::IsSorted => {
112 if let Some(is_sorted) = fb.is_sorted() {
113 stats_set.set(Stat::IsSorted, Precision::Exact(is_sorted.into()));
114 }
115 }
116 Stat::IsStrictSorted => {
117 if let Some(is_strict_sorted) = fb.is_strict_sorted() {
118 stats_set.set(
119 Stat::IsStrictSorted,
120 Precision::Exact(is_strict_sorted.into()),
121 );
122 }
123 }
124 Stat::Max => {
125 if let Some(max) = fb.max() {
126 let value = ScalarValue::from_protobytes(max.bytes())?;
127 stats_set.set(
128 Stat::Max,
129 match fb.max_precision() {
130 fba::Precision::Exact => Precision::Exact(value),
131 fba::Precision::Inexact => Precision::Inexact(value),
132 other => vortex_bail!("Corrupted max_precision field: {other:?}"),
133 },
134 );
135 }
136 }
137 Stat::Min => {
138 if let Some(min) = fb.min() {
139 let value = ScalarValue::from_protobytes(min.bytes())?;
140 stats_set.set(
141 Stat::Min,
142 match fb.min_precision() {
143 fba::Precision::Exact => Precision::Exact(value),
144 fba::Precision::Inexact => Precision::Inexact(value),
145 other => vortex_bail!("Corrupted min_precision field: {other:?}"),
146 },
147 );
148 }
149 }
150 Stat::NullCount => {
151 if let Some(null_count) = fb.null_count() {
152 stats_set.set(Stat::NullCount, Precision::Exact(null_count.into()));
153 }
154 }
155 Stat::UncompressedSizeInBytes => {
156 if let Some(uncompressed_size_in_bytes) = fb.uncompressed_size_in_bytes() {
157 stats_set.set(
158 Stat::UncompressedSizeInBytes,
159 Precision::Exact(uncompressed_size_in_bytes.into()),
160 );
161 }
162 }
163 Stat::Sum => {
164 if let Some(sum) = fb.sum() {
165 stats_set.set(
166 Stat::Sum,
167 Precision::Exact(ScalarValue::from_protobytes(sum.bytes())?),
168 );
169 }
170 }
171 Stat::NaNCount => {
172 if let Some(nan_count) = fb.nan_count() {
173 stats_set.set(
174 Stat::NaNCount,
175 Precision::Exact(ScalarValue::from(nan_count)),
176 );
177 }
178 }
179 }
180 }
181
182 Ok(stats_set)
183 }
184}