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