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