reflection/
lib.rs

1//! This library produces type schema information,
2//! including field names and type names in hierarchical [tree structure](https://docs.rs/trees), which reflects the type definitions.
3//!
4//! To avoid circular type definition, the pointer types( raw/smart pointers, references etc ) will be treated as terminal types,
5//! unless using `expand()` to get the referenced type's `schemata()`.
6//!
7//! # Example
8//!
9//! See [`fn serde_issue_345()`](https://github.com/oooutlk/reflection/blob/master/reflection_test/src/lib.rs#L151) for generating pretty print format from `schemata()`.
10
11extern crate trees;
12use trees::{tr,Tree,Forest,Node};
13
14use std::fmt;
15use std::fmt::{Display,Formatter};
16
17pub type Id = &'static str;
18pub type Name = Option<String>;
19
20#[derive( Copy, Clone, Debug, PartialEq, Eq, Ord )]
21/// Type constructs.
22pub enum Type {
23    Unknown,
24    Struct, Enum,
25    Bool, I8, U8, I16, U16, I32, U32, I64, U64, I128, U128, F32, F64,
26    Range,
27    RefStr, String,
28    Array, Tuple, Vec, 
29    CPtr, Ptr, NonNull, Ref, RefMut, Box, Rc,
30    Option, Result,
31    BTreeSet, HashSet,
32    BTreeMap, HashMap,
33}
34
35impl Type {
36    /// Returns `true` for the generalized pointer types such as raw/smart pointers and references, otherwise returns `false`.
37    pub fn is_pointer( &self ) -> bool { *self >= Type::CPtr && *self <= Type::Rc }
38}
39
40use std::cmp::Ordering;
41use std::cmp::Ordering::*;
42
43impl PartialOrd for Type {
44    fn partial_cmp( &self, other: &Self ) -> Option<Ordering> {
45        let ( a, b ) = ( *self as usize, *other as usize );
46        if a < b {
47            Some( Less )
48        } else if a > b {
49            Some( Greater )
50        } else {
51            Some( Equal )
52        }
53    }
54}
55
56impl Display for Type { fn fmt( &self, f: &mut Formatter ) -> fmt::Result { write!( f, "{}", TYPE_STR[ *self as usize ])}}
57
58const TYPE_STR: [Id;35] = [
59    "?",
60    "struct", "enum",
61    "bool", "i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "i128", "u128", "f32", "f64",
62    "Range",
63    "&str", "String",
64    "[]", "()", "Vec", 
65    "*const", "*mut", "NonNull", "&", "&mut", "Box", "Rc",
66    "Option", "Result",
67    "BTreeSet", "HashSet",
68    "BTreeMap", "HashMap",
69];
70
71/// To get the members of some type.
72pub type Expander = Option<fn() -> Schemas>;
73
74/// A type definition, or a field definition of some struct.
75#[derive( Clone, Debug, PartialEq, Eq )]
76pub struct Field {
77    pub id       : Id,
78    pub ty       : Type,
79    pub tyname   : Name,
80    pub expander : Expander,
81}
82
83impl Field {
84    pub fn new( id: Id, ty: Type, tyname: Name, expander: Expander ) -> Self {
85        Field { id, ty, tyname, expander }
86    }
87}
88
89/// A variant definition of some enum.
90#[derive( Clone, Debug, Eq, PartialEq )]
91pub struct Variant {
92    pub id     : Id,
93    pub tyname : Name,
94}
95
96/// The type of schema tree node.
97#[derive( Clone, Debug, PartialEq, Eq )]
98pub enum Member {
99    Field( Field ),
100    Variant( Variant ),
101}
102
103impl Member {
104    pub fn id( &self ) -> Id {
105        match *self {
106            Member::Field( ref field ) => field.id,
107            Member::Variant( ref variant ) => variant.id,
108        }
109    }
110}
111
112/// Defines a `Field` as a tree node.
113pub fn field( id: Id, ty: Type, tyname: Name, expander: Expander ) -> Schema { tr( Member::Field( Field::new( id, ty, tyname, expander )))}
114
115/// Defines a `Variant` as a tree node.
116pub fn variant( id: Id ) -> Schema { tr( Member::Variant( Variant{ id, tyname: None }))}
117
118/// Defines a `Field` as a tree node, which should have no child node.
119pub fn terminal( id: Id, ty: Type ) -> Schema {
120    tr( Member::Field( Field::new( id, ty,
121            Some( String::from( TYPE_STR[ ty as usize ])), None )))
122}
123
124impl Display for Member {
125    fn fmt( &self, f: &mut Formatter ) -> fmt::Result {
126        match *self {
127            Member::Field( ref field ) =>
128                write!( f, "{}:{}", field.id, &field.tyname.clone().unwrap_or_default() ),
129            Member::Variant( ref variant ) => 
130                write!( f, "{}|", variant.id ),
131        }
132    }
133}
134
135pub type Schema  = Tree  <Member>;
136pub type Schemas = Forest<Member>;
137
138/// Reflects type's fields' names and their type names.
139pub trait Reflection {
140    /// Returns type construct.
141    fn ty() -> Type { Type::Unknown }
142
143    /// Returns type name.
144    fn name() -> Name { Some( String::from( TYPE_STR[ Self::ty() as usize ]))}
145
146    /// Reflects field name, its type name and its members, by a tree of degree 1.
147    fn schema( id: Id ) -> Schema;
148
149    /// Reflects members' schema() by a forest of degree 1.
150    fn members() -> Schemas { Schemas::new() }
151
152    /// Reflects type's fields' names and their type names, by expanding `schema()` recursively.
153    fn schemata() -> Schema {
154        let mut schema = Self::schema( "_" );
155        expand( &mut schema );
156        schema
157    }
158}
159
160/// Expands `schema()` recursively, stopping at fields of primitives or pointers.
161#[allow( unused_must_use )]
162pub fn expand( node: &mut Node<Member> ) {
163    expand_field( node ) || expand_variant( node );
164}
165
166fn expand_field( node: &mut Node<Member> ) -> bool {
167    let mut expander: Expander = None;
168    if let Member::Field( ref field ) = node.data {
169        if node.is_leaf() && !field.ty.is_pointer() {
170            expander = field.expander;
171        }
172    }
173    expander.map( |expander| {
174        node.append( expander() );
175        for mut child in node.iter_mut() {
176            expand( &mut child );
177        }
178        true
179    }).unwrap_or( false ) 
180}
181
182fn expand_variant( node: &mut Node<Member> ) -> bool {
183    if let Member::Variant(_) = &mut node.data {
184        for mut child in node.iter_mut() {
185            expand_field( &mut child );
186        }
187        true
188    } else {
189        false
190    }
191}
192
193macro_rules! ty {
194    ($t:ty) => { <$t as Reflection>::ty() }
195}
196
197macro_rules! name {
198    ($ty:ty) => { <$ty as Reflection>::name() }
199}
200
201macro_rules! name_ {
202    ($ty:ty) => { <$ty as Reflection>::name().unwrap_or( String::from( "_" )) }
203}
204
205macro_rules! expander {
206    ($ty:ty) => { Some( <$ty as Reflection>::members )}
207}
208
209impl Reflection for bool { fn ty() -> Type { Type::Bool } fn schema( id: Id ) -> Schema { terminal( id, Type::Bool )}}
210impl Reflection for i8   { fn ty() -> Type { Type::I8   } fn schema( id: Id ) -> Schema { terminal( id, Type::I8   )}}
211impl Reflection for u8   { fn ty() -> Type { Type::U8   } fn schema( id: Id ) -> Schema { terminal( id, Type::U8   )}}
212impl Reflection for i16  { fn ty() -> Type { Type::I16  } fn schema( id: Id ) -> Schema { terminal( id, Type::I16  )}}
213impl Reflection for u16  { fn ty() -> Type { Type::U16  } fn schema( id: Id ) -> Schema { terminal( id, Type::U16  )}}
214impl Reflection for i32  { fn ty() -> Type { Type::I32  } fn schema( id: Id ) -> Schema { terminal( id, Type::I32  )}}
215impl Reflection for u32  { fn ty() -> Type { Type::U32  } fn schema( id: Id ) -> Schema { terminal( id, Type::U32  )}}
216impl Reflection for i64  { fn ty() -> Type { Type::I64  } fn schema( id: Id ) -> Schema { terminal( id, Type::I64  )}}
217impl Reflection for u64  { fn ty() -> Type { Type::U64  } fn schema( id: Id ) -> Schema { terminal( id, Type::U64  )}}
218impl Reflection for i128 { fn ty() -> Type { Type::I128 } fn schema( id: Id ) -> Schema { terminal( id, Type::I128 )}}
219impl Reflection for u128 { fn ty() -> Type { Type::U128 } fn schema( id: Id ) -> Schema { terminal( id, Type::U128 )}}
220impl Reflection for f32  { fn ty() -> Type { Type::F32  } fn schema( id: Id ) -> Schema { terminal( id, Type::F32  )}}
221impl Reflection for f64  { fn ty() -> Type { Type::F64  } fn schema( id: Id ) -> Schema { terminal( id, Type::F64  )}}
222
223impl<T:Reflection> Reflection for std::ops::Range<T> {
224    fn ty() -> Type { Type::Range }
225    fn name() -> Name { Some( format!( "Range<{}>", name_!(T) ))}
226    fn schema( id: Id ) -> Schema { field( id, Type::Range, name!(Self), expander!(Self) )}
227    fn members() -> Schemas {
228        - field( "start", ty!(T), name!(T), expander!(T) )
229        - field( "end",   ty!(T), name!(T), expander!(T) )
230    }
231}
232
233impl<'a> Reflection for &'a str { fn ty() -> Type { Type::RefStr } fn schema( id: Id ) -> Schema { terminal( id, Type::String )}}
234impl     Reflection for String  { fn ty() -> Type { Type::String } fn schema( id: Id ) -> Schema { terminal( id, Type::String )}}
235
236impl<T> Reflection for *const T where T: ?Sized + Reflection {
237    fn ty() -> Type { Type::CPtr }
238    fn name() -> Name { Some( format!( "*const {}", name_!(T) ))}
239    fn schema( id: Id ) -> Schema { field( id, Type::CPtr, name!(Self), expander!(Self) )}
240    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
241}
242
243impl<T> Reflection for *mut T where T: ?Sized + Reflection {
244    fn ty() -> Type { Type::Ptr }
245    fn name() -> Name { Some( format!( "*mut {}", name_!(T) ))}
246    fn schema( id: Id ) -> Schema { field( id, Type::Ptr, name!(Self), expander!(Self) )}
247    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
248}
249
250impl<T> Reflection for std::ptr::NonNull<T> where T: ?Sized + Reflection {
251    fn ty() -> Type { Type::NonNull }
252    fn name() -> Name { Some( format!( "NonNull<{}>", name_!(T) ))}
253    fn schema( id: Id ) -> Schema { field( id, Type::NonNull, name!(Self), expander!(Self) )}
254    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
255}
256
257impl<'a,T> Reflection for &'a T where T: 'a + ?Sized + Reflection {
258    fn ty() -> Type { Type::Ref }
259    fn name() -> Name { Some( format!( "&{}", name_!(T) ))}
260    fn schema( id: Id ) -> Schema { field( id, Type::Ref, name!(Self), expander!(Self) )}
261    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
262}
263
264impl<'a,T> Reflection for &'a mut T where T: 'a + ?Sized + Reflection {
265    fn ty() -> Type { Type::RefMut }
266    fn name() -> Name { Some( format!( "&mut {}", name_!(T) ))}
267    fn schema( id: Id ) -> Schema { field( id, Type::RefMut, name!(Self), expander!(Self) )}
268    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
269}
270
271impl<T> Reflection for Box<T> where T: ?Sized + Reflection {
272    fn ty() -> Type { Type::Box }
273    fn name() -> Name { Some( format!( "Box<{}>", name_!(T) ))}
274    fn schema( id: Id ) -> Schema { field( id, Type::Box, name!(Self), expander!(Self) )}
275    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
276}
277
278impl<T> Reflection for std::rc::Rc<T> where T: ?Sized + Reflection {
279    fn ty() -> Type { Type::Rc }
280    fn name() -> Name { Some( format!( "Rc<{}>", name_!(T) ))}
281    fn schema( id: Id ) -> Schema { field( id, Type::Rc, name!(Self), expander!(Self) )}
282    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
283}
284
285impl<T> Reflection for Vec<T> where T: Reflection {
286    fn ty() -> Type { Type::Vec }
287    fn name() -> Name { Some( format!( "Vec<{}>", name_!(T) ))}
288    fn schema( id: Id ) -> Schema { field( id, Type::Vec, name!(Self), expander!(Self) )}
289    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
290}
291
292impl<T> Reflection for Option<T> where T: Reflection {
293    fn ty() -> Type { Type::Enum }
294    fn name() -> Name { Some( format!( "Option<{}>", name_!(T) ))}
295    fn schema( id: Id ) -> Schema { field( id, Type::Option, name!(Self), expander!(Self) )}
296    fn members() -> Schemas {
297        -( variant( "None" ))
298        -( variant( "Some" ) / field( "0", ty!(T), name!(T), expander!(T) ))
299    }
300}
301
302impl<T,E> Reflection for Result<T,E> where T: Reflection, E: Reflection {
303    fn ty() -> Type { Type::Result }
304    fn name() -> Name { Some( format!( "Result<{},{}>", name_!(T), name_!(E) ))}
305    fn schema( id: Id ) -> Schema { field( id, Type::Result, name!(Self), expander!(Self) )}
306    fn members() -> Schemas {
307        -( variant( "Ok"  ) / field( "_", ty!(T), name!(T), expander!(T) ))
308        -( variant( "Err" ) / field( "_", ty!(E), name!(E), expander!(E) ))
309    }
310}
311
312impl<T:Reflection> Reflection for std::collections::BTreeSet<T> {
313    fn ty() -> Type { Type::BTreeSet }
314    fn name() -> Name { Some( format!( "BTreeSet<{}>", name_!(T) ))}
315    fn schema( id: Id ) -> Schema { field( id, Type::BTreeSet, name!(Self), expander!(Self) )}
316    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
317}
318
319impl<T:Reflection> Reflection for std::collections::HashSet<T> {
320    fn ty() -> Type { Type::HashSet }
321    fn name() -> Name { Some( format!( "HashSet<{}>", name_!(T) ))}
322    fn schema( id: Id ) -> Schema { field( id, Type::HashSet, name!(Self), expander!(Self) )}
323    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
324}
325
326impl<K,V> Reflection for std::collections::BTreeMap<K,V> where K: Reflection, V: Reflection {
327    fn ty() -> Type { Type::BTreeMap }
328    fn name() -> Name { Some( format!( "BTreeMap<{},{}>", name_!(K), name_!(V) ))}
329    fn schema( id: Id ) -> Schema { field( id, Type::BTreeMap, name!(Self), expander!(Self) )}
330    fn members() -> Schemas {
331        - field( "name", ty!(K), name!(K), expander!(K) )
332        - field( "value", ty!(V), name!(V), expander!(V) )
333    }
334}
335
336impl<K,V> Reflection for std::collections::HashMap<K,V> where K: Reflection, V: Reflection {
337    fn ty() -> Type { Type::HashMap }
338    fn name() -> Name { Some( format!( "HashMap<{},{}>", name_!(K), name_!(V) ))}
339    fn schema( id: Id ) -> Schema { field( id, Type::HashMap, name!(Self), expander!(Self) )}
340    fn members() -> Schemas {
341        - field( "name", ty!(K), name!(K), expander!(K) )
342        - field( "value", ty!(V), name!(V), expander!(V) )
343    }
344}
345
346impl<T> Reflection for [T] where T: Reflection {
347    fn ty() -> Type { Type::Array }
348    fn name() -> Name { Some( format!( "[{}]", name_!(T) ))}
349    fn schema( id: Id ) -> Schema { field( id, Type::Array, name!(Self), expander!(Self) )}
350    fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
351}
352
353macro_rules! array_impls {
354    ($($len:tt)+) => {
355        $(
356            impl<T> Reflection for [T;$len] where T: Reflection {
357                fn ty() -> Type { Type::Array }
358                fn name() -> Name { Some( format!( "[{}]", name_!(T) ))}
359                fn schema( id: Id ) -> Schema { field( id, Type::Array, name!(Self), expander!(Self) )}
360                fn members() -> Schemas { - field( "_", ty!(T), name!(T), expander!(T) )}
361            }
362        )+
363    }
364}
365
366array_impls!(
367    01 02 03 04 05 06 07 08
368    09 10 11 12 13 14 15 16
369    17 18 19 20 21 22 23 24
370    25 26 27 28 29 30 31 32
371);
372
373impl Reflection for () {
374    fn ty() -> Type { Type::Tuple }
375    fn name() -> Name { Some( format!( "()" ))}
376    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), None )}
377}
378
379impl<T0> Reflection for (T0,)
380    where T0: Reflection,
381{
382    fn ty() -> Type { Type::Tuple }
383    fn name() -> Name { Some( format!( "({},)", name_!(T0) ))}
384    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
385    fn members() -> Schemas { - field( "0", ty!(T0), name!(T0), expander!(T0) )}
386}
387
388impl<T0,T1> Reflection for (T0,T1)
389    where T0: Reflection, T1: Reflection,
390{
391    fn ty() -> Type { Type::Tuple }
392    fn name() -> Name { Some( format!( "({},{})", name_!(T0), name_!(T1) ))}
393    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
394    fn members() -> Schemas {
395        - field( "0", ty!(T0), name!(T0), expander!(T0) )
396        - field( "1", ty!(T1), name!(T1), expander!(T1) )
397    }
398}
399
400impl<T0,T1,T2> Reflection for (T0,T1,T2)
401    where T0: Reflection, T1: Reflection, T2: Reflection
402{
403    fn ty() -> Type { Type::Tuple }
404    fn name() -> Name { Some( format!( "({},{},{})", name_!(T0), name_!(T1), name_!(T2) ))}
405    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
406    fn members() -> Schemas {
407        - field( "0", ty!(T0), name!(T0), expander!(T0) )
408        - field( "1", ty!(T1), name!(T1), expander!(T1) )
409        - field( "2", ty!(T2), name!(T2), expander!(T2) )
410    }
411}
412
413impl<T0,T1,T2,T3> Reflection for (T0,T1,T2,T3)
414    where T0: Reflection, T1: Reflection, T2: Reflection, T3: Reflection
415{
416    fn ty() -> Type { Type::Tuple }
417    fn name() -> Name { Some( format!( "({},{},{},{})", name_!(T0), name_!(T1), name_!(T2), name_!(T3) ))}
418    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
419    fn members() -> Schemas {
420        - field( "0", ty!(T0), name!(T0), expander!(T0) )
421        - field( "1", ty!(T1), name!(T1), expander!(T1) )
422        - field( "2", ty!(T2), name!(T2), expander!(T2) )
423        - field( "3", ty!(T3), name!(T3), expander!(T3) )
424    }
425}
426
427impl<T0,T1,T2,T3,T4> Reflection for (T0,T1,T2,T3,T4)
428    where T0: Reflection, T1: Reflection, T2: Reflection, T3: Reflection, T4: Reflection
429{
430    fn ty() -> Type { Type::Tuple }
431    fn name() -> Name { Some( format!( "({},{},{},{},{})", name_!(T0), name_!(T1), name_!(T2), name_!(T3), name_!(T4) ))}
432    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
433    fn members() -> Schemas {
434        - field( "0", ty!(T0), name!(T0), expander!(T0) )
435        - field( "1", ty!(T1), name!(T1), expander!(T1) )
436        - field( "2", ty!(T2), name!(T2), expander!(T2) )
437        - field( "3", ty!(T3), name!(T3), expander!(T3) )
438        - field( "4", ty!(T4), name!(T4), expander!(T4) )
439    }
440}
441
442impl<T0,T1,T2,T3,T4,T5> Reflection for (T0,T1,T2,T3,T4,T5)
443    where T0: Reflection, T1: Reflection, T2: Reflection, T3: Reflection, T4: Reflection, T5: Reflection
444{
445    fn ty() -> Type { Type::Tuple }
446    fn name() -> Name { Some( format!( "({},{},{},{},{},{})", name_!(T0), name_!(T1), name_!(T2), name_!(T3), name_!(T4), name_!(T5) ))}
447    fn schema( id: Id ) -> Schema { field( id, Type::Tuple, name!(Self), expander!(Self) )}
448    fn members() -> Schemas {
449        - field( "0", ty!(T0), name!(T0), expander!(T0) )
450        - field( "1", ty!(T1), name!(T1), expander!(T1) )
451        - field( "2", ty!(T2), name!(T2), expander!(T2) )
452        - field( "3", ty!(T3), name!(T3), expander!(T3) )
453        - field( "4", ty!(T4), name!(T4), expander!(T4) )
454        - field( "5", ty!(T5), name!(T5), expander!(T5) )
455    }
456}