Merge pull request #4450 from yt2b/refactor_format_type

Refactor `FormatType`
This commit is contained in:
Jeong YunWon
2023-01-16 01:09:24 +09:00
committed by GitHub
2 changed files with 41 additions and 76 deletions

View File

@@ -100,7 +100,7 @@ pub fn is_integer(v: f64) -> bool {
(v - v.round()).abs() < f64::EPSILON
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Case {
Lower,
Upper,

View File

@@ -1,4 +1,5 @@
use crate::{float_ops, str::BorrowedStr};
use float_ops::Case;
use itertools::{Itertools, PeekingNext};
use num_bigint::{BigInt, Sign};
use num_traits::{cast::ToPrimitive, Signed};
@@ -125,15 +126,11 @@ pub enum FormatType {
Character,
Decimal,
Octal,
HexLower,
HexUpper,
Number,
ExponentLower,
ExponentUpper,
GeneralFormatLower,
GeneralFormatUpper,
FixedPointLower,
FixedPointUpper,
Hex(Case),
Exponent(Case),
GeneralFormat(Case),
FixedPoint(Case),
Percentage,
}
@@ -145,15 +142,15 @@ impl From<&FormatType> for char {
FormatType::Character => 'c',
FormatType::Decimal => 'd',
FormatType::Octal => 'o',
FormatType::HexLower => 'x',
FormatType::HexUpper => 'X',
FormatType::Number => 'n',
FormatType::ExponentLower => 'e',
FormatType::ExponentUpper => 'E',
FormatType::GeneralFormatLower => 'g',
FormatType::GeneralFormatUpper => 'G',
FormatType::FixedPointLower => 'f',
FormatType::FixedPointUpper => 'F',
FormatType::Hex(Case::Lower) => 'x',
FormatType::Hex(Case::Upper) => 'X',
FormatType::Exponent(Case::Lower) => 'e',
FormatType::Exponent(Case::Upper) => 'E',
FormatType::GeneralFormat(Case::Lower) => 'g',
FormatType::GeneralFormat(Case::Upper) => 'G',
FormatType::FixedPoint(Case::Lower) => 'f',
FormatType::FixedPoint(Case::Upper) => 'F',
FormatType::Percentage => '%',
}
}
@@ -168,15 +165,15 @@ impl FormatParse for FormatType {
Some('c') => (Some(Self::Character), chars.as_str()),
Some('d') => (Some(Self::Decimal), chars.as_str()),
Some('o') => (Some(Self::Octal), chars.as_str()),
Some('x') => (Some(Self::HexLower), chars.as_str()),
Some('X') => (Some(Self::HexUpper), chars.as_str()),
Some('e') => (Some(Self::ExponentLower), chars.as_str()),
Some('E') => (Some(Self::ExponentUpper), chars.as_str()),
Some('f') => (Some(Self::FixedPointLower), chars.as_str()),
Some('F') => (Some(Self::FixedPointUpper), chars.as_str()),
Some('g') => (Some(Self::GeneralFormatLower), chars.as_str()),
Some('G') => (Some(Self::GeneralFormatUpper), chars.as_str()),
Some('n') => (Some(Self::Number), chars.as_str()),
Some('x') => (Some(Self::Hex(Case::Lower)), chars.as_str()),
Some('X') => (Some(Self::Hex(Case::Upper)), chars.as_str()),
Some('e') => (Some(Self::Exponent(Case::Lower)), chars.as_str()),
Some('E') => (Some(Self::Exponent(Case::Upper)), chars.as_str()),
Some('f') => (Some(Self::FixedPoint(Case::Lower)), chars.as_str()),
Some('F') => (Some(Self::FixedPoint(Case::Upper)), chars.as_str()),
Some('g') => (Some(Self::GeneralFormat(Case::Lower)), chars.as_str()),
Some('G') => (Some(Self::GeneralFormat(Case::Upper)), chars.as_str()),
Some('%') => (Some(Self::Percentage), chars.as_str()),
_ => (None, text),
}
@@ -368,8 +365,7 @@ impl FormatSpec {
| FormatType::Character
| FormatType::Binary
| FormatType::Octal
| FormatType::HexLower
| FormatType::HexUpper
| FormatType::Hex(_)
| FormatType::Number,
) => {
let ch = char::from(format_type);
@@ -388,13 +384,8 @@ impl FormatSpec {
fn get_separator_interval(&self) -> usize {
match self.format_type {
Some(FormatType::Binary) => 4,
Some(FormatType::Decimal) => 3,
Some(FormatType::Octal) => 4,
Some(FormatType::HexLower) => 4,
Some(FormatType::HexUpper) => 4,
Some(FormatType::Number) => 3,
Some(FormatType::FixedPointLower) | Some(FormatType::FixedPointUpper) => 3,
Some(FormatType::Binary | FormatType::Octal | FormatType::Hex(_)) => 4,
Some(FormatType::Decimal | FormatType::Number | FormatType::FixedPoint(_)) => 3,
None => 3,
_ => panic!("Separators only valid for numbers!"),
}
@@ -423,63 +414,40 @@ impl FormatSpec {
}
pub fn format_float(&self, num: f64) -> Result<String, FormatSpecError> {
self.validate_format(FormatType::FixedPointLower)?;
self.validate_format(FormatType::FixedPoint(Case::Lower))?;
let precision = self.precision.unwrap_or(6);
let magnitude = num.abs();
let raw_magnitude_str: Result<String, FormatSpecError> = match self.format_type {
Some(FormatType::FixedPointUpper) => Ok(float_ops::format_fixed(
let raw_magnitude_str: Result<String, FormatSpecError> = match &self.format_type {
Some(FormatType::FixedPoint(case)) => Ok(float_ops::format_fixed(
precision,
magnitude,
float_ops::Case::Upper,
self.alternate_form,
)),
Some(FormatType::FixedPointLower) => Ok(float_ops::format_fixed(
precision,
magnitude,
float_ops::Case::Lower,
*case,
self.alternate_form,
)),
Some(FormatType::Decimal)
| Some(FormatType::Binary)
| Some(FormatType::Octal)
| Some(FormatType::HexLower)
| Some(FormatType::HexUpper)
| Some(FormatType::Hex(_))
| Some(FormatType::String)
| Some(FormatType::Character) => {
let ch = char::from(self.format_type.as_ref().unwrap());
Err(FormatSpecError::UnknownFormatCode(ch, "float"))
}
Some(FormatType::Number) => Err(FormatSpecError::NotImplemented('n', "float")),
Some(FormatType::GeneralFormatUpper) => {
Some(FormatType::GeneralFormat(case)) => {
let precision = if precision == 0 { 1 } else { precision };
Ok(float_ops::format_general(
precision,
magnitude,
float_ops::Case::Upper,
*case,
self.alternate_form,
false,
))
}
Some(FormatType::GeneralFormatLower) => {
let precision = if precision == 0 { 1 } else { precision };
Ok(float_ops::format_general(
precision,
magnitude,
float_ops::Case::Lower,
self.alternate_form,
false,
))
}
Some(FormatType::ExponentUpper) => Ok(float_ops::format_exponent(
Some(FormatType::Exponent(case)) => Ok(float_ops::format_exponent(
precision,
magnitude,
float_ops::Case::Upper,
self.alternate_form,
)),
Some(FormatType::ExponentLower) => Ok(float_ops::format_exponent(
precision,
magnitude,
float_ops::Case::Lower,
*case,
self.alternate_form,
)),
Some(FormatType::Percentage) => match magnitude {
@@ -542,8 +510,8 @@ impl FormatSpec {
match self.format_type {
Some(FormatType::Binary) => "0b",
Some(FormatType::Octal) => "0o",
Some(FormatType::HexLower) => "0x",
Some(FormatType::HexUpper) => "0X",
Some(FormatType::Hex(Case::Lower)) => "0x",
Some(FormatType::Hex(Case::Upper)) => "0X",
_ => "",
}
} else {
@@ -553,8 +521,8 @@ impl FormatSpec {
Some(FormatType::Binary) => self.format_int_radix(magnitude, 2),
Some(FormatType::Decimal) => self.format_int_radix(magnitude, 10),
Some(FormatType::Octal) => self.format_int_radix(magnitude, 8),
Some(FormatType::HexLower) => self.format_int_radix(magnitude, 16),
Some(FormatType::HexUpper) => match self.precision {
Some(FormatType::Hex(Case::Lower)) => self.format_int_radix(magnitude, 16),
Some(FormatType::Hex(Case::Upper)) => match self.precision {
Some(_) => Err(FormatSpecError::PrecisionNotAllowed),
None => {
let mut result = magnitude.to_str_radix(16);
@@ -572,12 +540,9 @@ impl FormatSpec {
Some(_) | None => Err(FormatSpecError::CodeNotInRange),
},
},
Some(FormatType::GeneralFormatUpper)
| Some(FormatType::GeneralFormatLower)
| Some(FormatType::FixedPointUpper)
| Some(FormatType::FixedPointLower)
| Some(FormatType::ExponentUpper)
| Some(FormatType::ExponentLower)
Some(FormatType::GeneralFormat(_))
| Some(FormatType::FixedPoint(_))
| Some(FormatType::Exponent(_))
| Some(FormatType::Percentage) => match num.to_f64() {
Some(float) => return self.format_float(float),
_ => Err(FormatSpecError::UnableToConvert),