1use std::{
4 fmt::Display,
5 hash::{Hash, Hasher},
6 io::Cursor,
7};
8
9mod error;
10#[cfg(test)]
11mod test;
12mod trait_impls;
13mod traits;
14
15use crate::structure::{FrcStructDesc, FrcStructure, FrcStructureBytes};
16pub use error::FrcValueCastError;
17pub use traits::IntoFrcValue;
18pub use traits::StaticallyFrcTyped;
19
20pub use inventory;
21
22use self::error::CastErrorReason;
23
24pub type FrcTimestamp = u64;
28
29#[allow(missing_docs)]
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum FrcType {
32 Void,
33 Raw,
34 Boolean,
35 Int,
36 Double,
37 Float,
38 String,
39 BooleanArray,
40 IntArray,
41 FloatArray,
42 DoubleArray,
43 StringArray,
44 Struct(&'static FrcStructDesc),
45 StructArray(&'static FrcStructDesc),
46}
47impl Display for FrcType {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Self::Void => write!(f, "Void"),
51 Self::Boolean => write!(f, "Boolean"),
52 Self::Int => write!(f, "Int"),
53 Self::Double => write!(f, "Double"),
54 Self::Float => write!(f, "Float"),
55 Self::String => write!(f, "String"),
56 Self::BooleanArray => write!(f, "BooleanArray"),
57 Self::IntArray => write!(f, "IntArray"),
58 Self::FloatArray => write!(f, "FloatArray"),
59 Self::DoubleArray => write!(f, "DoubleArray"),
60 Self::StringArray => write!(f, "StringArray"),
61 Self::Raw => write!(f, "Raw"),
62 Self::Struct(desc) => write!(f, "Struct({})", desc.type_str),
63 Self::StructArray(desc) => write!(f, "StructArray({})", desc.type_str),
64 }
65 }
66}
67
68type BoxVec<T> = Box<[T]>;
69type BoxStr = Box<str>;
70
71#[allow(missing_docs)]
90#[derive(Debug, Clone, PartialEq)]
91pub enum FrcValue {
92 Void,
96 Raw(BoxVec<u8>),
98 Boolean(bool),
100 Int(i64),
103 Double(f64),
104 Float(f32),
105 String(Box<str>),
106 BooleanArray(BoxVec<bool>),
107 IntArray(BoxVec<i64>),
108 FloatArray(BoxVec<f32>),
109 DoubleArray(BoxVec<f64>),
110 StringArray(BoxVec<BoxStr>),
113 Struct(Box<FrcStructureBytes>),
116 StructArray(Box<FrcStructureBytes>),
119}
120impl Display for FrcValue {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 match self {
123 Self::Void => write!(f, "Void"),
124 Self::Boolean(v) => write!(f, "{v}"),
125 Self::Int(v) => write!(f, "{v}"),
126 Self::Double(v) => write!(f, "{v}"),
127 Self::Float(v) => write!(f, "{v}"),
128 Self::String(v) => write!(f, "{v}"),
129 Self::BooleanArray(v) => write!(f, "{v:?}"),
130 Self::IntArray(v) => write!(f, "{v:?}"),
131 Self::FloatArray(v) => write!(f, "{v:?}"),
132 Self::DoubleArray(v) => write!(f, "{v:?}"),
133 Self::StringArray(v) => write!(f, "{v:?}"),
134 Self::Raw(v) => write!(f, "{v:?}"),
135 Self::Struct(bytes) => write!(f, "Struct({}):{:?}", bytes.desc.type_str, bytes.data),
136 Self::StructArray(bytes) => write!(
137 f,
138 "Struct({})[{}]:{:?}",
139 bytes.desc.type_str, bytes.count, bytes.data
140 ),
141 }
142 }
143}
144impl Hash for FrcValue {
145 fn hash<H: Hasher>(&self, state: &mut H) {
146 match self {
147 Self::Void => {}
148 Self::Boolean(v) => v.hash(state),
149 Self::Int(v) => v.hash(state),
150 Self::Double(v) => v.to_bits().hash(state),
151 Self::Float(v) => v.to_bits().hash(state),
152 Self::String(v) => v.hash(state),
153 Self::BooleanArray(v) => v.hash(state),
154 Self::IntArray(v) => v.hash(state),
155 Self::FloatArray(v) => v.iter().for_each(|v| v.to_bits().hash(state)),
156 Self::DoubleArray(v) => v.iter().for_each(|v| v.to_bits().hash(state)),
157 Self::StringArray(v) => v.hash(state),
158 Self::Raw(v) => v.hash(state),
159 Self::Struct(bytes) | Self::StructArray(bytes) => {
160 bytes.desc.schema_supplier.hash(state);
161 bytes.desc.type_str.hash(state);
162 bytes.data.hash(state);
163 }
164 }
165 }
166}
167impl FrcValue {
168 #[must_use]
170 pub const fn get_type(&self) -> FrcType {
171 match self {
172 Self::Void => FrcType::Void,
173 Self::Boolean(_) => FrcType::Boolean,
174 Self::Int(_) => FrcType::Int,
175 Self::Double(_) => FrcType::Double,
176 Self::Float(_) => FrcType::Float,
177 Self::String(_) => FrcType::String,
178 Self::BooleanArray(_) => FrcType::BooleanArray,
179 Self::IntArray(_) => FrcType::IntArray,
180 Self::FloatArray(_) => FrcType::FloatArray,
181 Self::DoubleArray(_) => FrcType::DoubleArray,
182 Self::StringArray(_) => FrcType::StringArray,
183 Self::Raw(_) => FrcType::Raw,
184 Self::Struct(s) => FrcType::Struct(s.desc),
185 Self::StructArray(s) => FrcType::StructArray(s.desc),
186 }
187 }
188 #[must_use]
190 pub const fn empty() -> Self {
191 Self::Void
192 }
193 #[must_use]
195 pub const fn is_empty(&self) -> bool {
196 match self {
197 Self::Void => true,
198 Self::String(v) => v.is_empty(),
199 Self::BooleanArray(v) => v.is_empty(),
200 Self::IntArray(v) => v.is_empty(),
201 Self::DoubleArray(v) => v.is_empty(),
202 Self::FloatArray(v) => v.is_empty(),
203 Self::StringArray(v) => v.is_empty(),
204 Self::Raw(v) => v.is_empty(),
205 Self::Struct(bytes) | Self::StructArray(bytes) => bytes.data.is_empty(),
206 _ => false,
207 }
208 }
209 #[must_use]
211 pub const fn is_array(&self) -> bool {
212 matches!(
213 self,
214 Self::BooleanArray(_)
215 | Self::IntArray(_)
216 | Self::DoubleArray(_)
217 | Self::FloatArray(_)
218 | Self::StringArray(_)
219 | Self::StructArray(_)
220 )
221 }
222 #[must_use]
224 pub const fn to_timestamped(self, timestamp: FrcTimestamp) -> FrcTimestampedValue {
225 FrcTimestampedValue::new(timestamp, self)
226 }
227 #[must_use]
234 pub fn default_value(r#type: FrcType) -> Option<Self> {
235 match r#type {
236 FrcType::Boolean => Some(Self::Boolean(false)),
237 FrcType::Int => Some(Self::Int(0)),
238 FrcType::Double => Some(Self::Double(0.0)),
239 FrcType::Float => Some(Self::Float(0.0)),
240 FrcType::String => Some(Self::String(Box::default())),
241 FrcType::BooleanArray => Some(Self::BooleanArray(Box::default())),
242 FrcType::IntArray => Some(Self::IntArray(Box::default())),
243 FrcType::FloatArray => Some(Self::FloatArray(Box::default())),
244 FrcType::DoubleArray => Some(Self::DoubleArray(Box::default())),
245 FrcType::StringArray => Some(Self::StringArray(Box::default())),
246 FrcType::Raw => Some(Self::Raw(Box::default())),
247 _ => None,
248 }
249 }
250}
251
252impl FrcValue {
253 pub fn from_struct<T: FrcStructure>(value: &T) -> Self {
255 let mut buffer = Vec::with_capacity(T::SIZE);
256 value.pack(&mut buffer);
257 Self::Struct(Box::new(FrcStructureBytes::from_parts(
258 &T::DESCRIPTION,
259 1,
260 buffer.into_boxed_slice(),
261 )))
262 }
263
264 pub fn try_into_struct<T: FrcStructure>(self) -> Result<T, FrcValueCastError> {
267 let frc_type = self.get_type();
268 match self {
269 Self::Struct(bytes) => {
270 let buffer = bytes.data;
271 if buffer.len() == T::SIZE {
272 let mut cursor = Cursor::new(buffer.as_ref());
273 Ok(T::unpack(&mut cursor))
274 } else {
275 Err(FrcValueCastError::InvalidCastTo(
276 frc_type,
277 T::TYPE,
278 CastErrorReason::Deserialization,
279 ))
280 }
281 }
282 _ => Err(FrcValueCastError::InvalidCastTo(
283 frc_type,
284 T::TYPE,
285 CastErrorReason::Type,
286 )),
287 }
288 }
289
290 pub fn from_struct_array<T: FrcStructure>(values: &[T]) -> Self {
292 let mut buffer = Vec::with_capacity(T::SIZE * values.len());
293 for value in values {
294 value.pack(&mut buffer);
295 }
296 Self::StructArray(Box::new(FrcStructureBytes::from_parts(
297 &T::DESCRIPTION,
298 values.len(),
299 buffer.into_boxed_slice(),
300 )))
301 }
302
303 pub fn try_into_struct_array<T: FrcStructure>(self) -> Result<Vec<T>, FrcValueCastError> {
306 let frc_type = self.get_type();
307 match self {
308 Self::StructArray(bytes) => {
309 let buffer = bytes.data;
310 if buffer.len() % T::SIZE == 0 {
311 let mut cursor = Cursor::new(buffer.as_ref());
312 let mut values = Vec::with_capacity(buffer.len() / T::SIZE);
313 while cursor.position() < buffer.len() as u64 {
314 values.push(T::unpack(&mut cursor));
315 }
316 Ok(values)
317 } else {
318 Err(FrcValueCastError::InvalidCastTo(
319 frc_type,
320 T::TYPE,
321 CastErrorReason::Deserialization,
322 ))
323 }
324 }
325 _ => Err(FrcValueCastError::InvalidCastTo(
326 frc_type,
327 T::TYPE,
328 CastErrorReason::Type,
329 )),
330 }
331 }
332}
333
334#[derive(Debug, Clone, PartialEq, Hash)]
337pub struct FrcTimestampedValue {
338 pub timestamp: FrcTimestamp,
342 pub value: FrcValue,
344}
345impl Display for FrcTimestampedValue {
346 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347 write!(f, "{} at {}", self.value, self.timestamp)
348 }
349}
350impl FrcTimestampedValue {
351 #[must_use]
353 pub const fn new(timestamp: FrcTimestamp, value: FrcValue) -> Self {
354 Self { timestamp, value }
355 }
356 #[must_use]
358 pub const fn is_after_timestamp(&self, timestamp: FrcTimestamp) -> bool {
359 self.timestamp > timestamp
360 }
361 #[must_use]
363 pub const fn is_after_other(&self, other: &Self) -> bool {
364 self.timestamp > other.timestamp
365 }
366 #[must_use]
368 pub const fn is_before_timestamp(&self, timestamp: FrcTimestamp) -> bool {
369 self.timestamp < timestamp
370 }
371 #[must_use]
373 pub const fn is_before_other(&self, other: &Self) -> bool {
374 self.timestamp < other.timestamp
375 }
376}
377
378#[derive(Debug, Clone)]
381pub struct FrcEntry {
382 pub timestamp: FrcTimestamp,
386 pub value: FrcValue,
388 pub key: &'static str,
390}
391impl Display for FrcEntry {
392 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
393 write!(f, "{} at {} for {}", self.value, self.timestamp, self.key)
394 }
395}