1use std::collections::HashMap;
22use std::fmt;
23use std::ops::Index;
24use std::sync::{Arc, OnceLock};
25
26use ::serde::de::{MapAccess, Visitor};
27use serde::de::{Error, IntoDeserializer};
28use serde::{Deserialize, Deserializer, Serialize, Serializer};
29use serde_json::Value as JsonValue;
30
31use super::values::Literal;
32use crate::ensure_data_valid;
33use crate::error::Result;
34use crate::spec::datatypes::_decimal::{MAX_PRECISION, REQUIRED_LENGTH};
35use crate::spec::{FormatVersion, PrimitiveLiteral};
36
37pub const LIST_FIELD_NAME: &str = "element";
39pub const MAP_KEY_FIELD_NAME: &str = "key";
41pub const MAP_VALUE_FIELD_NAME: &str = "value";
43
44pub(crate) const MAX_DECIMAL_BYTES: u32 = 24;
45pub(crate) const MAX_DECIMAL_PRECISION: u32 = 38;
46
47mod _decimal {
48 use once_cell::sync::Lazy;
49
50 use crate::spec::{MAX_DECIMAL_BYTES, MAX_DECIMAL_PRECISION};
51
52 pub(super) static MAX_PRECISION: Lazy<[u32; MAX_DECIMAL_BYTES as usize]> = Lazy::new(|| {
54 let mut ret: [u32; 24] = [0; 24];
55 for (i, prec) in ret.iter_mut().enumerate() {
56 *prec = 2f64.powi((8 * (i + 1) - 1) as i32).log10().floor() as u32;
57 }
58
59 ret
60 });
61
62 pub(super) static REQUIRED_LENGTH: Lazy<[u32; MAX_DECIMAL_PRECISION as usize]> =
64 Lazy::new(|| {
65 let mut ret: [u32; MAX_DECIMAL_PRECISION as usize] =
66 [0; MAX_DECIMAL_PRECISION as usize];
67
68 for (i, required_len) in ret.iter_mut().enumerate() {
69 for j in 0..MAX_PRECISION.len() {
70 if MAX_PRECISION[j] >= ((i + 1) as u32) {
71 *required_len = (j + 1) as u32;
72 break;
73 }
74 }
75 }
76
77 ret
78 });
79}
80
81#[derive(Debug, PartialEq, Eq, Clone)]
82pub enum Type {
84 Primitive(PrimitiveType),
86 Struct(StructType),
88 List(ListType),
90 Map(MapType),
92 Variant(VariantType),
94}
95
96impl fmt::Display for Type {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 match self {
99 Type::Primitive(primitive) => write!(f, "{primitive}"),
100 Type::Struct(s) => write!(f, "{s}"),
101 Type::List(_) => write!(f, "list"),
102 Type::Map(_) => write!(f, "map"),
103 Type::Variant(_) => write!(f, "variant"),
104 }
105 }
106}
107
108impl Type {
109 #[inline(always)]
111 pub fn is_primitive(&self) -> bool {
112 matches!(self, Type::Primitive(_))
113 }
114
115 #[inline(always)]
117 pub fn is_struct(&self) -> bool {
118 matches!(self, Type::Struct(_))
119 }
120
121 #[inline(always)]
123 pub fn is_nested(&self) -> bool {
124 matches!(self, Type::Struct(_) | Type::List(_) | Type::Map(_))
125 }
126
127 #[inline(always)]
129 pub fn is_variant(&self) -> bool {
130 matches!(self, Type::Variant(_))
131 }
132
133 pub(crate) fn min_format_version(&self) -> FormatVersion {
144 match self {
145 Type::Primitive(PrimitiveType::TimestampNs | PrimitiveType::TimestamptzNs)
146 | Type::Variant(_) => FormatVersion::V3,
147 _ => FormatVersion::V1,
148 }
149 }
150
151 pub fn as_primitive_type(&self) -> Option<&PrimitiveType> {
153 if let Type::Primitive(primitive_type) = self {
154 Some(primitive_type)
155 } else {
156 None
157 }
158 }
159
160 pub fn to_struct_type(self) -> Option<StructType> {
162 if let Type::Struct(struct_type) = self {
163 Some(struct_type)
164 } else {
165 None
166 }
167 }
168
169 #[inline(always)]
171 pub fn decimal_max_precision(num_bytes: u32) -> Result<u32> {
172 ensure_data_valid!(
173 num_bytes > 0 && num_bytes <= MAX_DECIMAL_BYTES,
174 "Decimal length larger than {MAX_DECIMAL_BYTES} is not supported: {num_bytes}",
175 );
176 Ok(MAX_PRECISION[num_bytes as usize - 1])
177 }
178
179 #[inline(always)]
181 pub fn decimal_required_bytes(precision: u32) -> Result<u32> {
182 ensure_data_valid!(
183 precision > 0 && precision <= MAX_DECIMAL_PRECISION,
184 "Decimals with precision larger than {MAX_DECIMAL_PRECISION} are not supported: {precision}",
185 );
186 Ok(REQUIRED_LENGTH[precision as usize - 1])
187 }
188
189 #[inline(always)]
191 pub fn decimal(precision: u32, scale: u32) -> Result<Self> {
192 ensure_data_valid!(
193 precision > 0 && precision <= MAX_DECIMAL_PRECISION,
194 "Decimals with precision larger than {MAX_DECIMAL_PRECISION} are not supported: {precision}",
195 );
196 Ok(Type::Primitive(PrimitiveType::Decimal { precision, scale }))
197 }
198
199 #[inline(always)]
201 pub fn is_floating_type(&self) -> bool {
202 matches!(
203 self,
204 Type::Primitive(PrimitiveType::Float) | Type::Primitive(PrimitiveType::Double)
205 )
206 }
207}
208
209impl From<PrimitiveType> for Type {
210 fn from(value: PrimitiveType) -> Self {
211 Self::Primitive(value)
212 }
213}
214
215impl From<StructType> for Type {
216 fn from(value: StructType) -> Self {
217 Type::Struct(value)
218 }
219}
220
221impl From<ListType> for Type {
222 fn from(value: ListType) -> Self {
223 Type::List(value)
224 }
225}
226
227impl From<MapType> for Type {
228 fn from(value: MapType) -> Self {
229 Type::Map(value)
230 }
231}
232
233#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Hash)]
235#[serde(rename_all = "lowercase", remote = "Self")]
236pub enum PrimitiveType {
237 Boolean,
239 Int,
241 Long,
243 Float,
245 Double,
247 Decimal {
249 precision: u32,
251 scale: u32,
253 },
254 Date,
256 Time,
258 Timestamp,
260 Timestamptz,
262 #[serde(rename = "timestamp_ns")]
264 TimestampNs,
265 #[serde(rename = "timestamptz_ns")]
267 TimestamptzNs,
268 String,
270 Uuid,
272 Fixed(u64),
274 Binary,
276}
277
278impl PrimitiveType {
279 pub fn compatible(&self, literal: &PrimitiveLiteral) -> bool {
281 matches!(
282 (self, literal),
283 (PrimitiveType::Boolean, PrimitiveLiteral::Boolean(_))
284 | (PrimitiveType::Int, PrimitiveLiteral::Int(_))
285 | (PrimitiveType::Long, PrimitiveLiteral::Long(_))
286 | (PrimitiveType::Float, PrimitiveLiteral::Float(_))
287 | (PrimitiveType::Double, PrimitiveLiteral::Double(_))
288 | (PrimitiveType::Decimal { .. }, PrimitiveLiteral::Int128(_))
289 | (PrimitiveType::Date, PrimitiveLiteral::Int(_))
290 | (PrimitiveType::Time, PrimitiveLiteral::Long(_))
291 | (PrimitiveType::Timestamp, PrimitiveLiteral::Long(_))
292 | (PrimitiveType::Timestamptz, PrimitiveLiteral::Long(_))
293 | (PrimitiveType::TimestampNs, PrimitiveLiteral::Long(_))
294 | (PrimitiveType::TimestamptzNs, PrimitiveLiteral::Long(_))
295 | (PrimitiveType::String, PrimitiveLiteral::String(_))
296 | (PrimitiveType::Uuid, PrimitiveLiteral::UInt128(_))
297 | (PrimitiveType::Fixed(_), PrimitiveLiteral::Binary(_))
298 | (PrimitiveType::Binary, PrimitiveLiteral::Binary(_))
299 )
300 }
301}
302
303impl Serialize for Type {
304 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
305 where S: Serializer {
306 let type_serde = _serde::SerdeType::from(self);
307 type_serde.serialize(serializer)
308 }
309}
310
311impl<'de> Deserialize<'de> for Type {
312 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
313 where D: Deserializer<'de> {
314 let type_serde = _serde::SerdeType::deserialize(deserializer)?;
315 Ok(Type::from(type_serde))
316 }
317}
318
319impl<'de> Deserialize<'de> for PrimitiveType {
320 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
321 where D: Deserializer<'de> {
322 let s = String::deserialize(deserializer)?;
323 if s.starts_with("decimal") {
324 deserialize_decimal(s.into_deserializer())
325 } else if s.starts_with("fixed") {
326 deserialize_fixed(s.into_deserializer())
327 } else {
328 PrimitiveType::deserialize(s.into_deserializer())
329 }
330 }
331}
332
333impl Serialize for PrimitiveType {
334 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
335 where S: Serializer {
336 match self {
337 PrimitiveType::Decimal { precision, scale } => {
338 serialize_decimal(precision, scale, serializer)
339 }
340 PrimitiveType::Fixed(l) => serialize_fixed(l, serializer),
341 _ => PrimitiveType::serialize(self, serializer),
342 }
343 }
344}
345
346fn deserialize_decimal<'de, D>(deserializer: D) -> std::result::Result<PrimitiveType, D::Error>
347where D: Deserializer<'de> {
348 let s = String::deserialize(deserializer)?;
349 let (precision, scale) = s
350 .trim_start_matches(r"decimal(")
351 .trim_end_matches(')')
352 .split_once(',')
353 .ok_or_else(|| D::Error::custom("Decimal requires precision and scale: {s}"))?;
354
355 Ok(PrimitiveType::Decimal {
356 precision: precision.trim().parse().map_err(D::Error::custom)?,
357 scale: scale.trim().parse().map_err(D::Error::custom)?,
358 })
359}
360
361fn serialize_decimal<S>(
362 precision: &u32,
363 scale: &u32,
364 serializer: S,
365) -> std::result::Result<S::Ok, S::Error>
366where
367 S: Serializer,
368{
369 serializer.serialize_str(&format!("decimal({precision}, {scale})"))
370}
371
372fn deserialize_fixed<'de, D>(deserializer: D) -> std::result::Result<PrimitiveType, D::Error>
373where D: Deserializer<'de> {
374 let fixed = String::deserialize(deserializer)?
375 .trim_start_matches(r"fixed[")
376 .trim_end_matches(']')
377 .to_owned();
378
379 fixed
380 .parse()
381 .map(PrimitiveType::Fixed)
382 .map_err(D::Error::custom)
383}
384
385fn serialize_fixed<S>(value: &u64, serializer: S) -> std::result::Result<S::Ok, S::Error>
386where S: Serializer {
387 serializer.serialize_str(&format!("fixed[{value}]"))
388}
389
390impl fmt::Display for PrimitiveType {
391 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392 match self {
393 PrimitiveType::Boolean => write!(f, "boolean"),
394 PrimitiveType::Int => write!(f, "int"),
395 PrimitiveType::Long => write!(f, "long"),
396 PrimitiveType::Float => write!(f, "float"),
397 PrimitiveType::Double => write!(f, "double"),
398 PrimitiveType::Decimal { precision, scale } => {
399 write!(f, "decimal({precision}, {scale})")
400 }
401 PrimitiveType::Date => write!(f, "date"),
402 PrimitiveType::Time => write!(f, "time"),
403 PrimitiveType::Timestamp => write!(f, "timestamp"),
404 PrimitiveType::Timestamptz => write!(f, "timestamptz"),
405 PrimitiveType::TimestampNs => write!(f, "timestamp_ns"),
406 PrimitiveType::TimestamptzNs => write!(f, "timestamptz_ns"),
407 PrimitiveType::String => write!(f, "string"),
408 PrimitiveType::Uuid => write!(f, "uuid"),
409 PrimitiveType::Fixed(size) => write!(f, "fixed({size})"),
410 PrimitiveType::Binary => write!(f, "binary"),
411 }
412 }
413}
414
415#[derive(Debug, Serialize, Clone, Default)]
417#[serde(rename = "struct", tag = "type")]
418pub struct StructType {
419 fields: Vec<NestedFieldRef>,
421 #[serde(skip_serializing)]
423 id_lookup: OnceLock<HashMap<i32, usize>>,
424 #[serde(skip_serializing)]
425 name_lookup: OnceLock<HashMap<String, usize>>,
426}
427
428impl<'de> Deserialize<'de> for StructType {
429 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
430 where D: Deserializer<'de> {
431 #[derive(Deserialize)]
432 #[serde(field_identifier, rename_all = "lowercase")]
433 enum Field {
434 Type,
435 Fields,
436 }
437
438 struct StructTypeVisitor;
439
440 impl<'de> Visitor<'de> for StructTypeVisitor {
441 type Value = StructType;
442
443 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
444 formatter.write_str("struct")
445 }
446
447 fn visit_map<V>(self, mut map: V) -> std::result::Result<StructType, V::Error>
448 where V: MapAccess<'de> {
449 let mut fields = None;
450 while let Some(key) = map.next_key()? {
451 match key {
452 Field::Type => {
453 let type_val: String = map.next_value()?;
454 if type_val != "struct" {
455 return Err(Error::custom(format!(
456 "expected type 'struct', got '{type_val}'"
457 )));
458 }
459 }
460 Field::Fields => {
461 if fields.is_some() {
462 return Err(Error::duplicate_field("fields"));
463 }
464 fields = Some(map.next_value()?);
465 }
466 }
467 }
468 let fields: Vec<NestedFieldRef> =
469 fields.ok_or_else(|| Error::missing_field("fields"))?;
470
471 Ok(StructType::new(fields))
472 }
473 }
474
475 const FIELDS: &[&str] = &["type", "fields"];
476 deserializer.deserialize_struct("struct", FIELDS, StructTypeVisitor)
477 }
478}
479
480impl StructType {
481 pub fn new(fields: Vec<NestedFieldRef>) -> Self {
483 Self {
484 fields,
485 id_lookup: OnceLock::new(),
486 name_lookup: OnceLock::new(),
487 }
488 }
489
490 pub fn field_by_id(&self, id: i32) -> Option<&NestedFieldRef> {
492 self.field_id_to_index(id).map(|idx| &self.fields[idx])
493 }
494
495 fn field_id_to_index(&self, field_id: i32) -> Option<usize> {
496 self.id_lookup
497 .get_or_init(|| {
498 HashMap::from_iter(self.fields.iter().enumerate().map(|(i, x)| (x.id, i)))
499 })
500 .get(&field_id)
501 .copied()
502 }
503
504 pub fn field_by_name(&self, name: &str) -> Option<&NestedFieldRef> {
506 self.field_name_to_index(name).map(|idx| &self.fields[idx])
507 }
508
509 fn field_name_to_index(&self, name: &str) -> Option<usize> {
510 self.name_lookup
511 .get_or_init(|| {
512 HashMap::from_iter(
513 self.fields
514 .iter()
515 .enumerate()
516 .map(|(i, x)| (x.name.clone(), i)),
517 )
518 })
519 .get(name)
520 .copied()
521 }
522
523 pub fn fields(&self) -> &[NestedFieldRef] {
525 &self.fields
526 }
527}
528
529impl PartialEq for StructType {
530 fn eq(&self, other: &Self) -> bool {
531 self.fields == other.fields
532 }
533}
534
535impl Eq for StructType {}
536
537impl Index<usize> for StructType {
538 type Output = NestedField;
539
540 fn index(&self, index: usize) -> &Self::Output {
541 &self.fields[index]
542 }
543}
544
545impl fmt::Display for StructType {
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
547 write!(f, "struct<")?;
548 for field in &self.fields {
549 write!(f, "{}", field.field_type)?;
550 }
551 write!(f, ">")
552 }
553}
554
555#[derive(Debug, PartialEq, Serialize, Deserialize, Eq, Clone)]
556#[serde(try_from = "SerdeNestedField", into = "SerdeNestedField")]
557pub struct NestedField {
561 pub id: i32,
563 pub name: String,
565 pub required: bool,
567 pub field_type: Box<Type>,
569 pub doc: Option<String>,
571 pub initial_default: Option<Literal>,
573 pub write_default: Option<Literal>,
575}
576
577#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
578#[serde(rename_all = "kebab-case")]
579struct SerdeNestedField {
580 pub id: i32,
581 pub name: String,
582 pub required: bool,
583 #[serde(rename = "type")]
584 pub field_type: Box<Type>,
585 #[serde(skip_serializing_if = "Option::is_none")]
586 pub doc: Option<String>,
587 #[serde(skip_serializing_if = "Option::is_none")]
588 pub initial_default: Option<JsonValue>,
589 #[serde(skip_serializing_if = "Option::is_none")]
590 pub write_default: Option<JsonValue>,
591}
592
593impl TryFrom<SerdeNestedField> for NestedField {
594 type Error = crate::Error;
595
596 fn try_from(value: SerdeNestedField) -> Result<Self> {
597 let initial_default = value
598 .initial_default
599 .map(|x| Literal::try_from_json(x, &value.field_type))
600 .transpose()?
601 .flatten();
602 let write_default = value
603 .write_default
604 .map(|x| Literal::try_from_json(x, &value.field_type))
605 .transpose()?
606 .flatten();
607
608 Ok(NestedField {
609 id: value.id,
610 name: value.name,
611 required: value.required,
612 initial_default,
613 write_default,
614 field_type: value.field_type,
615 doc: value.doc,
616 })
617 }
618}
619
620impl From<NestedField> for SerdeNestedField {
621 fn from(value: NestedField) -> Self {
622 let initial_default = value.initial_default.map(|x| x.try_into_json(&value.field_type).expect("We should have checked this in NestedField::with_initial_default, it can't be converted to json value"));
623 let write_default = value.write_default.map(|x| x.try_into_json(&value.field_type).expect("We should have checked this in NestedField::with_write_default, it can't be converted to json value"));
624 SerdeNestedField {
625 id: value.id,
626 name: value.name,
627 required: value.required,
628 field_type: value.field_type,
629 doc: value.doc,
630 initial_default,
631 write_default,
632 }
633 }
634}
635
636pub type NestedFieldRef = Arc<NestedField>;
638
639impl NestedField {
640 pub fn new(id: i32, name: impl ToString, field_type: Type, required: bool) -> Self {
642 Self {
643 id,
644 name: name.to_string(),
645 required,
646 field_type: Box::new(field_type),
647 doc: None,
648 initial_default: None,
649 write_default: None,
650 }
651 }
652
653 pub fn required(id: i32, name: impl ToString, field_type: Type) -> Self {
655 Self::new(id, name, field_type, true)
656 }
657
658 pub fn optional(id: i32, name: impl ToString, field_type: Type) -> Self {
660 Self::new(id, name, field_type, false)
661 }
662
663 pub fn list_element(id: i32, field_type: Type, required: bool) -> Self {
665 Self::new(id, LIST_FIELD_NAME, field_type, required)
666 }
667
668 pub fn map_key_element(id: i32, field_type: Type) -> Self {
670 Self::required(id, MAP_KEY_FIELD_NAME, field_type)
671 }
672
673 pub fn map_value_element(id: i32, field_type: Type, required: bool) -> Self {
675 Self::new(id, MAP_VALUE_FIELD_NAME, field_type, required)
676 }
677
678 pub fn with_doc(mut self, doc: impl ToString) -> Self {
680 self.doc = Some(doc.to_string());
681 self
682 }
683
684 pub fn with_initial_default(mut self, value: Literal) -> Self {
686 self.initial_default = Some(value);
687 self
688 }
689
690 pub fn with_write_default(mut self, value: Literal) -> Self {
692 self.write_default = Some(value);
693 self
694 }
695
696 pub(crate) fn with_id(mut self, id: i32) -> Self {
698 self.id = id;
699 self
700 }
701}
702
703impl fmt::Display for NestedField {
704 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
705 write!(f, "{}: ", self.id)?;
706 write!(f, "{}: ", self.name)?;
707 if self.required {
708 write!(f, "required ")?;
709 } else {
710 write!(f, "optional ")?;
711 }
712 write!(f, "{} ", self.field_type)?;
713 if let Some(doc) = &self.doc {
714 write!(f, "{doc}")?;
715 }
716 Ok(())
717 }
718}
719
720#[derive(Debug, PartialEq, Eq, Clone)]
721pub struct ListType {
724 pub element_field: NestedFieldRef,
726}
727
728impl ListType {
729 pub fn new(element_field: NestedFieldRef) -> Self {
731 Self { element_field }
732 }
733}
734
735pub(super) mod _serde {
737 use std::borrow::Cow;
738
739 use serde_derive::{Deserialize, Serialize};
740
741 use crate::spec::datatypes::Type::Map;
742 use crate::spec::datatypes::{
743 ListType, MapType, NestedField, NestedFieldRef, PrimitiveType, StructType, Type,
744 VariantType,
745 };
746
747 #[derive(Serialize, Deserialize)]
749 #[serde(untagged)]
750 pub(super) enum SerdeType<'a> {
751 #[serde(rename_all = "kebab-case")]
752 List {
753 r#type: String,
754 element_id: i32,
755 element_required: bool,
756 element: Cow<'a, Type>,
757 },
758 Struct {
759 r#type: String,
760 fields: Cow<'a, [NestedFieldRef]>,
761 },
762 #[serde(rename_all = "kebab-case")]
763 Map {
764 r#type: String,
765 key_id: i32,
766 key: Cow<'a, Type>,
767 value_id: i32,
768 value_required: bool,
769 value: Cow<'a, Type>,
770 },
771 Primitive(PrimitiveType),
772 Variant(VariantType),
773 }
774
775 impl From<SerdeType<'_>> for Type {
776 fn from(value: SerdeType) -> Self {
777 match value {
778 SerdeType::List {
779 r#type: _,
780 element_id,
781 element_required,
782 element,
783 } => Self::List(ListType {
784 element_field: NestedField::list_element(
785 element_id,
786 element.into_owned(),
787 element_required,
788 )
789 .into(),
790 }),
791 SerdeType::Map {
792 r#type: _,
793 key_id,
794 key,
795 value_id,
796 value_required,
797 value,
798 } => Map(MapType {
799 key_field: NestedField::map_key_element(key_id, key.into_owned()).into(),
800 value_field: NestedField::map_value_element(
801 value_id,
802 value.into_owned(),
803 value_required,
804 )
805 .into(),
806 }),
807 SerdeType::Struct { r#type: _, fields } => {
808 Self::Struct(StructType::new(fields.into_owned()))
809 }
810 SerdeType::Primitive(p) => Self::Primitive(p),
811 SerdeType::Variant(v) => Self::Variant(v),
812 }
813 }
814 }
815
816 impl<'a> From<&'a Type> for SerdeType<'a> {
817 fn from(value: &'a Type) -> Self {
818 match value {
819 Type::List(list) => SerdeType::List {
820 r#type: "list".to_string(),
821 element_id: list.element_field.id,
822 element_required: list.element_field.required,
823 element: Cow::Borrowed(&list.element_field.field_type),
824 },
825 Map(map) => SerdeType::Map {
826 r#type: "map".to_string(),
827 key_id: map.key_field.id,
828 key: Cow::Borrowed(&map.key_field.field_type),
829 value_id: map.value_field.id,
830 value_required: map.value_field.required,
831 value: Cow::Borrowed(&map.value_field.field_type),
832 },
833 Type::Struct(s) => SerdeType::Struct {
834 r#type: "struct".to_string(),
835 fields: Cow::Borrowed(&s.fields),
836 },
837 Type::Primitive(p) => SerdeType::Primitive(p.clone()),
838 Type::Variant(v) => SerdeType::Variant(*v),
839 }
840 }
841 }
842}
843
844#[derive(Debug, PartialEq, Eq, Clone)]
845pub struct MapType {
850 pub key_field: NestedFieldRef,
852 pub value_field: NestedFieldRef,
854}
855
856impl MapType {
857 pub fn new(key_field: NestedFieldRef, value_field: NestedFieldRef) -> Self {
859 Self {
860 key_field,
861 value_field,
862 }
863 }
864
865 pub fn optional(key_id: i32, key_type: Type, value_id: i32, value_type: Type) -> Self {
867 Self {
868 key_field: NestedField::map_key_element(key_id, key_type).into(),
869 value_field: NestedField::map_value_element(value_id, value_type, false).into(),
870 }
871 }
872
873 pub fn required(key_id: i32, key_type: Type, value_id: i32, value_type: Type) -> Self {
875 Self {
876 key_field: NestedField::map_key_element(key_id, key_type).into(),
877 value_field: NestedField::map_value_element(value_id, value_type, true).into(),
878 }
879 }
880}
881
882#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
885pub struct VariantType;
886
887impl fmt::Display for VariantType {
888 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889 write!(f, "variant")
890 }
891}
892
893impl From<VariantType> for Type {
894 fn from(_: VariantType) -> Self {
895 Type::Variant(VariantType)
896 }
897}
898
899impl Serialize for VariantType {
900 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
901 where S: Serializer {
902 serializer.serialize_str("variant")
903 }
904}
905
906impl<'de> Deserialize<'de> for VariantType {
907 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
908 where D: Deserializer<'de> {
909 let s = String::deserialize(deserializer)?;
910 if s == "variant" {
911 Ok(VariantType)
912 } else {
913 Err(D::Error::custom(format!("expected 'variant', got '{s}'")))
914 }
915 }
916}
917
918#[cfg(test)]
919mod tests {
920 use pretty_assertions::assert_eq;
921 use uuid::Uuid;
922
923 use super::*;
924 use crate::spec::values::PrimitiveLiteral;
925
926 fn check_type_serde(json: &str, expected_type: Type) {
927 let desered_type: Type = serde_json::from_str(json).unwrap();
928 assert_eq!(desered_type, expected_type);
929
930 let sered_json = serde_json::to_string(&expected_type).unwrap();
931 let parsed_json_value = serde_json::from_str::<serde_json::Value>(&sered_json).unwrap();
932 let raw_json_value = serde_json::from_str::<serde_json::Value>(json).unwrap();
933
934 assert_eq!(parsed_json_value, raw_json_value);
935 }
936
937 #[test]
938 fn primitive_type_serde() {
939 let record = r#"
940 {
941 "type": "struct",
942 "fields": [
943 {"id": 1, "name": "bool_field", "required": true, "type": "boolean"},
944 {"id": 2, "name": "int_field", "required": true, "type": "int"},
945 {"id": 3, "name": "long_field", "required": true, "type": "long"},
946 {"id": 4, "name": "float_field", "required": true, "type": "float"},
947 {"id": 5, "name": "double_field", "required": true, "type": "double"},
948 {"id": 6, "name": "decimal_field", "required": true, "type": "decimal(9, 2)"},
949 {"id": 7, "name": "date_field", "required": true, "type": "date"},
950 {"id": 8, "name": "time_field", "required": true, "type": "time"},
951 {"id": 9, "name": "timestamp_field", "required": true, "type": "timestamp"},
952 {"id": 10, "name": "timestamptz_field", "required": true, "type": "timestamptz"},
953 {"id": 11, "name": "timestamp_ns_field", "required": true, "type": "timestamp_ns"},
954 {"id": 12, "name": "timestamptz_ns_field", "required": true, "type": "timestamptz_ns"},
955 {"id": 13, "name": "uuid_field", "required": true, "type": "uuid"},
956 {"id": 14, "name": "fixed_field", "required": true, "type": "fixed[10]"},
957 {"id": 15, "name": "binary_field", "required": true, "type": "binary"},
958 {"id": 16, "name": "string_field", "required": true, "type": "string"}
959 ]
960 }
961 "#;
962
963 check_type_serde(
964 record,
965 Type::Struct(StructType {
966 fields: vec![
967 NestedField::required(1, "bool_field", Type::Primitive(PrimitiveType::Boolean))
968 .into(),
969 NestedField::required(2, "int_field", Type::Primitive(PrimitiveType::Int))
970 .into(),
971 NestedField::required(3, "long_field", Type::Primitive(PrimitiveType::Long))
972 .into(),
973 NestedField::required(4, "float_field", Type::Primitive(PrimitiveType::Float))
974 .into(),
975 NestedField::required(
976 5,
977 "double_field",
978 Type::Primitive(PrimitiveType::Double),
979 )
980 .into(),
981 NestedField::required(
982 6,
983 "decimal_field",
984 Type::Primitive(PrimitiveType::Decimal {
985 precision: 9,
986 scale: 2,
987 }),
988 )
989 .into(),
990 NestedField::required(7, "date_field", Type::Primitive(PrimitiveType::Date))
991 .into(),
992 NestedField::required(8, "time_field", Type::Primitive(PrimitiveType::Time))
993 .into(),
994 NestedField::required(
995 9,
996 "timestamp_field",
997 Type::Primitive(PrimitiveType::Timestamp),
998 )
999 .into(),
1000 NestedField::required(
1001 10,
1002 "timestamptz_field",
1003 Type::Primitive(PrimitiveType::Timestamptz),
1004 )
1005 .into(),
1006 NestedField::required(
1007 11,
1008 "timestamp_ns_field",
1009 Type::Primitive(PrimitiveType::TimestampNs),
1010 )
1011 .into(),
1012 NestedField::required(
1013 12,
1014 "timestamptz_ns_field",
1015 Type::Primitive(PrimitiveType::TimestamptzNs),
1016 )
1017 .into(),
1018 NestedField::required(13, "uuid_field", Type::Primitive(PrimitiveType::Uuid))
1019 .into(),
1020 NestedField::required(
1021 14,
1022 "fixed_field",
1023 Type::Primitive(PrimitiveType::Fixed(10)),
1024 )
1025 .into(),
1026 NestedField::required(
1027 15,
1028 "binary_field",
1029 Type::Primitive(PrimitiveType::Binary),
1030 )
1031 .into(),
1032 NestedField::required(
1033 16,
1034 "string_field",
1035 Type::Primitive(PrimitiveType::String),
1036 )
1037 .into(),
1038 ],
1039 id_lookup: OnceLock::default(),
1040 name_lookup: OnceLock::default(),
1041 }),
1042 )
1043 }
1044
1045 #[test]
1046 fn struct_type() {
1047 let record = r#"
1048 {
1049 "type": "struct",
1050 "fields": [
1051 {
1052 "id": 1,
1053 "name": "id",
1054 "required": true,
1055 "type": "uuid",
1056 "initial-default": "0db3e2a8-9d1d-42b9-aa7b-74ebe558dceb",
1057 "write-default": "ec5911be-b0a7-458c-8438-c9a3e53cffae"
1058 }, {
1059 "id": 2,
1060 "name": "data",
1061 "required": false,
1062 "type": "int"
1063 }
1064 ]
1065 }
1066 "#;
1067
1068 check_type_serde(
1069 record,
1070 Type::Struct(StructType {
1071 fields: vec![
1072 NestedField::required(1, "id", Type::Primitive(PrimitiveType::Uuid))
1073 .with_initial_default(Literal::Primitive(PrimitiveLiteral::UInt128(
1074 Uuid::parse_str("0db3e2a8-9d1d-42b9-aa7b-74ebe558dceb")
1075 .unwrap()
1076 .as_u128(),
1077 )))
1078 .with_write_default(Literal::Primitive(PrimitiveLiteral::UInt128(
1079 Uuid::parse_str("ec5911be-b0a7-458c-8438-c9a3e53cffae")
1080 .unwrap()
1081 .as_u128(),
1082 )))
1083 .into(),
1084 NestedField::optional(2, "data", Type::Primitive(PrimitiveType::Int)).into(),
1085 ],
1086 id_lookup: HashMap::from([(1, 0), (2, 1)]).into(),
1087 name_lookup: HashMap::from([("id".to_string(), 0), ("data".to_string(), 1)]).into(),
1088 }),
1089 )
1090 }
1091
1092 #[test]
1093 fn test_deeply_nested_struct() {
1094 let record = r#"
1095{
1096 "type": "struct",
1097 "fields": [
1098 {
1099 "id": 1,
1100 "name": "id",
1101 "required": true,
1102 "type": "uuid",
1103 "initial-default": "0db3e2a8-9d1d-42b9-aa7b-74ebe558dceb",
1104 "write-default": "ec5911be-b0a7-458c-8438-c9a3e53cffae"
1105 },
1106 {
1107 "id": 2,
1108 "name": "data",
1109 "required": false,
1110 "type": "int"
1111 },
1112 {
1113 "id": 3,
1114 "name": "address",
1115 "required": true,
1116 "type": {
1117 "type": "struct",
1118 "fields": [
1119 {
1120 "id": 4,
1121 "name": "street",
1122 "required": true,
1123 "type": "string"
1124 },
1125 {
1126 "id": 5,
1127 "name": "province",
1128 "required": false,
1129 "type": "string"
1130 },
1131 {
1132 "id": 6,
1133 "name": "zip",
1134 "required": true,
1135 "type": "int"
1136 }
1137 ]
1138 }
1139 }
1140 ]
1141}
1142"#;
1143
1144 let struct_type = Type::Struct(StructType::new(vec![
1145 NestedField::required(1, "id", Type::Primitive(PrimitiveType::Uuid))
1146 .with_initial_default(Literal::Primitive(PrimitiveLiteral::UInt128(
1147 Uuid::parse_str("0db3e2a8-9d1d-42b9-aa7b-74ebe558dceb")
1148 .unwrap()
1149 .as_u128(),
1150 )))
1151 .with_write_default(Literal::Primitive(PrimitiveLiteral::UInt128(
1152 Uuid::parse_str("ec5911be-b0a7-458c-8438-c9a3e53cffae")
1153 .unwrap()
1154 .as_u128(),
1155 )))
1156 .into(),
1157 NestedField::optional(2, "data", Type::Primitive(PrimitiveType::Int)).into(),
1158 NestedField::required(
1159 3,
1160 "address",
1161 Type::Struct(StructType::new(vec![
1162 NestedField::required(4, "street", Type::Primitive(PrimitiveType::String))
1163 .into(),
1164 NestedField::optional(5, "province", Type::Primitive(PrimitiveType::String))
1165 .into(),
1166 NestedField::required(6, "zip", Type::Primitive(PrimitiveType::Int)).into(),
1167 ])),
1168 )
1169 .into(),
1170 ]));
1171
1172 check_type_serde(record, struct_type)
1173 }
1174
1175 #[test]
1176 fn list() {
1177 let record = r#"
1178 {
1179 "type": "list",
1180 "element-id": 3,
1181 "element-required": true,
1182 "element": "string"
1183 }
1184 "#;
1185
1186 check_type_serde(
1187 record,
1188 Type::List(ListType {
1189 element_field: NestedField::list_element(
1190 3,
1191 Type::Primitive(PrimitiveType::String),
1192 true,
1193 )
1194 .into(),
1195 }),
1196 );
1197 }
1198
1199 #[test]
1200 fn map() {
1201 let record = r#"
1202 {
1203 "type": "map",
1204 "key-id": 4,
1205 "key": "string",
1206 "value-id": 5,
1207 "value-required": false,
1208 "value": "double"
1209 }
1210 "#;
1211
1212 check_type_serde(
1213 record,
1214 Type::Map(MapType {
1215 key_field: NestedField::map_key_element(4, Type::Primitive(PrimitiveType::String))
1216 .into(),
1217 value_field: NestedField::map_value_element(
1218 5,
1219 Type::Primitive(PrimitiveType::Double),
1220 false,
1221 )
1222 .into(),
1223 }),
1224 );
1225
1226 check_type_serde(
1227 record,
1228 Type::Map(MapType::optional(
1229 4,
1230 Type::Primitive(PrimitiveType::String),
1231 5,
1232 Type::Primitive(PrimitiveType::Double),
1233 )),
1234 );
1235 }
1236
1237 #[test]
1238 fn map_int() {
1239 let record = r#"
1240 {
1241 "type": "map",
1242 "key-id": 4,
1243 "key": "int",
1244 "value-id": 5,
1245 "value-required": false,
1246 "value": "string"
1247 }
1248 "#;
1249
1250 check_type_serde(
1251 record,
1252 Type::Map(MapType {
1253 key_field: NestedField::map_key_element(4, Type::Primitive(PrimitiveType::Int))
1254 .into(),
1255 value_field: NestedField::map_value_element(
1256 5,
1257 Type::Primitive(PrimitiveType::String),
1258 false,
1259 )
1260 .into(),
1261 }),
1262 );
1263
1264 check_type_serde(
1265 record,
1266 Type::Map(MapType::optional(
1267 4,
1268 Type::Primitive(PrimitiveType::Int),
1269 5,
1270 Type::Primitive(PrimitiveType::String),
1271 )),
1272 );
1273 }
1274
1275 #[test]
1276 fn map_required_int() {
1277 let record = r#"
1278 {
1279 "type": "map",
1280 "key-id": 4,
1281 "key": "int",
1282 "value-id": 5,
1283 "value-required": true,
1284 "value": "string"
1285 }
1286 "#;
1287
1288 check_type_serde(
1289 record,
1290 Type::Map(MapType::required(
1291 4,
1292 Type::Primitive(PrimitiveType::Int),
1293 5,
1294 Type::Primitive(PrimitiveType::String),
1295 )),
1296 );
1297 }
1298
1299 #[test]
1300 fn test_decimal_precision() {
1301 let expected_max_precision = [
1302 2, 4, 6, 9, 11, 14, 16, 18, 21, 23, 26, 28, 31, 33, 35, 38, 40, 43, 45, 47, 50, 52, 55,
1303 57,
1304 ];
1305 for (i, max_precision) in expected_max_precision.iter().enumerate() {
1306 assert_eq!(
1307 *max_precision,
1308 Type::decimal_max_precision(i as u32 + 1).unwrap(),
1309 "Failed calculate max precision for {i}"
1310 );
1311 }
1312
1313 assert_eq!(5, Type::decimal_required_bytes(10).unwrap());
1314 assert_eq!(16, Type::decimal_required_bytes(38).unwrap());
1315 }
1316
1317 #[test]
1318 fn test_primitive_type_compatible() {
1319 let pairs = vec![
1320 (PrimitiveType::Boolean, PrimitiveLiteral::Boolean(true)),
1321 (PrimitiveType::Int, PrimitiveLiteral::Int(1)),
1322 (PrimitiveType::Long, PrimitiveLiteral::Long(1)),
1323 (PrimitiveType::Float, PrimitiveLiteral::Float(1.0.into())),
1324 (PrimitiveType::Double, PrimitiveLiteral::Double(1.0.into())),
1325 (
1326 PrimitiveType::Decimal {
1327 precision: 9,
1328 scale: 2,
1329 },
1330 PrimitiveLiteral::Int128(1),
1331 ),
1332 (PrimitiveType::Date, PrimitiveLiteral::Int(1)),
1333 (PrimitiveType::Time, PrimitiveLiteral::Long(1)),
1334 (PrimitiveType::Timestamptz, PrimitiveLiteral::Long(1)),
1335 (PrimitiveType::Timestamp, PrimitiveLiteral::Long(1)),
1336 (PrimitiveType::TimestamptzNs, PrimitiveLiteral::Long(1)),
1337 (PrimitiveType::TimestampNs, PrimitiveLiteral::Long(1)),
1338 (
1339 PrimitiveType::Uuid,
1340 PrimitiveLiteral::UInt128(Uuid::new_v4().as_u128()),
1341 ),
1342 (PrimitiveType::Fixed(8), PrimitiveLiteral::Binary(vec![1])),
1343 (PrimitiveType::Binary, PrimitiveLiteral::Binary(vec![1])),
1344 ];
1345 for (ty, literal) in pairs {
1346 assert!(ty.compatible(&literal));
1347 }
1348 }
1349
1350 #[test]
1351 fn variant_type_serde() {
1352 let json = r#"{"id": 1, "name": "v", "required": true, "type": "variant"}"#;
1353 let field: NestedField = serde_json::from_str(json).unwrap();
1354 assert_eq!(*field.field_type, Type::Variant(VariantType));
1355
1356 let serialized = serde_json::to_string(&field).unwrap();
1357 let roundtrip: NestedField = serde_json::from_str(&serialized).unwrap();
1358 assert_eq!(field, roundtrip);
1359 }
1360
1361 #[test]
1362 fn nested_field_rejects_invalid_map_defaults() {
1363 for default_name in ["initial-default", "write-default"] {
1364 let json = format!(
1365 r#"{{
1366 "id": 1,
1367 "name": "properties",
1368 "required": false,
1369 "type": {{
1370 "type": "map",
1371 "key-id": 2,
1372 "key": "string",
1373 "value-id": 3,
1374 "value-required": false,
1375 "value": "int"
1376 }},
1377 "{default_name}": {{"keys": ["a", "b"], "values": [1]}}
1378 }}"#
1379 );
1380
1381 let error = serde_json::from_str::<NestedField>(&json).unwrap_err();
1382 assert!(error.to_string().contains("must have the same length"));
1383 }
1384 }
1385
1386 #[test]
1387 fn struct_type_with_type_field() {
1388 let json = r#"
1391 {
1392 "type": "struct",
1393 "fields": [
1394 {"id": 1, "name": "field1", "required": true, "type": "string"}
1395 ]
1396 }
1397 "#;
1398
1399 let struct_type: StructType = serde_json::from_str(json)
1400 .expect("Should successfully deserialize StructType with type field");
1401
1402 assert_eq!(struct_type.fields().len(), 1);
1403 assert_eq!(struct_type.fields()[0].name, "field1");
1404 }
1405
1406 #[test]
1407 fn struct_type_rejects_wrong_type() {
1408 let json = r#"
1410 {
1411 "type": "list",
1412 "fields": [
1413 {"id": 1, "name": "field1", "required": true, "type": "string"}
1414 ]
1415 }
1416 "#;
1417
1418 let result = serde_json::from_str::<StructType>(json);
1419 assert!(
1420 result.is_err(),
1421 "Should reject StructType with wrong type field"
1422 );
1423 assert!(
1424 result
1425 .unwrap_err()
1426 .to_string()
1427 .contains("expected type 'struct'")
1428 );
1429 }
1430}