aldrin_core/introspection/
function.rs

1use super::{ir, resolve_ir, LexicalId};
2use crate::tags::{self, PrimaryTag, Tag};
3use crate::{
4    Deserialize, DeserializeError, Deserializer, Serialize, SerializeError, Serializer, TypeId,
5};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::collections::BTreeMap;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(
11    feature = "serde",
12    derive(serde::Serialize, serde::Deserialize),
13    serde(rename_all = "kebab-case")
14)]
15pub struct Function {
16    id: u32,
17    name: String,
18
19    #[cfg_attr(
20        feature = "serde",
21        serde(default, skip_serializing_if = "Option::is_none")
22    )]
23    doc: Option<String>,
24
25    #[cfg_attr(
26        feature = "serde",
27        serde(default, skip_serializing_if = "Option::is_none")
28    )]
29    args: Option<TypeId>,
30
31    #[cfg_attr(
32        feature = "serde",
33        serde(default, skip_serializing_if = "Option::is_none")
34    )]
35    ok: Option<TypeId>,
36
37    #[cfg_attr(
38        feature = "serde",
39        serde(default, skip_serializing_if = "Option::is_none")
40    )]
41    err: Option<TypeId>,
42}
43
44impl Function {
45    pub fn from_ir(func: ir::FunctionIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
46        Self {
47            id: func.id,
48            name: func.name,
49            doc: func.doc,
50            args: func.args.map(|ty| resolve_ir(ty, references)),
51            ok: func.ok.map(|ty| resolve_ir(ty, references)),
52            err: func.err.map(|ty| resolve_ir(ty, references)),
53        }
54    }
55
56    pub fn id(&self) -> u32 {
57        self.id
58    }
59
60    pub fn name(&self) -> &str {
61        &self.name
62    }
63
64    pub fn doc(&self) -> Option<&str> {
65        self.doc.as_deref()
66    }
67
68    pub fn args(&self) -> Option<TypeId> {
69        self.args
70    }
71
72    pub fn ok(&self) -> Option<TypeId> {
73        self.ok
74    }
75
76    pub fn err(&self) -> Option<TypeId> {
77        self.err
78    }
79}
80
81#[derive(IntoPrimitive, TryFromPrimitive)]
82#[repr(u32)]
83enum FunctionField {
84    Id = 0,
85    Name = 1,
86    Doc = 2,
87    Args = 3,
88    Ok = 4,
89    Err = 5,
90}
91
92impl Tag for Function {}
93
94impl PrimaryTag for Function {
95    type Tag = Self;
96}
97
98impl Serialize<Self> for Function {
99    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
100        serializer.serialize(&self)
101    }
102}
103
104impl Serialize<Function> for &Function {
105    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
106        let mut serializer = serializer.serialize_struct2()?;
107
108        serializer.serialize::<tags::U32>(FunctionField::Id, &self.id)?;
109        serializer.serialize::<tags::String>(FunctionField::Name, &self.name)?;
110
111        serializer
112            .serialize_if_some::<tags::Option<tags::String>>(FunctionField::Doc, &self.doc)?;
113
114        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Args, &self.args)?;
115        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Ok, &self.ok)?;
116        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Err, &self.err)?;
117
118        serializer.finish()
119    }
120}
121
122impl Deserialize<Self> for Function {
123    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
124        let mut deserializer = deserializer.deserialize_struct()?;
125
126        let mut id = None;
127        let mut name = None;
128        let mut doc = None;
129        let mut args = None;
130        let mut ok = None;
131        let mut err = None;
132
133        while let Some(deserializer) = deserializer.deserialize()? {
134            match deserializer.try_id() {
135                Ok(FunctionField::Id) => {
136                    id = deserializer.deserialize::<tags::U32, _>().map(Some)?;
137                }
138
139                Ok(FunctionField::Name) => {
140                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
141                }
142
143                Ok(FunctionField::Doc) => {
144                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
145                }
146
147                Ok(FunctionField::Args) => {
148                    args = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
149                }
150
151                Ok(FunctionField::Ok) => {
152                    ok = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
153                }
154
155                Ok(FunctionField::Err) => {
156                    err = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
157                }
158
159                Err(_) => deserializer.skip()?,
160            }
161        }
162
163        deserializer.finish(Self {
164            id: id.ok_or(DeserializeError::InvalidSerialization)?,
165            name: name.ok_or(DeserializeError::InvalidSerialization)?,
166            doc,
167            args,
168            ok,
169            err,
170        })
171    }
172}