1use std::borrow::Cow;
2use std::iter::FromIterator;
3
4use crate::types::FluentValue;
5
6#[derive(Debug, Default)]
56pub struct FluentArgs<'args>(Vec<(Cow<'args, str>, FluentValue<'args>)>);
57
58impl<'args> FluentArgs<'args> {
59 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn with_capacity(capacity: usize) -> Self {
66 Self(Vec::with_capacity(capacity))
67 }
68
69 pub fn get<K>(&self, key: K) -> Option<&FluentValue<'args>>
71 where
72 K: Into<Cow<'args, str>>,
73 {
74 let key = key.into();
75 if let Ok(idx) = self.0.binary_search_by_key(&&key, |(k, _)| k) {
76 Some(&self.0[idx].1)
77 } else {
78 None
79 }
80 }
81
82 pub fn set<K, V>(&mut self, key: K, value: V)
84 where
85 K: Into<Cow<'args, str>>,
86 V: Into<FluentValue<'args>>,
87 {
88 let key = key.into();
89 match self.0.binary_search_by_key(&&key, |(k, _)| k) {
90 Ok(idx) => self.0[idx] = (key, value.into()),
91 Err(idx) => self.0.insert(idx, (key, value.into())),
92 };
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = (&str, &FluentValue)> {
97 self.0.iter().map(|(k, v)| (k.as_ref(), v))
98 }
99}
100
101impl<'args, K, V> FromIterator<(K, V)> for FluentArgs<'args>
102where
103 K: Into<Cow<'args, str>>,
104 V: Into<FluentValue<'args>>,
105{
106 fn from_iter<I>(iter: I) -> Self
107 where
108 I: IntoIterator<Item = (K, V)>,
109 {
110 let iter = iter.into_iter();
111 let mut args = if let Some(size) = iter.size_hint().1 {
112 FluentArgs::with_capacity(size)
113 } else {
114 FluentArgs::new()
115 };
116
117 for (k, v) in iter {
118 args.set(k, v);
119 }
120
121 args
122 }
123}
124
125impl<'args> IntoIterator for FluentArgs<'args> {
126 type Item = (Cow<'args, str>, FluentValue<'args>);
127 type IntoIter = std::vec::IntoIter<Self::Item>;
128
129 fn into_iter(self) -> Self::IntoIter {
130 self.0.into_iter()
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn replace_existing_arguments() {
140 let mut args = FluentArgs::new();
141
142 args.set("name", "John");
143 args.set("emailCount", 5);
144 assert_eq!(args.0.len(), 2);
145 assert_eq!(
146 args.get("name"),
147 Some(&FluentValue::String(Cow::Borrowed("John")))
148 );
149 assert_eq!(args.get("emailCount"), Some(&FluentValue::try_number("5")));
150
151 args.set("name", "Jane");
152 args.set("emailCount", 7);
153 assert_eq!(args.0.len(), 2);
154 assert_eq!(
155 args.get("name"),
156 Some(&FluentValue::String(Cow::Borrowed("Jane")))
157 );
158 assert_eq!(args.get("emailCount"), Some(&FluentValue::try_number("7")));
159 }
160}