mf2_runtime/functions/
string.rs1use crate::error::FormatError;
7use crate::function::{FnContext, Function, Options};
8use crate::number::equals;
9use crate::sink::{ErrorSink, Sink};
10use crate::unannotated;
11use crate::value::Value;
12
13#[derive(Clone, Copy, Default, Debug)]
15pub struct StringFunction;
16
17impl Function for StringFunction {
18 fn resolve<'a>(
19 &self,
20 cx: &FnContext<'_>,
21 operand: Option<&Value<'a>>,
22 _options: &Options<'_, 'a>,
23 errs: &mut dyn ErrorSink,
24 ) -> Option<Value<'a>> {
25 let value = operand.and_then(Value::try_copy);
28 match value {
29 Some(v) if unannotated::formattable(&v, cx.host()).is_ok() => Some(v),
30 _ => {
31 errs.error(FormatError::BadOperand);
32 None
33 }
34 }
35 }
36
37 fn format(&self, cx: &FnContext<'_>, value: &Value<'_>, out: &mut dyn Sink) {
38 unannotated::format(value, cx.host(), out);
39 }
40
41 fn selectable(&self, _value: &Value<'_>) -> bool {
42 true
43 }
44
45 fn matches(
46 &self,
47 cx: &FnContext<'_>,
48 value: &Value<'_>,
49 key: &str,
50 _errs: &mut dyn ErrorSink,
51 ) -> bool {
52 match value.as_str() {
53 Some(s) => crate::nfc::equivalent(cx.catalog.nfc_map(), s, key),
55 None => equals(key, |out| unannotated::format(value, cx.host(), out)),
57 }
58 }
59}