1//! `Entry` is used to store the lookup information for Messages, Terms and Functions in
2//! `FluentBundle` instances.
3
4use std::borrow::Borrow;
5
6use fluent_syntax::ast;
7
8use crate::args::FluentArgs;
9use crate::bundle::FluentBundle;
10use crate::resource::FluentResource;
11use crate::types::FluentValue;
12
13pub type FluentFunction =
14 Box<dyn for<'a> dynFn(&[FluentValue<'a>], &FluentArgs) -> FluentValue<'a> + Send + Sync>;
15
16type ResourceIdx = usize;
17type EntryIdx = usize;
18
19/// The [`Entry`] stores indexes into the [`FluentBundle`]'s resources for Messages and Terms,
20/// and owns the [`Box`] pointers to the [`FluentFunction`].
21pub enum Entry {
22 Message((ResourceIdx, EntryIdx)),
23 Term((ResourceIdx, EntryIdx)),
24 Function(FluentFunction),
25}
26
27pub trait GetEntry {
28 /// Looks up a message by its string ID, and returns it if it exists.
29 fn get_entry_message(&self, id: &str) -> Option<&ast::Message<&str>>;
30
31 /// Looks up a term by its string ID, and returns it if it exists.
32 fn get_entry_term(&self, id: &str) -> Option<&ast::Term<&str>>;
33
34 /// Looks up a function by its string ID, and returns it if it exists.
35 fn get_entry_function(&self, id: &str) -> Option<&FluentFunction>;
36}
37
38impl<R: Borrow<FluentResource>, M> GetEntry for FluentBundle<R, M> {
39 fn get_entry_message(&self, id: &str) -> Option<&ast::Message<&str>> {
40 self.entries.get(id).and_then(|ref entry| match entry {
41 Entry::Message((resource_idx, entry_idx)) => {
42 let res = self.resources.get(*resource_idx)?.borrow();
43 if let ast::Entry::Message(ref msg) = res.get_entry(*entry_idx)? {
44 Some(msg)
45 } else {
46 None
47 }
48 }
49 _ => None,
50 })
51 }
52
53 fn get_entry_term(&self, id: &str) -> Option<&ast::Term<&str>> {
54 self.entries.get(id).and_then(|ref entry| match entry {
55 Entry::Term((resource_idx, entry_idx)) => {
56 let res = self.resources.get(*resource_idx)?.borrow();
57 if let ast::Entry::Term(ref msg) = res.get_entry(*entry_idx)? {
58 Some(msg)
59 } else {
60 None
61 }
62 }
63 _ => None,
64 })
65 }
66
67 fn get_entry_function(&self, id: &str) -> Option<&FluentFunction> {
68 self.entries.get(id).and_then(|ref entry| match entry {
69 Entry::Function(function) => Some(function),
70 _ => None,
71 })
72 }
73}
74