message_format/ast/
plural_format.rs1use std::collections::HashMap;
8use std::fmt;
9
10use super::{Format, MessagePart};
11use super::english_cardinal_classifier;
12use {Args, Message};
13
14#[derive(Clone,Copy,Debug,PartialEq)]
18pub enum PluralCategory {
19 Zero,
21 One,
23 Two,
25 Few,
28 Many,
31 Other,
34}
35
36pub struct PluralFormat {
38 #[allow(dead_code)]
40 variable_name: String,
41 classifier: fn(i64) -> PluralCategory,
42 literals: HashMap<i64, Message>,
43 offset: i64,
44 zero: Option<Message>,
45 one: Option<Message>,
46 two: Option<Message>,
47 few: Option<Message>,
48 many: Option<Message>,
49 other: Message,
50}
51
52impl PluralFormat {
53 pub fn new(variable_name: &str, other: Message) -> Self {
55 PluralFormat {
56 variable_name: variable_name.to_string(),
57 classifier: english_cardinal_classifier,
58 literals: HashMap::new(),
59 offset: 0,
60 zero: None,
61 one: None,
62 two: None,
63 few: None,
64 many: None,
65 other: other,
66 }
67 }
68
69 pub fn literal(mut self, literal: i64, message: Message) -> Self {
71 self.literals.insert(literal, message);
72 self
73 }
74
75 pub fn offset(mut self, offset: i64) -> Self {
77 self.offset = offset;
78 self
79 }
80
81 pub fn zero(mut self, message: Message) -> Self {
83 self.zero = Some(message);
84 self
85 }
86
87 pub fn one(mut self, message: Message) -> Self {
89 self.one = Some(message);
90 self
91 }
92
93 pub fn two(mut self, message: Message) -> Self {
95 self.two = Some(message);
96 self
97 }
98
99 pub fn few(mut self, message: Message) -> Self {
101 self.few = Some(message);
102 self
103 }
104
105 pub fn many(mut self, message: Message) -> Self {
107 self.many = Some(message);
108 self
109 }
110
111 fn format_from_classifier(&self, offset_value: i64) -> &Message {
113 let category = (self.classifier)(offset_value);
114 match category {
115 PluralCategory::Zero => self.zero.as_ref().unwrap_or(&self.other),
116 PluralCategory::One => self.one.as_ref().unwrap_or(&self.other),
117 PluralCategory::Two => self.two.as_ref().unwrap_or(&self.other),
118 PluralCategory::Few => self.few.as_ref().unwrap_or(&self.other),
119 PluralCategory::Many => self.many.as_ref().unwrap_or(&self.other),
120 PluralCategory::Other => &self.other,
121 }
122 }
123
124 fn format_plural_message(&self,
127 stream: &mut fmt::Write,
128 message: &Message,
129 offset_value: i64,
130 args: &Args)
131 -> fmt::Result {
132 for part in &message.message_parts {
133 match *part {
134 MessagePart::String(ref string) => {
135 try!(write!(stream, "{}", string));
136 }
137 MessagePart::Placeholder => {
138 try!(write!(stream, "{}", offset_value));
139 }
140 MessagePart::Format(ref format) => try!(format.format_message_part(stream, args)),
141 }
142 }
143 Ok(())
144 }
145}
146
147impl Format for PluralFormat {
148 fn format_message_part(&self, stream: &mut fmt::Write, args: &Args) -> fmt::Result {
149 let value = 0;
150 let offset_value = value - self.offset;
151 let message = if !self.literals.is_empty() {
152 if let Some(literal) = self.literals.get(&offset_value) {
153 literal
154 } else {
155 self.format_from_classifier(offset_value)
156 }
157 } else {
158 self.format_from_classifier(offset_value)
159 };
160 try!(self.format_plural_message(stream, message, offset_value, args));
161 Ok(())
162 }
163}