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