1use super::{Map, Value};
4use yog_ids::shape_kind as kind;
5
6pub type ShapeFn = fn() -> Shape;
10
11#[derive(Debug, Clone)]
14pub enum Shape {
15 Any,
17 Bool,
18 Int {
19 min: i64,
20 max: i64,
21 },
22 Float {
24 bits: u32,
25 },
26 Str,
28 Atom,
30 Text,
32 Image,
34 Color,
36 Bytes,
38 Res,
40 Ref(&'static [&'static str]),
42 Tag(&'static [&'static str]),
44 RefOrTag(&'static [&'static str]),
46 RefOrImage(&'static [&'static str]),
48 List(ShapeFn),
49 Map(ShapeFn),
51 Optional(ShapeFn),
53 Struct(StructShape),
54 Enum(EnumShape),
55}
56
57#[derive(Debug, Clone)]
58pub struct StructShape {
59 pub name: &'static str,
60 pub doc: &'static str,
61 pub fields: Vec<Field>,
62}
63
64#[derive(Debug, Clone)]
65pub struct Field {
66 pub name: &'static str,
67 pub doc: &'static str,
68 pub shape: ShapeFn,
69 pub required: bool,
71 pub range: Option<(f64, f64)>,
73}
74
75#[derive(Debug, Clone)]
76pub struct EnumShape {
77 pub name: &'static str,
78 pub doc: &'static str,
79 pub tag: Option<&'static str>,
81 pub variants: Vec<Variant>,
82}
83
84#[derive(Debug, Clone)]
85pub struct Variant {
86 pub name: &'static str,
87 pub doc: &'static str,
88 pub fields: Vec<Field>,
90}
91
92mod key;
93
94fn of_kind(k: &str) -> Map {
96 let mut m = Map::new();
97 m.insert(key::KIND, Value::from(k));
98 m
99}
100
101fn put_doc(m: &mut Map, doc: &str) {
103 if !doc.is_empty() {
104 m.insert(key::DOC, Value::from(doc));
105 }
106}
107
108fn def_ref(name: &str) -> Map {
110 let mut m = of_kind(kind::DEF);
111 m.insert(key::NAME, Value::from(name));
112 m
113}
114
115fn describe_fields(fs: &[Field], defs: &mut Map) -> Value {
116 Value::List(
117 fs.iter()
118 .map(|f| {
119 let mut m = Map::new();
120 m.insert(key::NAME, Value::from(f.name));
121 put_doc(&mut m, f.doc);
122 m.insert(key::SHAPE, (f.shape)().describe_into(defs));
123 m.insert(key::REQUIRED, Value::Bool(f.required));
124 if let Some((lo, hi)) = f.range {
125 m.insert(
126 key::RANGE,
127 Value::List(vec![Value::Float(lo), Value::Float(hi)]),
128 );
129 }
130 Value::Map(m)
131 })
132 .collect(),
133 )
134}
135
136impl StructShape {
137 fn define(&self, defs: &mut Map) {
139 if defs.get(self.name).is_some() {
140 return;
141 }
142 defs.insert(self.name, Value::Null);
144 let mut d = of_kind(kind::STRUCT);
145 put_doc(&mut d, self.doc);
146 d.insert(key::FIELDS, describe_fields(&self.fields, defs));
147 defs.insert(self.name, Value::Map(d));
148 }
149}
150
151impl EnumShape {
152 fn define(&self, defs: &mut Map) {
154 if defs.get(self.name).is_some() {
155 return;
156 }
157 defs.insert(self.name, Value::Null);
158 let mut d = of_kind(kind::ENUM);
159 put_doc(&mut d, self.doc);
160 if let Some(tag) = self.tag {
161 d.insert(key::TAG, Value::from(tag));
162 }
163 let variants = self
164 .variants
165 .iter()
166 .map(|v| {
167 let mut m = Map::new();
168 m.insert(key::NAME, Value::from(v.name));
169 put_doc(&mut m, v.doc);
170 if self.tag.is_some() {
171 m.insert(key::FIELDS, describe_fields(&v.fields, defs));
172 }
173 Value::Map(m)
174 })
175 .collect();
176 d.insert(key::VARIANTS, Value::List(variants));
177 defs.insert(self.name, Value::Map(d));
178 }
179}
180
181impl Shape {
182 pub fn describe(&self) -> Value {
185 let mut defs = Map::new();
186 let root = self.describe_into(&mut defs);
187 let mut m = Map::new();
188 m.insert(key::ROOT, root);
189 m.insert(key::DEFS, Value::Map(defs));
190 Value::Map(m)
191 }
192
193 fn plain_kind(&self) -> Option<&'static str> {
195 Some(match self {
196 Shape::Any => kind::ANY,
197 Shape::Bool => kind::BOOL,
198 Shape::Str => kind::STRING,
199 Shape::Atom => kind::ATOM,
200 Shape::Text => kind::TEXT,
201 Shape::Image => kind::IMAGE,
202 Shape::Color => kind::COLOR,
203 Shape::Bytes => kind::BYTES,
204 Shape::Res => kind::RES,
205 _ => return None,
206 })
207 }
208
209 fn describe_into(&self, defs: &mut Map) -> Value {
210 if let Some(k) = self.plain_kind() {
211 return Value::Map(of_kind(k));
212 }
213 let m = match self {
214 Shape::Int { min, max } => {
215 let mut m = of_kind(kind::INT);
216 m.insert(key::MIN, Value::Int(*min));
217 m.insert(key::MAX, Value::Int(*max));
218 m
219 }
220 Shape::Float { bits } => {
221 let mut m = of_kind(kind::FLOAT);
222 m.insert(key::BITS, Value::Int(i64::from(*bits)));
223 m
224 }
225 Shape::Ref(k) | Shape::Tag(k) | Shape::RefOrTag(k) | Shape::RefOrImage(k) => {
226 let mut m = of_kind(match self {
227 Shape::Ref(_) => kind::REF,
228 Shape::Tag(_) => kind::TAG,
229 Shape::RefOrTag(_) => kind::REF_OR_TAG,
230 _ => kind::REF_OR_IMAGE,
231 });
232 m.insert(
233 key::OF,
234 Value::List(k.iter().map(|k| Value::from(*k)).collect()),
235 );
236 m
237 }
238 Shape::List(s) | Shape::Map(s) | Shape::Optional(s) => {
239 let mut m = of_kind(match self {
240 Shape::List(_) => kind::LIST,
241 Shape::Map(_) => kind::MAP,
242 _ => kind::OPTIONAL,
243 });
244 m.insert(key::OF, s().describe_into(defs));
245 m
246 }
247 Shape::Struct(s) => {
248 s.define(defs);
249 def_ref(s.name)
250 }
251 Shape::Enum(e) => {
252 e.define(defs);
253 def_ref(e.name)
254 }
255 _ => Map::new(),
256 };
257 Value::Map(m)
258 }
259}