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