1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
use crate::{lang, Currency, Lang, Language, Number, Output};
/// Error type returned by the builder
#[derive(Debug, PartialEq)]
pub enum Num2Err {
/// General error, language cannot convert number
CannotConvert,
/// Request of a negative ordinal
///
/// Example:
/// ```
/// use num2words::{Num2Err, Num2Words};
/// assert_eq!(
/// Num2Words::new(-42).ordinal().to_words(),
/// Err(Num2Err::NegativeOrdinal)
/// );
/// ```
NegativeOrdinal,
/// Request of a float ordinal
///
/// Example:
/// ```
/// use num2words::{Num2Err, Num2Words};
/// assert_eq!(
/// Num2Words::new(42.01).ordinal().to_words(),
/// Err(Num2Err::FloatingOrdinal)
/// );
/// ```
FloatingOrdinal,
/// Request of a float year
///
/// Example:
/// ```
/// use num2words::{Num2Err, Num2Words};
/// assert_eq!(
/// Num2Words::new(42.01).year().to_words(),
/// Err(Num2Err::FloatingYear)
/// );
/// ```
FloatingYear,
}
impl std::fmt::Display for Num2Err {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Num2Err::CannotConvert => "cannot convert number",
Num2Err::NegativeOrdinal => "cannot treat negative number as ordinal",
Num2Err::FloatingOrdinal => "cannot treat float as ordinal",
Num2Err::FloatingYear => "cannot treat float as year",
}
)
}
}
/// Builder for `num2words`
pub struct Num2Words {
num: Number,
lang: Lang,
output: Output,
currency: Currency,
}
impl Num2Words {
/// Creates a new builder
///
/// Example:
/// ```
/// use num2words::Num2Words;
/// assert_eq!(
/// Num2Words::new(42).to_words(),
/// Ok(String::from("forty-two"))
/// );
/// ```
pub fn new<T>(num: T) -> Self
where
T: Into<Number>,
{
Self {
num: num.into(),
lang: Lang::English,
output: Output::Cardinal,
currency: Currency::DOLLAR,
}
}
/// Sets the language of the output
///
/// For all of the available languages, see [`Lang`].
///
/// Example:
/// ```
/// use num2words::{Num2Words, Lang};
/// assert_eq!(
/// Num2Words::new(42).lang(Lang::English).to_words(),
/// Ok(String::from("forty-two"))
/// );
/// ```
pub fn lang(mut self, lang: Lang) -> Self {
self.lang = lang;
self
}
/// Sets the type of output to cardinal (`forty-two`)
///
/// Example:
/// ```
/// use num2words::Num2Words;
/// assert_eq!(
/// Num2Words::new(42).cardinal().to_words(),
/// Ok(String::from("forty-two"))
/// );
/// ```
pub fn cardinal(mut self) -> Self {
self.output = Output::Cardinal;
self
}
/// Sets the type of output to ordinal (`forty-second`)
///
/// Example:
/// ```
/// use num2words::Num2Words;
/// assert_eq!(
/// Num2Words::new(42).ordinal().to_words(),
/// Ok(String::from("forty-second"))
/// );
/// ```
pub fn ordinal(mut self) -> Self {
self.output = Output::Ordinal;
self
}
/// Sets the type of output to numbered ordinal (`42nd`)
///
/// Example:
/// ```
/// use num2words::Num2Words;
/// assert_eq!(
/// Num2Words::new(42).ordinal_num().to_words(),
/// Ok(String::from("42nd"))
/// );
/// ```
pub fn ordinal_num(mut self) -> Self {
self.output = Output::OrdinalNum;
self
}
/// Sets the type of output to year (`nineteen oh-one`)
///
/// Example:
/// ```
/// use num2words::Num2Words;
/// assert_eq!(
/// Num2Words::new(1901).year().to_words(),
/// Ok(String::from("nineteen oh-one"))
/// );
/// ```
pub fn year(mut self) -> Self {
self.output = Output::Year;
self
}
/// Sets the output to the currency it has been given
///
/// For all of the available currencies, see [`Currency`].
///
/// Example:
/// ```
/// use num2words::{Num2Words, Currency};
/// assert_eq!(
/// Num2Words::new(42.01).currency(Currency::DOLLAR).to_words(),
/// Ok(String::from("forty-two dollars and one cent"))
/// );
/// ```
pub fn currency(mut self, currency: Currency) -> Self {
self.output = Output::Currency;
self.currency = currency;
self
}
/// Builds the output
pub fn to_words(self) -> Result<String, Num2Err> {
let lang = lang::to_language(self.lang);
match self.output {
Output::Cardinal => lang.to_cardinal(self.num),
Output::Currency => lang.to_currency(self.num, self.currency),
Output::Ordinal => {
if let Number::Int(n) = self.num {
if n < 0 {
Err(Num2Err::NegativeOrdinal)
} else {
lang.to_ordinal(self.num)
}
} else {
Err(Num2Err::FloatingOrdinal)
}
}
Output::OrdinalNum => {
if let Number::Int(n) = self.num {
if n < 0 {
Err(Num2Err::NegativeOrdinal)
} else {
lang.to_ordinal_num(self.num)
}
} else {
Err(Num2Err::FloatingOrdinal)
}
}
Output::Year => lang.to_year(self.num),
}
}
}