specta 2.0.0-rc.21

Easily export your Rust types to other languages
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
//! Interop for Specta v1. This will not be in the final v2 release but is good for the meantime.

use std::borrow::Cow;

use specta1::NamedDataType;

use crate::{
    datatype::{DataType, DeprecatedType, LiteralType, PrimitiveType},
    TypeCollection,
};

/// Allow for conversion between Specta v2 and v1 data types.
pub fn specta_v2_to_v1(datatype: DataType) -> specta1::DataType {
    match datatype {
        DataType::Any => specta1::DataType::Any,
        DataType::Unknown => panic!("Specta v1 does not support unknown types"),
        DataType::Primitive(p) => specta1::DataType::Primitive(match p {
            PrimitiveType::i8 => specta1::PrimitiveType::i8,
            PrimitiveType::i16 => specta1::PrimitiveType::i16,
            PrimitiveType::i32 => specta1::PrimitiveType::i32,
            PrimitiveType::i64 => specta1::PrimitiveType::i64,
            PrimitiveType::i128 => specta1::PrimitiveType::i128,
            PrimitiveType::isize => specta1::PrimitiveType::isize,
            PrimitiveType::u8 => specta1::PrimitiveType::u8,
            PrimitiveType::u16 => specta1::PrimitiveType::u16,
            PrimitiveType::u32 => specta1::PrimitiveType::u32,
            PrimitiveType::u64 => specta1::PrimitiveType::u64,
            PrimitiveType::u128 => specta1::PrimitiveType::u128,
            PrimitiveType::usize => specta1::PrimitiveType::usize,
            PrimitiveType::f32 => specta1::PrimitiveType::f32,
            PrimitiveType::f64 => specta1::PrimitiveType::f64,
            PrimitiveType::bool => specta1::PrimitiveType::bool,
            PrimitiveType::char => specta1::PrimitiveType::char,
            PrimitiveType::String => specta1::PrimitiveType::String,
        }),
        DataType::Literal(l) => specta1::DataType::Literal(match l {
            LiteralType::i8(v) => specta1::LiteralType::i8(v),
            LiteralType::i16(v) => specta1::LiteralType::i16(v),
            LiteralType::i32(v) => specta1::LiteralType::i32(v),
            LiteralType::u8(v) => specta1::LiteralType::u8(v),
            LiteralType::u16(v) => specta1::LiteralType::u16(v),
            LiteralType::u32(v) => specta1::LiteralType::u32(v),
            LiteralType::f32(v) => specta1::LiteralType::f32(v),
            LiteralType::f64(v) => specta1::LiteralType::f64(v),
            LiteralType::bool(v) => specta1::LiteralType::bool(v),
            LiteralType::String(v) => specta1::LiteralType::String(v),
            LiteralType::char(_) => panic!("Specta v1 does not support char literals"),
            LiteralType::None => specta1::LiteralType::None,
        }),
        DataType::List(l) => specta1::DataType::List(Box::new(specta_v2_to_v1(l.ty().clone()))),
        DataType::Map(m) => specta1::DataType::Record(Box::new((
            specta_v2_to_v1(m.key_ty().clone()),
            specta_v2_to_v1(m.value_ty().clone()),
        ))),
        DataType::Nullable(n) => specta1::DataType::Nullable(Box::new(specta_v2_to_v1(*n))),
        DataType::Struct(s) => specta1::DataType::Object(specta1::ObjectType {
            tag: match s.tag() {
                Some(v) => Some(match v {
                    Cow::Borrowed(v) => v,
                    Cow::Owned(v) => String::leak(v.clone()),
                }),
                None => None,
            },
            generics: s
                .generics
                .into_iter()
                .map(|g| match g.0 {
                    Cow::Borrowed(v) => v,
                    Cow::Owned(v) => String::leak(v),
                })
                .collect(),
            fields: match s.fields {
                crate::datatype::StructFields::Unit => vec![],
                crate::datatype::StructFields::Unnamed(f) => f
                    .fields
                    .into_iter()
                    .map(|f| specta1::ObjectField {
                        key: "", // TODO: Imagine an unnamed struct field having a name
                        optional: f.optional,
                        flatten: f.flatten,
                        ty: specta_v2_to_v1(f.ty.unwrap_or(DataType::Unknown)),
                    })
                    .collect(),
                crate::datatype::StructFields::Named(f) => f
                    .fields
                    .into_iter()
                    .map(|(name, f)| specta1::ObjectField {
                        key: match name {
                            Cow::Borrowed(v) => v,
                            Cow::Owned(v) => String::leak(v),
                        },
                        optional: f.optional,
                        flatten: f.flatten,
                        ty: specta_v2_to_v1(f.ty.unwrap_or(DataType::Unknown)),
                    })
                    .collect(),
            },
        }),
        DataType::Enum(e) => {
            let generics = e
                .generics
                .into_iter()
                .map(|v| match v.0 {
                    Cow::Borrowed(v) => v,
                    Cow::Owned(v) => String::leak(v),
                })
                .collect::<Vec<_>>();

            specta1::DataType::Enum(match e.repr {
                crate::datatype::EnumRepr::Untagged => specta1::EnumType::Untagged {
                    generics: generics.clone(),
                    variants: e
                        .variants
                        .into_iter()
                        .map(|(name, v)| match v.inner() {
                            crate::datatype::EnumVariants::Unit => specta1::EnumVariant::Unit,
                            crate::datatype::EnumVariants::Named(f) => {
                                specta1::EnumVariant::Named(specta1::ObjectType {
                                    generics: generics.clone(),
                                    fields: f
                                        .fields
                                        .iter()
                                        .map(|(name, f)| specta1::ObjectField {
                                            key: match name {
                                                Cow::Borrowed(v) => v,
                                                Cow::Owned(v) => String::leak(v.clone()),
                                            },
                                            optional: f.optional,
                                            flatten: f.flatten,
                                            ty: specta_v2_to_v1(
                                                f.ty.clone().unwrap_or(DataType::Unknown),
                                            ),
                                        })
                                        .collect(),
                                    tag: f.tag.clone().map(|v| match v {
                                        Cow::Borrowed(v) => v,
                                        Cow::Owned(v) => String::leak(v),
                                    }),
                                })
                            }
                            crate::datatype::EnumVariants::Unnamed(f) => {
                                specta1::EnumVariant::Unnamed(specta1::TupleType {
                                    generics: generics.clone(),
                                    fields: f
                                        .fields
                                        .clone()
                                        .into_iter()
                                        .map(|f| specta_v2_to_v1(f.ty.unwrap_or(DataType::Unknown)))
                                        .collect(),
                                })
                            }
                        })
                        .collect::<Vec<_>>(),
                },
                crate::datatype::EnumRepr::External => specta1::EnumType::Tagged {
                    variants: e
                        .variants
                        .into_iter()
                        .map(|(name, v)| {
                            (
                                match name {
                                    Cow::Borrowed(v) => v,
                                    Cow::Owned(v) => String::leak(v),
                                },
                                match v.inner {
                                    crate::datatype::EnumVariants::Unit => {
                                        specta1::EnumVariant::Unit
                                    }
                                    crate::datatype::EnumVariants::Named(f) => {
                                        specta1::EnumVariant::Named(specta1::ObjectType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|(name, f)| specta1::ObjectField {
                                                    key: match name {
                                                        Cow::Borrowed(v) => v,
                                                        Cow::Owned(v) => String::leak(v),
                                                    },
                                                    optional: f.optional,
                                                    flatten: f.flatten,
                                                    ty: specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    ),
                                                })
                                                .collect(),
                                            tag: f.tag.map(|v| match v {
                                                Cow::Borrowed(v) => v,
                                                Cow::Owned(v) => String::leak(v),
                                            }),
                                        })
                                    }
                                    crate::datatype::EnumVariants::Unnamed(f) => {
                                        specta1::EnumVariant::Unnamed(specta1::TupleType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|f| {
                                                    specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    )
                                                })
                                                .collect(),
                                        })
                                    }
                                },
                            )
                        })
                        .collect(),
                    generics,
                    repr: specta1::EnumRepr::External,
                },
                crate::datatype::EnumRepr::Internal { tag } => specta1::EnumType::Tagged {
                    generics: generics.clone(),
                    variants: e
                        .variants
                        .into_iter()
                        .map(|(name, v)| {
                            (
                                match name {
                                    Cow::Borrowed(v) => v,
                                    Cow::Owned(v) => String::leak(v),
                                },
                                match v.inner {
                                    crate::datatype::EnumVariants::Unit => {
                                        specta1::EnumVariant::Unit
                                    }
                                    crate::datatype::EnumVariants::Named(f) => {
                                        specta1::EnumVariant::Named(specta1::ObjectType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|(name, f)| specta1::ObjectField {
                                                    key: match name {
                                                        Cow::Borrowed(v) => v,
                                                        Cow::Owned(v) => String::leak(v),
                                                    },
                                                    optional: f.optional,
                                                    flatten: f.flatten,
                                                    ty: specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    ),
                                                })
                                                .collect(),
                                            tag: f.tag.map(|v| match v {
                                                Cow::Borrowed(v) => v,
                                                Cow::Owned(v) => String::leak(v),
                                            }),
                                        })
                                    }
                                    crate::datatype::EnumVariants::Unnamed(f) => {
                                        specta1::EnumVariant::Unnamed(specta1::TupleType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|f| {
                                                    specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    )
                                                })
                                                .collect(),
                                        })
                                    }
                                },
                            )
                        })
                        .collect(),
                    repr: specta1::EnumRepr::Internal {
                        tag: match tag {
                            Cow::Borrowed(v) => v,
                            Cow::Owned(v) => String::leak(v),
                        },
                    },
                },
                crate::datatype::EnumRepr::Adjacent { tag, content } => specta1::EnumType::Tagged {
                    generics: generics.clone(),
                    repr: specta1::EnumRepr::Adjacent {
                        tag: match tag {
                            Cow::Borrowed(v) => v,
                            Cow::Owned(v) => String::leak(v),
                        },
                        content: match content {
                            Cow::Borrowed(v) => v,
                            Cow::Owned(v) => String::leak(v),
                        },
                    },
                    variants: e
                        .variants
                        .clone()
                        .into_iter()
                        .map(|(name, v)| {
                            (
                                match name {
                                    Cow::Borrowed(v) => v,
                                    Cow::Owned(v) => String::leak(v),
                                },
                                match v.inner {
                                    crate::datatype::EnumVariants::Unit => {
                                        specta1::EnumVariant::Unit
                                    }
                                    crate::datatype::EnumVariants::Named(f) => {
                                        specta1::EnumVariant::Named(specta1::ObjectType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|(name, f)| specta1::ObjectField {
                                                    key: match name {
                                                        Cow::Borrowed(v) => v,
                                                        Cow::Owned(v) => String::leak(v),
                                                    },
                                                    optional: f.optional,
                                                    flatten: f.flatten,
                                                    ty: specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    ),
                                                })
                                                .collect(),
                                            tag: f.tag.map(|v| match v {
                                                Cow::Borrowed(v) => v,
                                                Cow::Owned(v) => String::leak(v),
                                            }),
                                        })
                                    }
                                    crate::datatype::EnumVariants::Unnamed(f) => {
                                        specta1::EnumVariant::Unnamed(specta1::TupleType {
                                            generics: generics.clone(),
                                            fields: f
                                                .fields
                                                .into_iter()
                                                .map(|f| {
                                                    specta_v2_to_v1(
                                                        f.ty.unwrap_or(DataType::Unknown),
                                                    )
                                                })
                                                .collect(),
                                        })
                                    }
                                },
                            )
                        })
                        .collect(),
                },
            })
        }
        DataType::Tuple(t) => specta1::DataType::Tuple(specta1::TupleType {
            fields: t.elements.into_iter().map(specta_v2_to_v1).collect(),
            generics: vec![],
        }),
        DataType::Reference(r) => specta1::DataType::Reference(specta1::DataTypeReference {
            name: match r.name {
                Cow::Borrowed(v) => v,
                Cow::Owned(v) => String::leak(v),
            },
            sid: specta1::r#type::internal_sid_hash("specta1", "", r.sid.type_name),
            generics: r
                .generics
                .into_iter()
                .map(|(_, d)| specta_v2_to_v1(d))
                .collect(),
        }),
        DataType::Generic(g) => specta1::DataType::Generic(specta1::GenericType(match g.0 {
            Cow::Borrowed(s) => s,
            Cow::Owned(s) => String::leak(s),
        })),
    }
}

