Skip to main content

uritemplate/
templatevar.rs

1use std::collections::HashMap;
2
3/// TemplateVar represents the value of a template variable, which can be a
4/// scalar (a simple string), a list of strings, or an associative array of
5/// strings.
6///
7/// Normally, it is not necessary to use this class unless you are implementing
8/// the `IntoTemplateVar` trait for your own classes.
9#[derive(Clone)]
10pub enum TemplateVar {
11    /// A simple string such as `"foo"`
12    Scalar(String),
13    /// A list of strings such as `["foo", "bar"]`
14    List(Vec<String>),
15    /// An associative array of strings, such as
16    /// `[("key1", "value1"), ("key2", "value2")]`
17    AssociativeArray(Vec<(String, String)>),
18}
19
20/// IntoTemplateVar represents any type that can be converted into a TemplateVar
21/// for use as the value of a template variable, such as a `String`,
22/// `Vec<String>`, or `Vec<(String, String)>`. Default implementations are
23/// available for those three types, as well as the `&str` versions.
24///
25/// Example
26/// -------
27/// Here is an example of implementing `IntoTemplateVar` for your own `Address`
28/// struct. Note that you should probably implement the trait for a reference to
29/// your struct, not the actual struct, unless you intend to move the value
30/// efficiently.
31///
32/// ```ignore
33/// struct Address {
34///     city: String,
35///     state: String
36/// }
37///
38/// impl <'a> IntoTemplateVar for &'a Address {
39///     fn into_template_var(self) -> TemplateVar {
40///         TemplateVar::AssociativeArray(vec![
41///             ("city".to_string(), self.city.clone()),
42///             ("state".to_string(), self.state.clone())
43///         ])
44///     }
45/// }
46/// ```
47///
48/// Now, `Address` variables can be set as `UriTemplate` variables.
49///
50/// ```ignore
51/// let address = Address {
52///     city: "Los Angelos".to_string(),
53///     state: "California".to_string()
54/// };
55///
56/// let uri = UriTemplate::new("http://example.com/view{?address*}")
57///     .set("address", &address)
58///     .build();
59///
60/// assert_eq!(
61///     uri,
62///     "http://example.com/view?city=Los%20Angelos&state=California"
63/// );
64/// ```
65pub trait IntoTemplateVar {
66    fn into_template_var(self) -> TemplateVar;
67}
68
69impl IntoTemplateVar for TemplateVar {
70    fn into_template_var(self) -> TemplateVar {
71        self.clone()
72    }
73}
74
75impl<'a> IntoTemplateVar for &'a str {
76    fn into_template_var(self) -> TemplateVar {
77        TemplateVar::Scalar(self.to_string())
78    }
79}
80
81impl IntoTemplateVar for String {
82    fn into_template_var(self) -> TemplateVar {
83        TemplateVar::Scalar(self)
84    }
85}
86
87impl<'a> IntoTemplateVar for &'a [String] {
88    fn into_template_var(self) -> TemplateVar {
89        let mut vec = Vec::new();
90        for s in self {
91            vec.push(s.clone());
92        }
93        TemplateVar::List(vec)
94    }
95}
96
97impl IntoTemplateVar for Vec<String> {
98    fn into_template_var(self) -> TemplateVar {
99        TemplateVar::List(self)
100    }
101}
102
103impl<'a, 'b> IntoTemplateVar for &'a [&'b str] {
104    fn into_template_var(self) -> TemplateVar {
105        let mut vec = Vec::new();
106        for s in self {
107            vec.push(s.to_string());
108        }
109        TemplateVar::List(vec)
110    }
111}
112
113impl<'a> IntoTemplateVar for &'a [(String, String)] {
114    fn into_template_var(self) -> TemplateVar {
115        let mut vec = Vec::new();
116        for s in self {
117            vec.push(s.clone());
118        }
119        TemplateVar::AssociativeArray(vec)
120    }
121}
122
123impl IntoTemplateVar for Vec<(String, String)> {
124    fn into_template_var(self) -> TemplateVar {
125        TemplateVar::AssociativeArray(self)
126    }
127}
128
129impl<'a, 'b, 'c> IntoTemplateVar for &'a [(&'b str, &'c str)] {
130    fn into_template_var(self) -> TemplateVar {
131        let mut vec = Vec::new();
132        for s in self {
133            vec.push((s.0.to_string(), s.1.to_string()));
134        }
135        TemplateVar::AssociativeArray(vec)
136    }
137}
138
139impl<'a> IntoTemplateVar for &'a HashMap<String, String> {
140    fn into_template_var(self) -> TemplateVar {
141        let mut vec = Vec::new();
142        for (k, v) in self {
143            vec.push((k.clone(), v.clone()));
144        }
145        TemplateVar::AssociativeArray(vec)
146    }
147}
148
149impl<'a, 'b, 'c> IntoTemplateVar for &'a HashMap<&'b str, &'c str> {
150    fn into_template_var(self) -> TemplateVar {
151        let mut vec = Vec::new();
152        for (k, v) in self {
153            vec.push((k.to_string(), v.to_string()));
154        }
155        TemplateVar::AssociativeArray(vec)
156    }
157}
158
159macro_rules! array_impls {
160    ($($N:expr)+) => {$(
161        impl <'a> IntoTemplateVar for &'a [String; $N] {
162            fn into_template_var(self) -> TemplateVar {
163                self[..].into_template_var()
164            }
165        }
166
167        impl <'a, 'b> IntoTemplateVar for &'a[&'b str; $N] {
168            fn into_template_var(self) -> TemplateVar {
169                self[..].into_template_var()
170            }
171        }
172
173        impl <'a> IntoTemplateVar for &'a [(String, String); $N] {
174            fn into_template_var(self) -> TemplateVar {
175                self[..].into_template_var()
176            }
177        }
178
179        impl <'a, 'b, 'c> IntoTemplateVar for &'a[(&'b str, &'c str); $N] {
180            fn into_template_var(self) -> TemplateVar {
181                self[..].into_template_var()
182            }
183        }
184    )+}
185}
186
187array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
188    26 27 28 29 30 31 32);