Skip to main content

aphyn_reflection/
registry.rs

1use std::{
2    any::{Any, TypeId},
3    collections::HashMap,
4};
5
6use crate::{
7    refl_repr::{ReflRepr, ReflReprFields, ReflReprStruct},
8    refl_repr_reg_entries,
9    refl_ty::{ReflTy, ReflTyId},
10};
11
12// todo: ffi?
13
14#[derive(Default)]
15pub struct ReflTyRegistry {
16    pub types: HashMap<ReflTyId, ReflTy>,
17}
18
19impl ReflTyRegistry {
20    pub fn set(&mut self, id: ReflTyId, ty: ReflTy) {
21        self.types.insert(id, ty);
22    }
23
24    pub fn get(&self, id: &ReflTyId) -> Option<&ReflTy> {
25        self.types.get(id)
26    }
27}
28
29#[derive(Default)]
30pub struct ReflRepresenterRegistry {
31    pub representers: HashMap<TypeId, Box<dyn Any>>,
32}
33
34impl ReflRepresenterRegistry {
35    pub fn set<T: 'static>(&mut self, representer: Box<dyn ReflRepresenter<Item = T>>) {
36        let any = Box::new(representer) as Box<dyn Any>;
37
38        self.representers.insert(TypeId::of::<T>(), any);
39    }
40    pub fn get<T: 'static>(&self) -> Option<&dyn ReflRepresenter<Item = T>> {
41        let any = self.representers.get(&TypeId::of::<T>())?;
42
43        Some(&**(any.downcast_ref::<Box<dyn ReflRepresenter<Item = T>>>()?))
44    }
45
46    pub fn item_name<T: 'static>(&self) -> Option<String> {
47        Some(self.get::<T>()?.item_name(&ReflRepresenterCtx { reg: self }))
48    }
49    pub fn into_repr<T: 'static>(&self, v: &T) -> Option<ReflRepr> {
50        self.get::<T>()?.into_repr(&ReflRepresenterCtx { reg: self }, v)
51    }
52    pub fn from_repr<T: 'static>(&self, v: &ReflRepr) -> Option<T> {
53        self.get::<T>()?.from_repr(&ReflRepresenterCtx { reg: self }, v)
54    }
55}
56
57pub struct ReflRepresenterCtx<'a> {
58    reg: &'a ReflRepresenterRegistry,
59}
60
61impl<'a> ReflRepresenterCtx<'a> {
62    pub fn item_name<T: 'static>(&self) -> Option<String> {
63        Some(self.reg.get::<T>()?.item_name(self))
64    }
65    pub fn into_repr<T: 'static>(&self, v: &T) -> Option<ReflRepr> {
66        self.reg.get::<T>()?.into_repr(self, v)
67    }
68    pub fn from_repr<T: 'static>(&self, v: &ReflRepr) -> Option<T> {
69        self.reg.get::<T>()?.from_repr(self, v)
70    }
71}
72
73pub trait ReflRepresenter {
74    type Item;
75
76    fn item_name(&self, ctx: &ReflRepresenterCtx) -> String;
77    fn into_repr(&self, ctx: &ReflRepresenterCtx, v: &Self::Item) -> Option<ReflRepr>;
78    fn from_repr(&self, ctx: &ReflRepresenterCtx, v: &ReflRepr) -> Option<Self::Item> {
79        None
80    }
81}
82
83// example
84
85#[derive(Debug)]
86pub struct ExampleStruct {
87    pub age: u8,
88    pub name: Option<String>,
89}
90
91pub fn registry_use_case() {
92    let mut reg = ReflRepresenterRegistry::default();
93
94    refl_repr_reg_entries::set_common_representers(&mut reg);
95
96    reg.set(Box::new(ExampleStructReflRepresenter::default()));
97
98    let example_struct = ExampleStruct {
99        age: 55,
100        name: Some(String::from("Barry")),
101    };
102
103    let repr = reg.into_repr(&example_struct).unwrap();
104
105    println!("{:?}", repr);
106    println!("{:?}", example_struct);
107}
108
109#[derive(Default)]
110struct ExampleStructReflRepresenter;
111impl ReflRepresenter for ExampleStructReflRepresenter {
112    type Item = ExampleStruct;
113
114    fn item_name(&self, _ctx: &ReflRepresenterCtx) -> String {
115        String::from("ExampleStruct")
116    }
117
118    fn into_repr(&self, ctx: &ReflRepresenterCtx, v: &Self::Item) -> Option<ReflRepr> {
119        Some(ReflRepr::Struct(ReflReprStruct {
120            name: String::from("ExampleStruct"),
121            fields: ReflReprFields::Named(vec![
122                (String::from("age"), ctx.into_repr(&v.age)?),
123                (String::from("name"), ctx.into_repr(&v.name)?),
124            ]),
125        }))
126    }
127}