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