tmpl_resolver/resolver/
std_impl.rs

1use core::fmt::Display;
2use std::collections::HashMap as StdHashMap;
3
4use kstring::KString;
5use tap::Pipe;
6
7use crate::{
8  TemplateResolver,
9  error::{ResolverError, ResolverResult},
10  parsers::parse_value_or_map_err,
11  resolver::TemplateAST,
12};
13
14impl<K, V, S> TryFrom<StdHashMap<K, V, S>> for TemplateResolver
15where
16  K: Into<KString> + Display,
17  V: AsRef<str>,
18{
19  type Error = ResolverError;
20
21  fn try_from(value: StdHashMap<K, V, S>) -> Result<Self, Self::Error> {
22    Self::try_from_raw(value)
23  }
24}
25
26impl<K, V, S> TryFrom<ahash::AHashMap<K, V, S>> for TemplateResolver
27where
28  K: Into<KString> + Display,
29  V: AsRef<str>,
30{
31  type Error = ResolverError;
32
33  fn try_from(value: ahash::AHashMap<K, V, S>) -> Result<Self, Self::Error> {
34    Self::try_from_raw(value)
35  }
36}
37
38impl<K, V> TryFrom<Vec<(K, V)>> for TemplateResolver
39where
40  K: Into<KString> + Display,
41  V: AsRef<str>,
42{
43  type Error = ResolverError;
44
45  fn try_from(value: Vec<(K, V)>) -> Result<Self, Self::Error> {
46    Self::try_from_raw(value)
47  }
48}
49
50impl TemplateResolver {
51  /// Construct from `IntoIterator<(K, V)>`, e.g., HashMap
52  ///
53  /// ## Example
54  ///
55  /// ```
56  /// use tmpl_resolver::TemplateResolver;
57  /// use tap::pipe::Pipe;
58  ///
59  /// let resolver = [
60  ///    (
61  ///      "salutation",
62  ///      "
63  ///      $gender ->
64  ///        [male] Mr.
65  ///        *[female] Ms.",
66  ///    ),
67  ///    ("g", "Good"),
68  ///    (
69  ///      "time-greeting",
70  ///      "$period ->
71  ///        [morning] {g} Morning
72  ///        [evening] {g} Evening
73  ///        *[other] {g} {$period}
74  ///      ",
75  ///    ),
76  ///    ("greeting", "{ time-greeting }! { salutation }{ $name }"),
77  ///  ]
78  ///  // .into_iter()
79  ///  // .map(|(k, v)| (k.into(), v.into()))
80  ///  // .collect::<tmpl_resolver::resolver::AHashRawMap>()
81  ///  .pipe(TemplateResolver::try_from_raw)?;
82  ///
83  /// let text = resolver
84  ///    .get_with_context(
85  ///      "greeting",
86  ///      &[
87  ///        ("period", "evening"),
88  ///        ("name", "Alice"),
89  ///        ("gender", "unknown"),
90  ///      ],
91  ///    )
92  ///    .expect("Failed to get text");
93  ///
94  /// assert_eq!(text, "Good Evening! Ms.Alice");
95  /// # Ok::<(), tmpl_resolver::error::ResolverError>(())
96  /// ```
97  pub fn try_from_raw<K, V, I>(iter: I) -> ResolverResult<Self>
98  where
99    K: Into<KString> + Display,
100    V: AsRef<str>,
101    I: IntoIterator<Item = (K, V)>,
102  {
103    iter
104      .into_iter()
105      .map(|(key, value)| {
106        parse_value_or_map_err(&key, value.as_ref()) //
107          .map(|tmpl| (key.into(), tmpl))
108      })
109      // .tap_dbg(|x| println!("{:?}", x.size_hint()))
110      .collect::<Result<TemplateAST, _>>()?
111      .pipe(Self)
112      .pipe(Ok)
113  }
114}