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