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