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