latexml_core/binding/def/
traits.rs1use std::collections::VecDeque;
4
5use crate::{
6 common::{
7 arena, arena::SymHashMap as HashMap, color::Color, error::*, glue::Glue,
8 mudimension::MuDimension, muglue::MuGlue, number::Number, store::Stored,
9 },
10 definition::{Reversion, SizingClosure, argument::ArgWrap, register::*},
11 keyvals::KeyVals,
12 list::List,
13 state::{Scope, lookup_font},
14 token::*,
15 tokens::TeXString,
16 whatsit::Whatsit,
17 *,
18};
19
20fn sizer_options_from_whatsit(w: &Whatsit) -> HashMap<Stored> {
24 let mut options: HashMap<Stored> = HashMap::default();
25 for key in ["width", "height", "depth", "vattach", "layout", "mode"] {
26 if let Some(v) = w.get_property(key) {
27 options.insert(key, v.into_owned());
28 }
29 }
30 options
31}
32
33enum SizerRef {
35 Arg(usize),
36 Prop(String),
37}
38
39pub trait IntoOption<T>: Sized {
43 fn into_option(self) -> T;
45}
46
47impl IntoOption<Option<String>> for &str {
48 fn into_option(self) -> Option<String> { Some(self.to_string()) }
49}
50
51impl<T> IntoOption<Option<T>> for Option<T> {
52 fn into_option(self) -> Option<T> { self }
53}
54
55impl IntoOption<bool> for bool {
56 fn into_option(self) -> bool { self }
57}
58impl IntoOption<Option<bool>> for bool {
59 fn into_option(self) -> Option<bool> { Some(self) }
60}
61
62impl<T> IntoOption<Option<Vec<T>>> for Vec<T> {
63 fn into_option(self) -> Option<Vec<T>> { Some(self) }
64}
65
66impl<T> IntoOption<Option<VecDeque<T>>> for VecDeque<T> {
67 fn into_option(self) -> Option<VecDeque<T>> { Some(self) }
68}
69impl IntoOption<Option<usize>> for usize {
70 fn into_option(self) -> Option<usize> { Some(self) }
71}
72
73impl IntoOption<Option<Reversion>> for Tokens {
74 fn into_option(self) -> Option<Reversion> { Some(Reversion::Tokens(self)) }
75}
76impl IntoOption<Option<Reversion>> for &str {
77 fn into_option(self) -> Option<Reversion> {
78 if self.is_empty() {
79 Some(Reversion::Tokens(Tokens!()))
80 } else {
81 Some(Reversion::Tokens(
82 mouth::tokenize_internal(TeXString::assembled(self.to_string()))
88 .pack_parameters()
89 .ok()
90 .unwrap(),
91 ))
92 }
93 }
94}
95
96impl IntoOption<Option<Scope>> for &str {
97 fn into_option(self) -> Option<Scope> {
98 match self {
99 "" => None,
100 "local" => Some(Scope::Local),
101 "Local" => Some(Scope::Local),
102 "LOCAL" => Some(Scope::Local),
103 "global" => Some(Scope::Global),
104 "Global" => Some(Scope::Global),
105 "GLOBAL" => Some(Scope::Global),
106 other => Some(Scope::Named(arena::pin(other))),
107 }
108 }
109}
110impl IntoOption<Option<Scope>> for String {
111 fn into_option(self) -> Option<Scope> {
112 match self.as_ref() {
113 "" => None,
114 "local" => Some(Scope::Local),
115 "Local" => Some(Scope::Local),
116 "LOCAL" => Some(Scope::Local),
117 "global" => Some(Scope::Global),
118 "Global" => Some(Scope::Global),
119 "GLOBAL" => Some(Scope::Global),
120 _ => Some(Scope::Named(arena::pin(self))),
121 }
122 }
123}
124
125impl IntoOption<Option<SizingClosure>> for i64 {
127 fn into_option(self) -> Option<SizingClosure> {
128 Some(Rc::new(move |_| {
129 Ok((
130 Dimension::new(self),
131 Dimension::new(self),
132 Dimension::new(self),
133 ))
134 }))
135 }
136}
137impl IntoOption<Option<SizingClosure>> for &str {
138 fn into_option(self) -> Option<SizingClosure> {
139 if self.is_empty() {
140 None
141 } else if self == "0" {
142 Some(Rc::new(|_| {
143 Ok((
144 Dimension::default(),
145 Dimension::default(),
146 Dimension::default(),
147 ))
148 }))
149 } else if self.starts_with('#') {
150 let mut refs: Vec<SizerRef> = Vec::new();
153 let mut rest = self;
154 while let Some(stripped) = rest.strip_prefix('#') {
155 let end = stripped.find('#').unwrap_or(stripped.len());
156 let name = &stripped[..end];
157 if let Ok(n) = name.parse::<usize>() {
158 refs.push(SizerRef::Arg(n));
159 } else {
160 refs.push(SizerRef::Prop(name.to_string()));
161 }
162 rest = &stripped[end..];
163 }
164 Some(Rc::new(move |w| {
165 let mut boxes: Vec<Digested> = Vec::with_capacity(refs.len());
166 for r in &refs {
167 match r {
168 SizerRef::Arg(n) => {
169 if let Some(arg) = w.get_arg(*n) {
170 boxes.push(arg.clone());
171 }
172 },
173 SizerRef::Prop(name) => {
174 if let Some(Stored::Digested(d)) = w.get_property(name).as_deref() {
175 boxes.push(d.clone());
176 }
177 },
178 }
179 }
180 if boxes.len() == 1 {
181 let options = sizer_options_from_whatsit(w);
184 boxes[0].compute_size(options)
185 } else if boxes.is_empty() {
186 Ok((
187 Dimension::default(),
188 Dimension::default(),
189 Dimension::default(),
190 ))
191 } else {
192 let font = match w.get_property("font").as_deref() {
193 Some(Stored::Font(font)) => font.clone(),
194 _ => lookup_font().unwrap(),
195 };
196 let options = sizer_options_from_whatsit(w);
197 font.compute_boxes_size(&boxes, options)
198 }
199 }))
200 } else {
201 let sized_data = String::from(self);
203 Some(Rc::new(move |w| {
204 let font = match *w.get_property("font").unwrap() {
205 Stored::Font(ref font) => font.clone(),
206 _ => lookup_font().unwrap(),
207 };
208 let options = sizer_options_from_whatsit(w);
209 font.compute_boxes_size(
210 &[Digested::from(Tbox {
211 text: arena::pin(&sized_data),
212 ..Tbox::default()
213 })],
214 options,
215 )
216 }))
217 }
218 }
219}
220
221pub trait IntoTokensResult<T>: Sized {
224 fn into_tokens_result(self) -> Result<Tokens>;
226}
227
228impl IntoTokensResult<Result<Tokens>> for Token {
229 fn into_tokens_result(self) -> Result<Tokens> { Ok(Tokens!(self)) }
230}
231
232impl IntoTokensResult<Result<Tokens>> for Vec<Token> {
233 fn into_tokens_result(self) -> Result<Tokens> { Ok(Tokens::new(self)) }
234}
235
236impl IntoTokensResult<Result<Tokens>> for Tokens {
237 fn into_tokens_result(self) -> Result<Tokens> { Ok(self) }
238}
239
240impl IntoTokensResult<Result<Tokens>> for Result<Tokens> {
241 fn into_tokens_result(self) -> Result<Tokens> { self }
242}
243
244impl IntoTokensResult<Result<Tokens>> for Result<()> {
245 fn into_tokens_result(self) -> Result<Tokens> {
246 match self {
247 Ok(()) => Ok(Tokens!()),
248 Err(e) => Err(e),
249 }
250 }
251}
252
253impl IntoTokensResult<Result<Tokens>> for () {
254 fn into_tokens_result(self) -> Result<Tokens> { Ok(Tokens!()) }
255}
256
257impl IntoTokensResult<Result<Tokens>> for ArgWrap {
258 fn into_tokens_result(self) -> Result<Tokens> { Ok(self.owned_tokens().unwrap_or_default()) }
260}
261impl IntoTokensResult<Result<Tokens>> for Result<ArgWrap> {
262 fn into_tokens_result(self) -> Result<Tokens> {
264 self.map(|w| w.owned_tokens().unwrap_or_default())
265 }
266}
267
268pub trait IntoResultArgWrap<T>: Sized {
271 fn into_result_argwrap(self) -> Result<ArgWrap>;
273}
274
275impl IntoResultArgWrap<Result<ArgWrap>> for Error {
276 fn into_result_argwrap(self) -> Result<ArgWrap> { Err(self) }
277}
278
279impl<T> IntoResultArgWrap<Result<ArgWrap>> for Result<T>
280where T: Into<ArgWrap> + Sized
281{
282 fn into_result_argwrap(self) -> Result<ArgWrap> { self.map(|v| v.into()) }
283}
284
285impl<T> IntoResultArgWrap<Result<ArgWrap>> for T
286where T: Into<ArgWrap> + Sized
287{
288 fn into_result_argwrap(self) -> Result<ArgWrap> { Ok(self.into()) }
289}
290
291impl IntoResultArgWrap<Result<ArgWrap>> for Vec<Token> {
292 fn into_result_argwrap(self) -> Result<ArgWrap> { Ok(ArgWrap::Tokens(Tokens::new(self))) }
293}
294
295pub trait IntoBoolResult<T>: Sized {
297 fn into_bool_result(self) -> Result<bool>;
299}
300impl IntoBoolResult<Result<bool>> for bool {
301 fn into_bool_result(self) -> Result<bool> { Ok(self) }
302}
303impl IntoBoolResult<Result<bool>> for Result<bool> {
304 fn into_bool_result(self) -> Result<bool> { self }
305}
306
307pub trait IntoDigestedResult<T>: Sized {
309 fn into_digested_result(self) -> Result<Vec<Digested>>;
311}
312impl IntoDigestedResult<Result<Vec<Digested>>> for () {
313 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(Vec::new()) }
314}
315impl IntoDigestedResult<Result<Vec<Digested>>> for Error {
316 fn into_digested_result(self) -> Result<Vec<Digested>> { Err(self) }
317}
318impl IntoDigestedResult<Result<Vec<Digested>>> for Result<()> {
319 fn into_digested_result(self) -> Result<Vec<Digested>> { self.map(|_| Vec::new()) }
320}
321impl IntoDigestedResult<Result<Vec<Digested>>> for Tbox {
322 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(vec![self.into()]) }
323}
324impl IntoDigestedResult<Result<Vec<Digested>>> for Result<Tbox> {
325 fn into_digested_result(self) -> Result<Vec<Digested>> { self.map(|tb| vec![tb.into()]) }
326}
327
328impl IntoDigestedResult<Result<Vec<Digested>>> for Whatsit {
329 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(vec![self.into()]) }
330}
331
332impl IntoDigestedResult<Result<Vec<Digested>>> for List {
333 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(vec![self.into()]) }
334}
335
336impl IntoDigestedResult<Result<Vec<Digested>>> for Digested {
337 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(vec![self]) }
338}
339
340impl IntoDigestedResult<Result<Vec<Digested>>> for Vec<Digested> {
341 fn into_digested_result(self) -> Result<Vec<Digested>> { Ok(self) }
342}
343
344impl IntoDigestedResult<Result<Vec<Digested>>> for Result<Vec<Digested>> {
345 fn into_digested_result(self) -> Result<Vec<Digested>> { self }
346}
347impl IntoDigestedResult<Result<Vec<Digested>>> for Result<Digested> {
348 fn into_digested_result(self) -> Result<Vec<Digested>> { self.map(|d| vec![d]) }
349}
350
351pub trait IntoRegisterValueOption<T>: Sized {
354 fn into_register_value_option(self) -> Option<RegisterValue>;
355}
356impl IntoRegisterValueOption<Option<RegisterValue>> for () {
357 fn into_register_value_option(self) -> Option<RegisterValue> { None }
358}
359impl IntoRegisterValueOption<Option<RegisterValue>> for Option<RegisterValue> {
360 fn into_register_value_option(self) -> Option<RegisterValue> { self }
361}
362impl IntoRegisterValueOption<Option<RegisterValue>> for usize {
363 fn into_register_value_option(self) -> Option<RegisterValue> {
364 Some(RegisterValue::Number(Number(self as i64)))
365 }
366}
367impl IntoRegisterValueOption<Option<RegisterValue>> for Number {
368 fn into_register_value_option(self) -> Option<RegisterValue> { Some(RegisterValue::Number(self)) }
369}
370impl IntoRegisterValueOption<Option<RegisterValue>> for Dimension {
371 fn into_register_value_option(self) -> Option<RegisterValue> {
372 Some(RegisterValue::Dimension(self))
373 }
374}
375impl IntoRegisterValueOption<Option<RegisterValue>> for MuDimension {
376 fn into_register_value_option(self) -> Option<RegisterValue> {
377 Some(RegisterValue::MuDimension(self))
378 }
379}
380impl IntoRegisterValueOption<Option<RegisterValue>> for Glue {
381 fn into_register_value_option(self) -> Option<RegisterValue> { Some(RegisterValue::Glue(self)) }
382}
383impl IntoRegisterValueOption<Option<RegisterValue>> for MuGlue {
384 fn into_register_value_option(self) -> Option<RegisterValue> { Some(RegisterValue::MuGlue(self)) }
385}
386impl IntoRegisterValueOption<Option<RegisterValue>> for Token {
387 fn into_register_value_option(self) -> Option<RegisterValue> { Some(RegisterValue::Token(self)) }
388}
389impl IntoRegisterValueOption<Option<RegisterValue>> for Option<Token> {
390 fn into_register_value_option(self) -> Option<RegisterValue> { self.map(RegisterValue::Token) }
391}
392impl IntoRegisterValueOption<Option<RegisterValue>> for Tokens {
393 fn into_register_value_option(self) -> Option<RegisterValue> { Some(RegisterValue::Tokens(self)) }
394}
395
396impl IntoRegisterValueOption<Option<RegisterValue>> for Option<Number> {
397 fn into_register_value_option(self) -> Option<RegisterValue> { self.map(RegisterValue::Number) }
398}
399
400pub trait IntoDigestedOptionResult<T>: Sized {
402 fn into_digested_option_result(self) -> Result<Option<Digested>>;
403}
404
405impl IntoDigestedOptionResult<Result<Option<Digested>>> for () {
406 fn into_digested_option_result(self: ()) -> Result<Option<Digested>> { Ok(None) }
407}
408
409impl IntoDigestedOptionResult<Result<Option<Digested>>> for Glue {
410 fn into_digested_option_result(self) -> Result<Option<Digested>> {
411 RegisterValue::Glue(self).into_digested_option_result()
412 }
413}
414impl IntoDigestedOptionResult<Result<Option<Digested>>> for MuGlue {
415 fn into_digested_option_result(self) -> Result<Option<Digested>> {
416 RegisterValue::MuGlue(self).into_digested_option_result()
417 }
418}
419impl IntoDigestedOptionResult<Result<Option<Digested>>> for Dimension {
420 fn into_digested_option_result(self) -> Result<Option<Digested>> {
421 RegisterValue::Dimension(self).into_digested_option_result()
422 }
423}
424impl IntoDigestedOptionResult<Result<Option<Digested>>> for MuDimension {
425 fn into_digested_option_result(self) -> Result<Option<Digested>> {
426 RegisterValue::MuDimension(self).into_digested_option_result()
427 }
428}
429
430impl IntoDigestedOptionResult<Result<Option<Digested>>> for Number {
431 fn into_digested_option_result(self) -> Result<Option<Digested>> {
432 RegisterValue::Number(self).into_digested_option_result()
433 }
434}
435
436impl IntoDigestedOptionResult<Result<Option<Digested>>> for RegisterValue {
437 fn into_digested_option_result(self) -> Result<Option<Digested>> { Ok(Some(self.into())) }
438}
439impl IntoDigestedOptionResult<Result<Option<Digested>>> for Option<Digested> {
440 fn into_digested_option_result(self) -> Result<Option<Digested>> { Ok(self) }
441}
442impl IntoDigestedOptionResult<Result<Option<Digested>>> for Result<Option<Digested>> {
443 fn into_digested_option_result(self) -> Result<Option<Digested>> { self }
444}
445impl IntoDigestedOptionResult<Result<Option<Digested>>> for KeyVals {
446 fn into_digested_option_result(self) -> Result<Option<Digested>> {
447 Ok(Some(Digested::from(self)))
448 }
449}
450impl IntoDigestedOptionResult<Result<Option<Digested>>> for Option<KeyVals> {
451 fn into_digested_option_result(self) -> Result<Option<Digested>> {
452 match self {
453 None => Ok(None),
454 Some(kv) => kv.into(),
455 }
456 }
457}
458impl IntoDigestedOptionResult<Result<Option<Digested>>> for List {
459 fn into_digested_option_result(self) -> Result<Option<Digested>> {
460 Ok(Some(Digested::from(self)))
461 }
462}
463
464pub trait IntoPropertiesResult {
465 fn into_properties_result(self) -> Result<HashMap<Stored>>;
466}
467impl IntoPropertiesResult for HashMap<Stored> {
468 fn into_properties_result(self) -> Result<HashMap<Stored>> { Ok(self) }
469}
470impl IntoPropertiesResult for Result<HashMap<Stored>> {
471 fn into_properties_result(self) -> Result<HashMap<Stored>> { self }
472}
473
474pub trait IntoFontField<T>: Sized {
475 fn into_font_field(self) -> T;
476}
477
478impl IntoFontField<Option<bool>> for bool {
479 fn into_font_field(self) -> Option<bool> { Some(self) }
480}
481
482impl IntoFontField<bool> for bool {
483 fn into_font_field(self) -> bool { self }
484}
485
486impl IntoFontField<Option<Cow<'static, str>>> for &'static str {
487 fn into_font_field(self) -> Option<Cow<'static, str>> { Some(Cow::Borrowed(self)) }
488}
489impl IntoFontField<Option<f64>> for f64 {
490 fn into_font_field(self) -> Option<f64> { Some(self) }
491}
492impl IntoFontField<Option<f64>> for i32 {
493 fn into_font_field(self) -> Option<f64> { Some(self as f64) }
494}
495impl IntoFontField<Option<Color>> for Color {
496 fn into_font_field(self) -> Option<Color> { Some(self) }
497}