pub fn specta_v2_type_map_to_v1_type_defs(defs: TypeCollection, type_map: &mut specta1::TypeDefs) {
    for (sid, dt) in defs.into_iter() {
        let dtv1 = specta_v2_to_v1(dt.inner.clone());
        let sid = specta1::r#type::internal_sid_hash("specta1", "", sid.type_name);
        type_map.insert(
            sid,
            Some(NamedDataType {
                name: match dt.name.clone() {
                    Cow::Borrowed(v) => v,
                    Cow::Owned(v) => String::leak(v),
                },
                sid: Some(sid),
                impl_location: None,
                comments: Vec::leak(vec![match dt.docs.clone() {
                    Cow::Borrowed(v) => v,
                    Cow::Owned(v) => String::leak(v),
                }]),
                export: None,
                deprecated: dt.deprecated.clone().map(|v| match v {
                    DeprecatedType::Deprecated => "",
                    DeprecatedType::DeprecatedWithSince {  note, .. } => match note {
                        Cow::Borrowed(v) => v,
                        Cow::Owned(v) => String::leak(v),
                    }
                }),
                item: match dtv1 {
                    specta1::DataType::Object(o) => specta1::NamedDataTypeItem::Object(o),
                    specta1::DataType::Enum(e) => specta1::NamedDataTypeItem::Enum(e),
                    specta1::DataType::Tuple(t) => specta1::NamedDataTypeItem::Tuple(t),
                    _ => unreachable!("Specta v1 doesn't support named types that aren't an object, enum or tuple!"),
                }
            }),
        );
    }
}