1use crate::scalar::ScalarTyp;
2use crate::typ::{Fields, Typ};
3
4#[derive(PartialEq, Eq, Clone, Debug)]
7pub enum SchemaTyp {
8 Scalar(ScalarTyp),
9 Array(u32, Box<SchemaTyp>),
10 Vec(Box<SchemaTyp>),
11 Optional(Box<SchemaTyp>),
12 SimpleEnum {
13 name: String,
14 variants: Vec<(u8, String)>,
15 },
16 Struct {
17 name: String,
18 fields: SchemaFields,
19 },
20 Enum {
21 name: String,
22 variants: Vec<(u8, String, SchemaTyp)>,
23 },
24 Custom(String, Vec<SchemaTyp>),
25}
26
27#[derive(PartialEq, Eq, Clone, Debug)]
28pub enum SchemaFields {
29 Named(Vec<(String, SchemaTyp)>),
30 Unnamed(Vec<SchemaTyp>),
31}
32
33impl From<&Typ> for SchemaTyp {
34 fn from(t: &Typ) -> Self {
35 match t {
36 Typ::Scalar(s) => SchemaTyp::Scalar(*s),
37 Typ::Array(n, inner) => SchemaTyp::Array(*n, Box::new(SchemaTyp::from(*inner))),
38 Typ::Vec(inner) => SchemaTyp::Vec(Box::new(SchemaTyp::from(*inner))),
39 Typ::Optional(inner) => SchemaTyp::Optional(Box::new(SchemaTyp::from(*inner))),
40 Typ::SimpleEnum(e) => SchemaTyp::SimpleEnum {
41 name: e.name.to_string(),
42 variants: e
43 .variants
44 .iter()
45 .map(|(i, n)| (*i, n.to_string()))
46 .collect(),
47 },
48 Typ::Struct(s) => SchemaTyp::Struct {
49 name: s.name.to_string(),
50 fields: match s.fields {
51 Fields::Named(fs) => SchemaFields::Named(
52 fs.iter()
53 .map(|(n, ty)| (n.to_string(), SchemaTyp::from(ty)))
54 .collect(),
55 ),
56 Fields::Unnamed(fs) => {
57 SchemaFields::Unnamed(fs.iter().map(SchemaTyp::from).collect())
58 }
59 },
60 },
61 Typ::Enum(e) => SchemaTyp::Enum {
62 name: e.name.to_string(),
63 variants: e
64 .variants
65 .iter()
66 .map(|(i, (n, ty))| (*i, n.to_string(), SchemaTyp::from(ty)))
67 .collect(),
68 },
69 Typ::Custom(name, items) => SchemaTyp::Custom(
70 name.to_string(),
71 items.iter().map(SchemaTyp::from).collect(),
72 ),
73 }
74 }
75}
76
77#[cfg(test)]
82#[allow(dead_code)]
83fn _schema_guard(s: &SchemaTyp) {
84 match s {
85 SchemaTyp::Scalar(_) => {}
86 SchemaTyp::Array(_, _) => {}
87 SchemaTyp::Vec(_) => {}
88 SchemaTyp::Optional(_) => {}
89 SchemaTyp::SimpleEnum { .. } => {}
90 SchemaTyp::Struct { .. } => {}
91 SchemaTyp::Enum { .. } => {}
92 SchemaTyp::Custom(_, _) => {}
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use crate::scalar::ScalarTyp;
100 use crate::typ::{Fields, StructType, Typ};
101
102 #[test]
103 fn from_typ_struct_roundtrips_shape() {
104 static T: Typ = Typ::Struct(StructType {
105 name: "S",
106 fields: Fields::Named(&[
107 ("a", Typ::Scalar(ScalarTyp::U64)),
108 ("b", Typ::Vec(&Typ::Scalar(ScalarTyp::Str))),
109 ]),
110 });
111 let s = SchemaTyp::from(&T);
112 let expected = SchemaTyp::Struct {
113 name: "S".to_string(),
114 fields: SchemaFields::Named(vec![
115 ("a".to_string(), SchemaTyp::Scalar(ScalarTyp::U64)),
116 (
117 "b".to_string(),
118 SchemaTyp::Vec(Box::new(SchemaTyp::Scalar(ScalarTyp::Str))),
119 ),
120 ]),
121 };
122 assert_eq!(s, expected);
123 }
124
125 #[test]
126 fn from_typ_covers_scalars_and_composites() {
127 assert_eq!(
128 SchemaTyp::from(&Typ::Scalar(ScalarTyp::Fuid)),
129 SchemaTyp::Scalar(ScalarTyp::Fuid)
130 );
131 assert_eq!(
132 SchemaTyp::from(&Typ::Optional(&Typ::Scalar(ScalarTyp::Id64))),
133 SchemaTyp::Optional(Box::new(SchemaTyp::Scalar(ScalarTyp::Id64)))
134 );
135 assert_eq!(
136 SchemaTyp::from(&Typ::Custom("c", &[Typ::Scalar(ScalarTyp::U8)])),
137 SchemaTyp::Custom("c".to_string(), vec![SchemaTyp::Scalar(ScalarTyp::U8)])
138 );
139 }
140}