use std::collections::HashMap;
use std::fmt;
use super::{Format, MessagePart};
use super::english_cardinal_classifier;
use {Args, Message};
#[derive(Clone,Copy,Debug,PartialEq)]
pub enum PluralCategory {
Zero,
One,
Two,
Few,
Many,
Other,
}
pub struct PluralFormat {
#[allow(dead_code)]
variable_name: String,
classifier: fn(i64) -> PluralCategory,
literals: HashMap<i64, Message>,
offset: i64,
zero: Option<Message>,
one: Option<Message>,
two: Option<Message>,
few: Option<Message>,
many: Option<Message>,
other: Message,
}
impl PluralFormat {
pub fn new(variable_name: &str, other: Message) -> Self {
PluralFormat {
variable_name: variable_name.to_string(),
classifier: english_cardinal_classifier,
literals: HashMap::new(),
offset: 0,
zero: None,
one: None,
two: None,
few: None,
many: None,
other: other,
}
}
pub fn literal(mut self, literal: i64, message: Message) -> Self {
self.literals.insert(literal, message);
self
}
pub fn offset(mut self, offset: i64) -> Self {
self.offset = offset;
self
}
pub fn zero(mut self, message: Message) -> Self {
self.zero = Some(message);
self
}
pub fn one(mut self, message: Message) -> Self {
self.one = Some(message);
self
}
pub fn two(mut self, message: Message) -> Self {
self.two = Some(message);
self
}
pub fn few(mut self, message: Message) -> Self {
self.few = Some(message);
self
}
pub fn many(mut self, message: Message) -> Self {
self.many = Some(message);
self
}
fn format_from_classifier(&self, offset_value: i64) -> &Message {
let category = (self.classifier)(offset_value);
match category {
PluralCategory::Zero => self.zero.as_ref().unwrap_or(&self.other),
PluralCategory::One => self.one.as_ref().unwrap_or(&self.other),
PluralCategory::Two => self.two.as_ref().unwrap_or(&self.other),
PluralCategory::Few => self.few.as_ref().unwrap_or(&self.other),
PluralCategory::Many => self.many.as_ref().unwrap_or(&self.other),
PluralCategory::Other => &self.other,
}
}
fn format_plural_message(&self,
stream: &mut fmt::Write,
message: &Message,
offset_value: i64,
args: &Args)
-> fmt::Result {
for part in &message.message_parts {
match *part {
MessagePart::String(ref string) => {
try!(write!(stream, "{}", string));
}
MessagePart::Placeholder => {
try!(write!(stream, "{}", offset_value));
}
MessagePart::Format(ref format) => try!(format.format_message_part(stream, args)),
}
}
Ok(())
}
}
impl Format for PluralFormat {
fn format_message_part(&self, stream: &mut fmt::Write, args: &Args) -> fmt::Result {
let value = 0;
let offset_value = value - self.offset;
let message = if !self.literals.is_empty() {
if let Some(literal) = self.literals.get(&offset_value) {
literal
} else {
self.format_from_classifier(offset_value)
}
} else {
self.format_from_classifier(offset_value)
};
try!(self.format_plural_message(stream, message, offset_value, args));
Ok(())
}
}