1 | use std::borrow::Cow; |
2 | use std::iter::FromIterator; |
3 | |
4 | use crate::types::FluentValue; |
5 | |
6 | /// A map of arguments passed from the code to |
7 | /// the localization to be used for message |
8 | /// formatting. |
9 | /// |
10 | /// # Example |
11 | /// |
12 | /// ``` |
13 | /// use fluent_bundle::{FluentArgs, FluentBundle, FluentResource}; |
14 | /// |
15 | /// let mut args = FluentArgs::new(); |
16 | /// args.set("user" , "John" ); |
17 | /// args.set("emailCount" , 5); |
18 | /// |
19 | /// let res = FluentResource::try_new(r#" |
20 | /// |
21 | /// msg-key = Hello, { $user }. You have { $emailCount } messages. |
22 | /// |
23 | /// "# .to_string()) |
24 | /// .expect("Failed to parse FTL." ); |
25 | /// |
26 | /// let mut bundle = FluentBundle::default(); |
27 | /// |
28 | /// // For this example, we'll turn on BiDi support. |
29 | /// // Please, be careful when doing it, it's a risky move. |
30 | /// bundle.set_use_isolating(false); |
31 | /// |
32 | /// bundle.add_resource(res) |
33 | /// .expect("Failed to add a resource." ); |
34 | /// |
35 | /// let mut err = vec![]; |
36 | /// |
37 | /// let msg = bundle.get_message("msg-key" ) |
38 | /// .expect("Failed to retrieve a message." ); |
39 | /// let value = msg.value() |
40 | /// .expect("Failed to retrieve a value." ); |
41 | /// |
42 | /// assert_eq!( |
43 | /// bundle.format_pattern(value, Some(&args), &mut err), |
44 | /// "Hello, John. You have 5 messages." |
45 | /// ); |
46 | /// ``` |
47 | #[derive (Debug, Default)] |
48 | pub struct FluentArgs<'args>(Vec<(Cow<'args, str>, FluentValue<'args>)>); |
49 | |
50 | impl<'args> FluentArgs<'args> { |
51 | pub fn new() -> Self { |
52 | Self::default() |
53 | } |
54 | |
55 | pub fn with_capacity(capacity: usize) -> Self { |
56 | Self(Vec::with_capacity(capacity)) |
57 | } |
58 | |
59 | pub fn get<K>(&self, key: K) -> Option<&FluentValue<'args>> |
60 | where |
61 | K: Into<Cow<'args, str>>, |
62 | { |
63 | let key = key.into(); |
64 | if let Ok(idx) = self.0.binary_search_by_key(&&key, |(k, _)| k) { |
65 | Some(&self.0[idx].1) |
66 | } else { |
67 | None |
68 | } |
69 | } |
70 | |
71 | pub fn set<K, V>(&mut self, key: K, value: V) |
72 | where |
73 | K: Into<Cow<'args, str>>, |
74 | V: Into<FluentValue<'args>>, |
75 | { |
76 | let key = key.into(); |
77 | let idx = match self.0.binary_search_by_key(&&key, |(k, _)| k) { |
78 | Ok(idx) => idx, |
79 | Err(idx) => idx, |
80 | }; |
81 | self.0.insert(idx, (key, value.into())); |
82 | } |
83 | |
84 | pub fn iter(&self) -> impl Iterator<Item = (&str, &FluentValue)> { |
85 | self.0.iter().map(|(k, v)| (k.as_ref(), v)) |
86 | } |
87 | } |
88 | |
89 | impl<'args, K, V> FromIterator<(K, V)> for FluentArgs<'args> |
90 | where |
91 | K: Into<Cow<'args, str>>, |
92 | V: Into<FluentValue<'args>>, |
93 | { |
94 | fn from_iter<I>(iter: I) -> Self |
95 | where |
96 | I: IntoIterator<Item = (K, V)>, |
97 | { |
98 | let iter: ::IntoIter = iter.into_iter(); |
99 | let mut args: FluentArgs<'_> = if let Some(size: usize) = iter.size_hint().1 { |
100 | FluentArgs::with_capacity(size) |
101 | } else { |
102 | FluentArgs::new() |
103 | }; |
104 | |
105 | for (k: K, v: V) in iter { |
106 | args.set(key:k, value:v); |
107 | } |
108 | |
109 | args |
110 | } |
111 | } |
112 | |
113 | impl<'args> IntoIterator for FluentArgs<'args> { |
114 | type Item = (Cow<'args, str>, FluentValue<'args>); |
115 | type IntoIter = std::vec::IntoIter<Self::Item>; |
116 | |
117 | fn into_iter(self) -> Self::IntoIter { |
118 | self.0.into_iter() |
119 | } |
120 | } |
121 | |