1use std::collections::BTreeMap;
19
20use crate::error::Error;
21use crate::types::{Date, Duration, Timestamp};
22
23use super::reader::{ArrayView, MapView};
24use super::writer::{ArrayWriter, MapWriter, ValueWriter};
25
26#[doc(hidden)]
32pub trait RowValue {
33 type View<'a>;
35
36 const FIXED_SIZE: Option<usize>;
38
39 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error>;
41
42 fn read<'a>(bytes: &'a [u8]) -> Result<Self::View<'a>, Error>;
44
45 fn is_null(&self) -> bool {
47 false
48 }
49
50 fn read_null<'a>() -> Result<Self::View<'a>, Error> {
52 Err(Error::invalid_data(
53 "null row value cannot be read as a non-optional type",
54 ))
55 }
56}
57
58pub trait Row: RowValue {}
63
64macro_rules! impl_fixed_row_value {
65 ($ty:ty, $size:expr) => {
66 impl RowValue for $ty {
67 type View<'a> = Self;
68
69 const FIXED_SIZE: Option<usize> = Some($size);
70
71 #[inline(always)]
72 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
73 writer.write_bytes(&self.to_le_bytes())
74 }
75
76 #[inline(always)]
77 fn read(bytes: &[u8]) -> Result<Self, Error> {
78 Ok(Self::from_le_bytes(read_fixed(bytes)?))
79 }
80 }
81 };
82}
83
84impl RowValue for bool {
85 type View<'a> = Self;
86
87 const FIXED_SIZE: Option<usize> = Some(1);
88
89 #[inline(always)]
90 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
91 writer.write_bytes(&[u8::from(*self)])
92 }
93
94 #[inline(always)]
95 fn read(bytes: &[u8]) -> Result<Self, Error> {
96 match read_fixed::<1>(bytes)?[0] {
97 0 => Ok(false),
98 1 => Ok(true),
99 _ => Err(Error::invalid_data("row boolean must be encoded as 0 or 1")),
100 }
101 }
102}
103
104impl RowValue for i8 {
105 type View<'a> = Self;
106
107 const FIXED_SIZE: Option<usize> = Some(1);
108
109 #[inline(always)]
110 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
111 writer.write_bytes(&self.to_le_bytes())
112 }
113
114 #[inline(always)]
115 fn read(bytes: &[u8]) -> Result<Self, Error> {
116 Ok(Self::from_le_bytes(read_fixed(bytes)?))
117 }
118}
119
120impl_fixed_row_value!(i16, 2);
121impl_fixed_row_value!(i32, 4);
122impl_fixed_row_value!(i64, 8);
123impl_fixed_row_value!(f32, 4);
124impl_fixed_row_value!(f64, 8);
125
126impl RowValue for String {
127 type View<'a> = &'a str;
128
129 const FIXED_SIZE: Option<usize> = None;
130
131 #[inline(always)]
132 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
133 writer.write_bytes(self.as_bytes())
134 }
135
136 #[inline]
137 fn read(bytes: &[u8]) -> Result<&str, Error> {
138 std::str::from_utf8(bytes).map_err(|_| Error::invalid_data("invalid UTF-8 in row string"))
139 }
140}
141
142impl RowValue for &str {
143 type View<'a> = &'a str;
144
145 const FIXED_SIZE: Option<usize> = None;
146
147 #[inline(always)]
148 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
149 writer.write_bytes(self.as_bytes())
150 }
151
152 #[inline]
153 fn read(bytes: &[u8]) -> Result<&str, Error> {
154 std::str::from_utf8(bytes).map_err(|_| Error::invalid_data("invalid UTF-8 in row string"))
155 }
156}
157
158impl RowValue for Vec<u8> {
159 type View<'a> = &'a [u8];
160
161 const FIXED_SIZE: Option<usize> = None;
162
163 #[inline(always)]
164 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
165 writer.write_bytes(self)
166 }
167
168 #[inline(always)]
169 fn read(bytes: &[u8]) -> Result<&[u8], Error> {
170 Ok(bytes)
171 }
172}
173
174impl RowValue for &[u8] {
175 type View<'a> = &'a [u8];
176
177 const FIXED_SIZE: Option<usize> = None;
178
179 #[inline(always)]
180 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
181 writer.write_bytes(self)
182 }
183
184 #[inline(always)]
185 fn read(bytes: &[u8]) -> Result<&[u8], Error> {
186 Ok(bytes)
187 }
188}
189
190impl<T: RowValue> RowValue for Option<T> {
191 type View<'a> = Option<T::View<'a>>;
192
193 const FIXED_SIZE: Option<usize> = T::FIXED_SIZE;
194
195 #[inline(always)]
196 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
197 match self {
198 Some(value) => value.write(writer),
199 None => Err(Error::invalid_data(
200 "a null row value must be written by its container",
201 )),
202 }
203 }
204
205 #[inline(always)]
206 fn read<'a>(bytes: &'a [u8]) -> Result<Self::View<'a>, Error> {
207 T::read(bytes).map(Some)
208 }
209
210 #[inline(always)]
211 fn is_null(&self) -> bool {
212 self.is_none()
213 }
214
215 #[inline(always)]
216 fn read_null<'a>() -> Result<Self::View<'a>, Error> {
217 Ok(None)
218 }
219}
220
221impl RowValue for Date {
222 type View<'a> = Self;
223
224 const FIXED_SIZE: Option<usize> = Some(4);
225
226 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
227 let days = i32::try_from(self.epoch_days()).map_err(|_| {
228 Error::invalid_data(format!(
229 "row date day count {} exceeds date32 range",
230 self.epoch_days()
231 ))
232 })?;
233 writer.write_bytes(&days.to_le_bytes())
234 }
235
236 fn read(bytes: &[u8]) -> Result<Self, Error> {
237 let days = i32::from_le_bytes(read_fixed(bytes)?);
238 Ok(Date::from_epoch_days(i64::from(days)))
239 }
240}
241
242impl RowValue for Timestamp {
243 type View<'a> = Self;
244
245 const FIXED_SIZE: Option<usize> = Some(8);
246
247 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
248 writer.write_bytes(&self.to_epoch_micros()?.to_le_bytes())
249 }
250
251 fn read(bytes: &[u8]) -> Result<Self, Error> {
252 Ok(Timestamp::from_epoch_micros(i64::from_le_bytes(
253 read_fixed(bytes)?,
254 )))
255 }
256}
257
258impl RowValue for Duration {
259 type View<'a> = Self;
260
261 const FIXED_SIZE: Option<usize> = Some(8);
262
263 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
264 writer.write_bytes(&self.to_micros()?.to_le_bytes())
265 }
266
267 fn read(bytes: &[u8]) -> Result<Self, Error> {
268 Ok(Duration::from_micros(i64::from_le_bytes(read_fixed(
269 bytes,
270 )?)))
271 }
272}
273
274impl<T: RowValue, const N: usize> RowValue for [T; N] {
275 type View<'a> = ArrayView<'a, T>;
276
277 const FIXED_SIZE: Option<usize> = None;
278
279 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
280 let mut array_writer = ArrayWriter::<T>::new(N, writer.into_variable()?)?;
281 for (index, value) in self.iter().enumerate() {
282 array_writer.write(index, value)?;
283 }
284 Ok(())
285 }
286
287 fn read(bytes: &[u8]) -> Result<Self::View<'_>, Error> {
288 let view = ArrayView::new(bytes)?;
289 if view.len() != N {
290 return Err(Error::invalid_data(format!(
291 "row fixed array expected {N} elements, found {}",
292 view.len()
293 )));
294 }
295 Ok(view)
296 }
297}
298
299impl<T: RowValue, const N: usize> Row for [T; N] {}
300
301impl<T: RowValue> RowValue for Vec<T> {
302 type View<'a> = ArrayView<'a, T>;
303
304 const FIXED_SIZE: Option<usize> = None;
305
306 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
307 let mut array_writer = ArrayWriter::<T>::new(self.len(), writer.into_variable()?)?;
308 for (index, value) in self.iter().enumerate() {
309 array_writer.write(index, value)?;
310 }
311 Ok(())
312 }
313
314 fn read(bytes: &[u8]) -> Result<Self::View<'_>, Error> {
315 ArrayView::new(bytes)
316 }
317}
318
319impl<T: RowValue> Row for Vec<T> {}
320
321impl<K, V> RowValue for BTreeMap<K, V>
322where
323 K: RowValue + Ord,
324 V: RowValue,
325{
326 type View<'a> = MapView<'a, K, V>;
327
328 const FIXED_SIZE: Option<usize> = None;
329
330 fn write(&self, writer: ValueWriter<'_, '_>) -> Result<(), Error> {
331 let mut map_writer = MapWriter::new(writer.into_variable()?);
332 map_writer.write(self)
333 }
334
335 fn read(bytes: &[u8]) -> Result<Self::View<'_>, Error> {
336 MapView::new(bytes)
337 }
338}
339
340impl<K, V> Row for BTreeMap<K, V>
341where
342 K: RowValue + Ord,
343 V: RowValue,
344{
345}
346
347fn read_fixed<const N: usize>(bytes: &[u8]) -> Result<[u8; N], Error> {
348 if bytes.len() != N {
349 return Err(Error::invalid_data(format!(
350 "row fixed-width value expected {N} bytes, found {}",
351 bytes.len()
352 )));
353 }
354 let mut value = [0u8; N];
355 value.copy_from_slice(bytes);
356 Ok(value)
357}