Skip to content

Commit 3e36b0d

Browse files
authored
Refactor FluentArgs (#130)
1 parent 239f5a2 commit 3e36b0d

File tree

14 files changed

+93
-88
lines changed

14 files changed

+93
-88
lines changed

fluent-bundle/benches/resolver.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,20 @@ fn get_ids(res: &FluentResource) -> Vec<String> {
3838
.collect()
3939
}
4040

41-
fn get_args(name: &str) -> Option<HashMap<String, FluentValue>> {
41+
fn get_args(name: &str) -> Option<HashMap<&str, FluentValue>> {
4242
match name {
4343
"preferences" => {
4444
let mut prefs_args = HashMap::new();
45-
prefs_args.insert("name".to_string(), FluentValue::from("John"));
46-
prefs_args.insert("tabCount".to_string(), FluentValue::from(5));
47-
prefs_args.insert("count".to_string(), FluentValue::from(3));
48-
prefs_args.insert("version".to_string(), FluentValue::from("65.0"));
49-
prefs_args.insert("path".to_string(), FluentValue::from("/tmp"));
50-
prefs_args.insert("num".to_string(), FluentValue::from(4));
51-
prefs_args.insert("email".to_string(), FluentValue::from("[email protected]"));
52-
prefs_args.insert("value".to_string(), FluentValue::from(4.5));
53-
prefs_args.insert("unit".to_string(), FluentValue::from("mb"));
54-
prefs_args.insert(
55-
"service-name".to_string(),
56-
FluentValue::from("Mozilla Disk"),
57-
);
45+
prefs_args.insert("name", FluentValue::from("John"));
46+
prefs_args.insert("tabCount", FluentValue::from(5));
47+
prefs_args.insert("count", FluentValue::from(3));
48+
prefs_args.insert("version", FluentValue::from("65.0"));
49+
prefs_args.insert("path", FluentValue::from("/tmp"));
50+
prefs_args.insert("num", FluentValue::from(4));
51+
prefs_args.insert("email", FluentValue::from("[email protected]"));
52+
prefs_args.insert("value", FluentValue::from(4.5));
53+
prefs_args.insert("unit", FluentValue::from("mb"));
54+
prefs_args.insert("service-name", FluentValue::from("Mozilla Disk"));
5855
Some(prefs_args)
5956
}
6057
_ => None,

fluent-bundle/examples/external_arguments.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use fluent_bundle::{FluentBundle, FluentResource, FluentValue};
2-
use std::collections::HashMap;
1+
use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
32
use unic_langid::langid;
43

54
fn main() {
@@ -21,8 +20,8 @@ unread-emails =
2120
.add_resource(res)
2221
.expect("Failed to add FTL resources to the bundle.");
2322

24-
let mut args = HashMap::new();
25-
args.insert("name".to_string(), FluentValue::from("John"));
23+
let mut args = FluentArgs::new();
24+
args.insert("name", FluentValue::from("John"));
2625

2726
let msg = bundle
2827
.get_message("hello-world")
@@ -38,8 +37,8 @@ unread-emails =
3837
let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
3938
println!("{}", value);
4039

41-
let mut args = HashMap::new();
42-
args.insert("emailCount".to_string(), FluentValue::into_number("1.0"));
40+
let mut args = FluentArgs::new();
41+
args.insert("emailCount", FluentValue::into_number("1.0"));
4342

4443
let msg = bundle
4544
.get_message("unread-emails")

fluent-bundle/examples/selector.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use fluent_bundle::{FluentBundle, FluentResource, FluentValue};
2-
use std::collections::HashMap;
1+
use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
32

43
fn main() {
54
let ftl_string = String::from(
@@ -29,8 +28,8 @@ hello-world2 = Hello { $name ->
2928
let value = bundle.format_pattern(&pattern, None, &mut errors);
3029
println!("{}", value);
3130

32-
let mut args = HashMap::new();
33-
args.insert("name".to_string(), FluentValue::from("moon"));
31+
let mut args = FluentArgs::new();
32+
args.insert("name", FluentValue::from("moon"));
3433

3534
let msg = bundle
3635
.get_message("hello-world2")

fluent-bundle/examples/simple-app.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
//!
1818
//! If the second argument is omitted, `en-US` locale is used as the
1919
//! default one.
20-
use fluent_bundle::{FluentBundle, FluentResource, FluentValue};
20+
use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
2121
use fluent_locale::{negotiate_languages, NegotiationStrategy};
22-
use std::collections::HashMap;
2322
use std::env;
2423
use std::fs;
2524
use std::fs::File;
@@ -130,9 +129,9 @@ fn main() {
130129
Ok(i) => {
131130
// 7.2. Construct a map of arguments
132131
// to format the message.
133-
let mut args = HashMap::new();
134-
args.insert("input".to_string(), FluentValue::from(i));
135-
args.insert("value".to_string(), FluentValue::from(collatz(i)));
132+
let mut args = FluentArgs::new();
133+
args.insert("input", FluentValue::from(i));
134+
args.insert("value", FluentValue::from(collatz(i)));
136135
// 7.3. Format the message.
137136
let mut errors = vec![];
138137
let msg = bundle
@@ -143,9 +142,9 @@ fn main() {
143142
println!("{}", value);
144143
}
145144
Err(err) => {
146-
let mut args = HashMap::new();
147-
args.insert("input".to_string(), FluentValue::from(input.as_str()));
148-
args.insert("reason".to_string(), FluentValue::from(err.to_string()));
145+
let mut args = FluentArgs::new();
146+
args.insert("input", FluentValue::from(input.as_str()));
147+
args.insert("reason", FluentValue::from(err.to_string()));
149148
let mut errors = vec![];
150149
let msg = bundle
151150
.get_message("input-parse-error")

fluent-bundle/src/bundle.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pub struct FluentMessage<'m> {
2828
pub attributes: HashMap<&'m str, &'m ast::Pattern<'m>>,
2929
}
3030

31+
pub type FluentArgs<'args> = HashMap<&'args str, FluentValue<'args>>;
32+
3133
/// A collection of localization messages for a single locale, which are meant
3234
/// to be used together in a single view, widget or any other UI abstraction.
3335
///
@@ -48,7 +50,7 @@ pub struct FluentMessage<'m> {
4850
/// .expect("Failed to add FTL resources to the bundle.");
4951
///
5052
/// let mut args = HashMap::new();
51-
/// args.insert("name".to_string(), FluentValue::from("Rustacean"));
53+
/// args.insert("name", FluentValue::from("Rustacean"));
5254
///
5355
/// let msg = bundle.get_message("intro").expect("Message doesn't exist.");
5456
/// let mut errors = vec![];
@@ -282,7 +284,7 @@ impl<R> FluentBundle<R> {
282284
pub fn format_pattern<'bundle>(
283285
&'bundle self,
284286
pattern: &'bundle ast::Pattern,
285-
args: Option<&'bundle HashMap<String, FluentValue>>,
287+
args: Option<&'bundle FluentArgs>,
286288
errors: &mut Vec<FluentError>,
287289
) -> Cow<'bundle, str>
288290
where
@@ -335,9 +337,7 @@ impl<R> FluentBundle<R> {
335337
/// [FTL syntax guide]: https://projectfluent.org/fluent/guide/functions.html
336338
pub fn add_function<F: 'static>(&mut self, id: &str, func: F) -> Result<(), FluentError>
337339
where
338-
F: for<'a> Fn(&[FluentValue<'a>], &HashMap<String, FluentValue<'a>>) -> FluentValue<'a>
339-
+ Sync
340-
+ Send,
340+
F: for<'a> Fn(&[FluentValue<'a>], &FluentArgs) -> FluentValue<'a> + Sync + Send,
341341
{
342342
match self.entries.entry(id.to_owned()) {
343343
HashEntry::Vacant(entry) => {

fluent-bundle/src/entry.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
//! `Entry` is used to store Messages, Terms and Functions in `FluentBundle` instances.
22
33
use std::borrow::Borrow;
4-
use std::collections::HashMap;
54

65
use fluent_syntax::ast;
76

8-
use crate::bundle::FluentBundle;
7+
use crate::bundle::{FluentArgs, FluentBundle};
98
use crate::resource::FluentResource;
109
use crate::types::FluentValue;
1110

12-
pub type FluentFunction = Box<
13-
dyn for<'a> Fn(&[FluentValue<'a>], &HashMap<String, FluentValue<'a>>) -> FluentValue<'a>
14-
+ Send
15-
+ Sync,
16-
>;
11+
pub type FluentFunction =
12+
Box<dyn for<'a> Fn(&[FluentValue<'a>], &FluentArgs) -> FluentValue<'a> + Send + Sync>;
1713

1814
pub enum Entry {
1915
Message([usize; 2]),

fluent-bundle/src/lib.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
//! # Example
1212
//!
1313
//! ```
14-
//! use fluent_bundle::{FluentBundle, FluentValue, FluentResource};
15-
//! use std::collections::HashMap;
14+
//! use fluent_bundle::{FluentBundle, FluentValue, FluentResource, FluentArgs};
1615
//! use unic_langid::langid;
1716
//!
1817
//! let ftl_string = String::from("
@@ -36,8 +35,8 @@
3635
//!
3736
//! assert_eq!(&value, "Hello, world!");
3837
//!
39-
//! let mut args = HashMap::new();
40-
//! args.insert("name".to_string(), FluentValue::from("John"));
38+
//! let mut args = FluentArgs::new();
39+
//! args.insert("name", FluentValue::from("John"));
4140
//!
4241
//! let msg = bundle.get_message("intro").expect("Message doesn't exist.");
4342
//! let mut errors = vec![];
@@ -59,6 +58,6 @@ pub mod resolve;
5958
pub mod resource;
6059
pub mod types;
6160

62-
pub use bundle::FluentBundle;
61+
pub use bundle::{FluentArgs, FluentBundle, FluentMessage};
6362
pub use resource::FluentResource;
6463
pub use types::FluentValue;

fluent-bundle/src/resolve.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
//! [`FluentBundle`]: ../bundle/struct.FluentBundle.html
88
99
use std::borrow::Borrow;
10-
use std::collections::HashMap;
1110
use std::fmt::Write;
1211

1312
use fluent_syntax::ast;
1413
use fluent_syntax::unicode::unescape_unicode;
1514

16-
use crate::bundle::FluentBundle;
15+
use crate::bundle::{FluentArgs, FluentBundle};
1716
use crate::entry::GetEntry;
1817
use crate::resource::FluentResource;
1918
use crate::types::DisplayableNode;
@@ -31,20 +30,17 @@ pub struct Scope<'bundle, R: Borrow<FluentResource>> {
3130
/// The current `FluentBundle` instance.
3231
pub bundle: &'bundle FluentBundle<R>,
3332
/// The current arguments passed by the developer.
34-
args: Option<&'bundle HashMap<String, FluentValue<'bundle>>>,
33+
args: Option<&'bundle FluentArgs<'bundle>>,
3534
/// Local args
36-
local_args: Option<HashMap<String, FluentValue<'bundle>>>,
35+
local_args: Option<FluentArgs<'bundle>>,
3736
/// Tracks hashes to prevent infinite recursion.
3837
travelled: smallvec::SmallVec<[&'bundle ast::Pattern<'bundle>; 2]>,
3938
/// Track errors accumulated during resolving.
4039
pub errors: Vec<ResolverError>,
4140
}
4241

4342
impl<'bundle, R: Borrow<FluentResource>> Scope<'bundle, R> {
44-
pub fn new(
45-
bundle: &'bundle FluentBundle<R>,
46-
args: Option<&'bundle HashMap<String, FluentValue>>,
47-
) -> Self {
43+
pub fn new(bundle: &'bundle FluentBundle<R>, args: Option<&'bundle FluentArgs>) -> Self {
4844
Scope {
4945
bundle,
5046
args,
@@ -281,23 +277,20 @@ impl<'source> ResolveValue<'source> for ast::InlineExpression<'source> {
281277
fn get_arguments<'bundle, R>(
282278
scope: &mut Scope<'bundle, R>,
283279
arguments: &'bundle Option<ast::CallArguments<'bundle>>,
284-
) -> (
285-
Vec<FluentValue<'bundle>>,
286-
HashMap<String, FluentValue<'bundle>>,
287-
)
280+
) -> (Vec<FluentValue<'bundle>>, FluentArgs<'bundle>)
288281
where
289282
R: Borrow<FluentResource>,
290283
{
291284
let mut resolved_positional_args = Vec::new();
292-
let mut resolved_named_args = HashMap::new();
285+
let mut resolved_named_args = FluentArgs::new();
293286

294287
if let Some(ast::CallArguments { named, positional }) = arguments {
295288
for expression in positional {
296289
resolved_positional_args.push(expression.resolve(scope));
297290
}
298291

299292
for arg in named {
300-
resolved_named_args.insert(arg.name.name.to_string(), arg.value.resolve(scope));
293+
resolved_named_args.insert(arg.name.name, arg.value.resolve(scope));
301294
}
302295
}
303296

fluent-bundle/tests/resolver_fixtures.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::iter;
66
use std::path::Path;
77
use std::str::FromStr;
88

9+
use fluent_bundle::bundle::FluentArgs;
910
use fluent_bundle::errors::FluentError;
1011
use fluent_bundle::resolve::ResolverError;
1112
use fluent_bundle::{FluentBundle as FluentBundleGeneric, FluentResource, FluentValue};
@@ -264,14 +265,14 @@ fn test_test(test: &Test, defaults: &Option<TestDefaults>, mut scope: Scope) {
264265
))
265266
};
266267

267-
let args: Option<HashMap<String, FluentValue>> = assert.args.as_ref().map(|args| {
268+
let args: Option<FluentArgs> = assert.args.as_ref().map(|args| {
268269
args.iter()
269270
.map(|(k, v)| {
270271
let val = match f64::from_str(v) {
271272
Ok(_) => FluentValue::Number(v.into()),
272273
Err(_) => FluentValue::String(v.into()),
273274
};
274-
(k.to_string(), val)
275+
(k.as_str(), val)
275276
})
276277
.collect()
277278
});

fluent-fallback/examples/simple-fallback.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@
1818
//! If the second argument is omitted, `en-US` locale is used as the
1919
//! default one.
2020
use elsa::FrozenMap;
21-
use fluent_bundle::{FluentBundle, FluentResource, FluentValue};
21+
use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
2222
use fluent_fallback::Localization;
2323
use fluent_locale::{negotiate_languages, NegotiationStrategy};
24-
use std::collections::HashMap;
2524
use std::env;
2625
use std::fs;
2726
use std::fs::File;
@@ -139,17 +138,17 @@ fn main() {
139138
Ok(i) => {
140139
// 7.2. Construct a map of arguments
141140
// to format the message.
142-
let mut args = HashMap::new();
143-
args.insert("input".to_string(), FluentValue::from(i));
144-
args.insert("value".to_string(), FluentValue::from(collatz(i)));
141+
let mut args = FluentArgs::new();
142+
args.insert("input", FluentValue::from(i));
143+
args.insert("value", FluentValue::from(collatz(i)));
145144
// 7.3. Format the message.
146145
let value = loc.format_value("response-msg", Some(&args));
147146
println!("{}", value);
148147
}
149148
Err(err) => {
150-
let mut args = HashMap::new();
151-
args.insert("input".to_string(), FluentValue::from(input.as_str()));
152-
args.insert("reason".to_string(), FluentValue::from(err.to_string()));
149+
let mut args = FluentArgs::new();
150+
args.insert("input", FluentValue::from(input.as_str()));
151+
args.insert("reason", FluentValue::from(err.to_string()));
153152
let value = loc.format_value("input-parse-error-msg", Some(&args));
154153
println!("{}", value);
155154
}

fluent-fallback/src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use std::borrow::Borrow;
2-
use std::collections::HashMap;
32

4-
use fluent_bundle::FluentBundle;
53
use fluent_bundle::FluentResource;
6-
use fluent_bundle::FluentValue;
4+
use fluent_bundle::{FluentArgs, FluentBundle};
75

86
use reiterate::Reiterate;
97

@@ -45,7 +43,7 @@ impl<'loc, R> Localization<'loc, R> {
4543
self.bundles = Reiterate::new((self.generate_bundles)(&self.resource_ids));
4644
}
4745

48-
pub fn format_value(&mut self, id: &str, args: Option<&HashMap<String, FluentValue>>) -> String
46+
pub fn format_value(&mut self, id: &str, args: Option<&FluentArgs>) -> String
4947
where
5048
R: Borrow<FluentResource>,
5149
{

fluent-resmgr/examples/simple-resmgr.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
//!
1818
//! If the second argument is omitted, `en-US` locale is used as the
1919
//! default one.
20-
use fluent_bundle::FluentValue;
20+
use fluent_bundle::{FluentArgs, FluentValue};
2121
use fluent_locale::{negotiate_languages, NegotiationStrategy};
2222
use fluent_resmgr::resource_manager::ResourceManager;
23-
use std::collections::HashMap;
2423
use std::env;
2524
use std::fs;
2625
use std::io;
@@ -94,9 +93,9 @@ fn main() {
9493
Ok(i) => {
9594
// 6.2. Construct a map of arguments
9695
// to format the message.
97-
let mut args = HashMap::new();
98-
args.insert("input".to_string(), FluentValue::from(i));
99-
args.insert("value".to_string(), FluentValue::from(collatz(i)));
96+
let mut args = FluentArgs::new();
97+
args.insert("input", FluentValue::from(i));
98+
args.insert("value", FluentValue::from(collatz(i)));
10099
// 6.3. Format the message.
101100
let mut errors = vec![];
102101
let msg = bundle.get_message("response-msg").expect("Message exists");
@@ -105,9 +104,9 @@ fn main() {
105104
println!("{}", value);
106105
}
107106
Err(err) => {
108-
let mut args = HashMap::new();
109-
args.insert("input".to_string(), FluentValue::from(input.to_string()));
110-
args.insert("reason".to_string(), FluentValue::from(err.to_string()));
107+
let mut args = FluentArgs::new();
108+
args.insert("input", FluentValue::from(input.to_string()));
109+
args.insert("reason", FluentValue::from(err.to_string()));
111110
let mut errors = vec![];
112111
let msg = bundle
113112
.get_message("input-parse-error-msg")

0 commit comments

Comments
 (0)