abi_stable/reflection/
export_module.rs

1//! Data structures to export a type as though it were a module.
2
3use std::fmt::{self, Display};
4
5use core_extensions::SelfOps;
6
7use crate::{reflection::ModReflMode, type_layout::*};
8
9#[derive(Debug, Serialize, Deserialize)]
10pub struct MRItem {
11    item_name: String,
12    type_: String,
13    field_accessor: MRFieldAccessor,
14    #[serde(flatten)]
15    variant: MRItemVariant,
16}
17
18#[derive(Debug, Serialize, Deserialize)]
19pub struct MRNameType {
20    name: String,
21    type_: String,
22}
23
24#[derive(Debug, Serialize, Deserialize)]
25#[serde(tag = "variant")]
26pub enum MRItemVariant {
27    Function(MRFunction),
28    Module(MRModule),
29    Static,
30}
31
32#[derive(Debug, Serialize, Deserialize)]
33pub struct MRFunction {
34    params: Vec<MRNameType>,
35    returns: MRNameType,
36}
37
38#[derive(Debug, Serialize, Deserialize)]
39pub struct MRModule {
40    mod_refl_mode: MRModReflMode,
41    items: Vec<MRItem>,
42}
43
44#[derive(Debug, Serialize, Deserialize)]
45pub enum MRModReflMode {
46    Module,
47    Opaque,
48    DelegateDeref,
49}
50
51#[repr(u8)]
52#[derive(Debug, Serialize, Deserialize)]
53pub enum MRFieldAccessor {
54    /// Accessible with `self.field_name`
55    Direct,
56    /// Accessible with `fn field_name(&self)->FieldType`
57    Method { name: Option<String> },
58    /// Accessible with `fn field_name(&self)->Option<FieldType>`
59    MethodOption,
60    /// This field is completely inaccessible.
61    Opaque,
62}
63
64impl MRItem {
65    pub fn from_type_layout(layout: &'static TypeLayout) -> Self {
66        let type_ = layout.full_type().to_string();
67
68        let variant = Self::get_item_variant(layout);
69
70        Self {
71            item_name: "root".into(),
72            type_,
73            field_accessor: MRFieldAccessor::Direct,
74            variant,
75        }
76    }
77
78    fn get_item_variant(layout: &'static TypeLayout) -> MRItemVariant {
79        match layout.mod_refl_mode() {
80            ModReflMode::Module => {
81                let fields = match layout.data() {
82                    TLData::Struct { fields } => fields,
83                    TLData::PrefixType(prefix) => prefix.fields,
84                    TLData::Primitive { .. }
85                    | TLData::Opaque { .. }
86                    | TLData::Union { .. }
87                    | TLData::Enum { .. } => return MRItemVariant::Static,
88                };
89
90                let items = fields
91                    .iter()
92                    .filter(|f| f.field_accessor() != FieldAccessor::Opaque)
93                    .map(|field| {
94                        let (type_, variant) = if field.is_function() {
95                            let func = MRFunction::from(&field.function_range().index(0));
96                            (func.to_string(), MRItemVariant::Function(func))
97                        } else {
98                            let layout = field.layout();
99                            (
100                                layout.full_type().to_string(),
101                                Self::get_item_variant(layout),
102                            )
103                        };
104                        MRItem {
105                            item_name: field.name().to_string(),
106                            type_,
107                            field_accessor: field.field_accessor().into(),
108                            variant,
109                        }
110                    })
111                    .collect::<Vec<_>>();
112                MRItemVariant::Module(MRModule {
113                    mod_refl_mode: layout.mod_refl_mode().into(),
114                    items,
115                })
116            }
117            ModReflMode::Opaque => MRItemVariant::Static,
118            ModReflMode::DelegateDeref { layout_index } => {
119                let delegate_to = layout.shared_vars().type_layouts()[layout_index as usize];
120                let inner_layout = delegate_to();
121                Self::get_item_variant(inner_layout)
122            }
123        }
124    }
125}
126
127///////////////////////////////////////////////////////////////////////////////
128
129impl<'a> From<&'a TLFunction> for MRFunction {
130    fn from(this: &'a TLFunction) -> Self {
131        Self {
132            params: this.get_params().map(MRNameType::from).collect::<Vec<_>>(),
133            returns: this.get_return().into_::<MRNameType>(),
134        }
135    }
136}
137
138impl Display for MRFunction {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        write!(f, "fn(")?;
141        let param_count = self.params.len();
142        for (param_i, param) in self.params.iter().enumerate() {
143            Display::fmt(param, f)?;
144            if param_i + 1 != param_count {
145                Display::fmt(&", ", f)?;
146            }
147        }
148        write!(f, ")")?;
149
150        let returns = &self.returns;
151        Display::fmt(&"->", f)?;
152        Display::fmt(returns, f)?;
153
154        Ok(())
155    }
156}
157
158///////////////////////////////////////////////////////////////////////////////
159
160impl From<TLField> for MRNameType {
161    fn from(field: TLField) -> Self {
162        let name = field.name().to_string();
163        let type_ = if field.is_function() {
164            field.function_range().index(0).to_string()
165        } else {
166            field.layout().full_type().to_string()
167        };
168
169        Self { name, type_ }
170    }
171}
172
173impl Display for MRNameType {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        write!(f, "{}:{}", self.name, self.type_)
176    }
177}
178
179///////////////////////////////////////////////////////////////////////////////
180
181impl From<ModReflMode> for MRModReflMode {
182    fn from(this: ModReflMode) -> Self {
183        match this {
184            ModReflMode::Module { .. } => MRModReflMode::Module,
185            ModReflMode::Opaque { .. } => MRModReflMode::Opaque,
186            ModReflMode::DelegateDeref { .. } => MRModReflMode::DelegateDeref,
187        }
188    }
189}
190
191///////////////////////////////////////////////////////////////////////////////
192
193impl From<FieldAccessor> for MRFieldAccessor {
194    fn from(this: FieldAccessor) -> MRFieldAccessor {
195        match this {
196            FieldAccessor::Direct => MRFieldAccessor::Direct,
197            FieldAccessor::Method => MRFieldAccessor::Method { name: None },
198            FieldAccessor::MethodNamed { name } => MRFieldAccessor::Method {
199                name: Some(name.to_string()),
200            },
201            FieldAccessor::MethodOption => MRFieldAccessor::MethodOption,
202            FieldAccessor::Opaque => MRFieldAccessor::Opaque,
203        }
204    }
205}