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