ferogram_tl_parser/tl/
definition.rs1use std::fmt;
16use std::str::FromStr;
17
18use crate::errors::{ParamParseError, ParseError};
19use crate::tl::{Category, Flag, Parameter, ParameterType, Type};
20use crate::utils::tl_id;
21
22#[derive(Clone, Debug, PartialEq)]
31pub struct Definition {
32 pub namespace: Vec<String>,
34
35 pub name: String,
37
38 pub id: u32,
40
41 pub params: Vec<Parameter>,
43
44 pub ty: Type,
46
47 pub category: Category,
49}
50
51impl Definition {
52 pub fn full_name(&self) -> String {
54 let cap = self.namespace.iter().map(|ns| ns.len() + 1).sum::<usize>() + self.name.len();
55 let mut s = String::with_capacity(cap);
56 for ns in &self.namespace {
57 s.push_str(ns);
58 s.push('.');
59 }
60 s.push_str(&self.name);
61 s
62 }
63}
64
65impl fmt::Display for Definition {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 for ns in &self.namespace {
68 write!(f, "{ns}.")?;
69 }
70 write!(f, "{}#{:x}", self.name, self.id)?;
71
72 let mut generics: Vec<&str> = Vec::new();
74 for p in &self.params {
75 if let ParameterType::Normal { ty, .. } = &p.ty {
76 ty.collect_generic_refs(&mut generics);
77 }
78 }
79 generics.sort_unstable();
80 generics.dedup();
81 for g in generics {
82 write!(f, " {{{g}:Type}}")?;
83 }
84
85 for p in &self.params {
86 write!(f, " {p}")?;
87 }
88 write!(f, " = {}", self.ty)
89 }
90}
91
92impl FromStr for Definition {
93 type Err = ParseError;
94
95 fn from_str(raw: &str) -> Result<Self, Self::Err> {
96 let raw = raw.trim();
97 if raw.is_empty() {
98 return Err(ParseError::Empty);
99 }
100
101 let (lhs, ty_str) = raw.split_once('=').ok_or(ParseError::MissingType)?;
103 let lhs = lhs.trim();
104 let ty_str = ty_str.trim().trim_end_matches(';').trim();
105
106 if ty_str.is_empty() {
107 return Err(ParseError::MissingType);
108 }
109
110 let mut ty = Type::from_str(ty_str).map_err(|_| ParseError::MissingType)?;
111
112 let (head, rest) = match lhs.split_once(|c: char| c.is_whitespace()) {
114 Some((h, r)) => (h.trim_end(), r.trim_start()),
115 None => (lhs, ""),
116 };
117
118 let (full_name, explicit_id) = match head.split_once('#') {
120 Some((n, id)) => (n, Some(id)),
121 None => (head, None),
122 };
123
124 let (namespace, name) = match full_name.rsplit_once('.') {
126 Some((ns_part, n)) => (ns_part.split('.').map(String::from).collect::<Vec<_>>(), n),
127 None => (Vec::new(), full_name),
128 };
129
130 if namespace.iter().any(|p| p.is_empty()) || name.is_empty() {
131 return Err(ParseError::MissingName);
132 }
133
134 let id = match explicit_id {
135 Some(hex) => u32::from_str_radix(hex.trim(), 16).map_err(ParseError::InvalidId)?,
136 None => tl_id(raw),
137 };
138
139 let mut type_defs: Vec<String> = Vec::new();
141 let mut flag_defs: Vec<String> = Vec::new();
142
143 let params = rest
144 .split_whitespace()
145 .filter_map(|token| match Parameter::from_str(token) {
146 Err(ParamParseError::TypeDef { name }) => {
148 type_defs.push(name);
149 None
150 }
151 Ok(p) => {
152 match &p {
153 Parameter {
154 ty: ParameterType::Flags,
155 ..
156 } => {
157 flag_defs.push(p.name.clone());
158 }
159 Parameter {
161 ty:
162 ParameterType::Normal {
163 ty:
164 Type {
165 name: tn,
166 generic_ref: true,
167 ..
168 },
169 ..
170 },
171 ..
172 } if !type_defs.contains(tn) => {
173 return Some(Err(ParseError::InvalidParam(
174 ParamParseError::MissingDef,
175 )));
176 }
177 Parameter {
179 ty:
180 ParameterType::Normal {
181 flag: Some(Flag { name: fn_, .. }),
182 ..
183 },
184 ..
185 } if !flag_defs.contains(fn_) => {
186 return Some(Err(ParseError::InvalidParam(
187 ParamParseError::MissingDef,
188 )));
189 }
190 _ => {}
191 }
192 Some(Ok(p))
193 }
194 Err(ParamParseError::NotImplemented) => Some(Err(ParseError::NotImplemented)),
195 Err(e) => Some(Err(ParseError::InvalidParam(e))),
196 })
197 .collect::<Result<Vec<_>, ParseError>>()?;
198
199 if type_defs.contains(&ty.name) {
201 ty.generic_ref = true;
202 }
203
204 Ok(Definition {
205 namespace,
206 name: name.to_owned(),
207 id,
208 params,
209 ty,
210 category: Category::Types, })
212 }
213}