use core::fmt::{self, Display}; /// Describes how a TOML integer should be formatted. /// /// # Example /// /// ```rust /// # #[cfg(feature = "alloc")] { /// # use toml_writer::ToTomlValue as _; /// let format = toml_writer::TomlIntegerFormat::new().as_hex_lower(); /// let number = 10; /// let number = format.format(number).unwrap_or(toml_writer::TomlInteger::new(number)); /// let number = number.to_toml_value(); /// assert_eq!(number, "0xa"); /// # } /// ``` #[derive(Copy, Clone, Debug)] pub struct TomlIntegerFormat { radix: Radix, } impl TomlIntegerFormat { /// Creates a new integer format (decimal). pub fn new() -> Self { Self { radix: Radix::Decimal, } } /// Sets the format to decimal. pub fn as_decimal(mut self) -> Self { self.radix = Radix::Decimal; self } /// Sets the format to hexadecimal with all characters in uppercase. pub fn as_hex_upper(mut self) -> Self { self.radix = Radix::Hexadecimal { case: HexCase::Upper, }; self } /// Sets the format to hexadecimal with all characters in lowercase. pub fn as_hex_lower(mut self) -> Self { self.radix = Radix::Hexadecimal { case: HexCase::Lower, }; self } /// Sets the format to octal. pub fn as_octal(mut self) -> Self { self.radix = Radix::Octal; self } /// Sets the format to binary. pub fn as_binary(mut self) -> Self { self.radix = Radix::Binary; self } /// Formats `value` as a TOML integer. /// /// Returns `None` if the value cannot be formatted /// (e.g. value is negative and the radix is not decimal). pub fn format>(self, value: N) -> Option> where TomlInteger: crate::WriteTomlValue, { match self.radix { Radix::Decimal => (), Radix::Hexadecimal { .. } | Radix::Octal | Radix::Binary => { if value < 0 { return None; } } } Some(TomlInteger { value, format: self, }) } } impl Default for TomlIntegerFormat { fn default() -> Self { Self::new() } } /// Helper struct for formatting TOML integers. /// /// This may be constructed by calling [`TomlIntegerFormat::format()`]. #[derive(Copy, Clone, Debug)] pub struct TomlInteger { value: N, format: TomlIntegerFormat, } impl TomlInteger where Self: crate::WriteTomlValue, { /// Apply default formatting pub fn new(value: N) -> Self { Self { value, format: TomlIntegerFormat::new(), } } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } impl crate::WriteTomlValue for TomlInteger { fn write_toml_value(&self, writer: &mut W) -> fmt::Result { write_toml_value(self.value, &self.format, writer) } } #[derive(Copy, Clone, Debug)] enum Radix { Decimal, Hexadecimal { case: HexCase }, Octal, Binary, } #[derive(Copy, Clone, Debug)] enum HexCase { Upper, Lower, } fn write_toml_value< N: Display + fmt::UpperHex + fmt::LowerHex + fmt::Octal + fmt::Binary, W: crate::TomlWrite + ?Sized, >( value: N, format: &TomlIntegerFormat, writer: &mut W, ) -> fmt::Result { match format.radix { Radix::Decimal => write!(writer, "{value}")?, Radix::Hexadecimal { case } => match case { HexCase::Upper => write!(writer, "0x{value:X}")?, HexCase::Lower => write!(writer, "0x{value:x}")?, }, Radix::Octal => write!(writer, "0o{value:o}")?, Radix::Binary => write!(writer, "0b{value:b}")?, } Ok(()) }