aldrin_core/introspection/
function.rs1use 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}