icu4x icon indicating copy to clipboard operation
icu4x copied to clipboard

Design for the first version of the units conversion.

Open younies opened this issue 2 years ago • 2 comments

I am proposing this design for the fist version of the units conversion.

First MeasureUnit:

  • it is a struct that contains a list of MeasureUnitItems.
  • Each MeasureUnitItem contains the following:
  1. si prefix --> optional
  2. unit id
  3. power
  • MeasureUnit implements a fn try_from_id(id: &str) --> Result<Self, DimensionError>

Second: Converter

  • it is a struct that contains the followings:
  1. Conversion Rate (including the offset)
  2. Convertibility
  • Converter implements the following functions:
  1. static fn try_from_ids( id1: &str, id2: &str) --> Result<Self, DimensionError>
  2. static fn try_from_measunits( unit1: &MeasureUnit, unit2: &MeasureUnit) --> Result<Self, DimensionError>
  3. static fn extract_convertibility_from_ids( id1: &str, id2: &str) --> Result<Convertibility, DimensionError>
  4. static fn extract_convertibility_from_measunits( unit1: &MeasureUnit, unit2: &MeasureUnit --> Result<Convertibility, DimensionError>
  5. fn convert_f64(&self, value: f64) --> f64
  6. fn convert_BigRational(&self, value: BigRational) --> BigRational
  7. fn convert_FixedDecimal(&self, value: FixedDecimal) --> FixedDecimal --> postpone for now.

Third: Convertibility

  • An enum that contains the following fields:
  1. Convertible
  2. Reciprocal
  3. NotConvertible ??? --> do we need it ?

Fourth: DimensionError

  • An enum that contains the following fields:
  1. WrongCldrUnitId
  2. NotConvertible

younies avatar Nov 28 '23 14:11 younies

Discussion:

@sffc , for MeasureUnitParser, we can have MeasureUnitParser::parse_bytes(&self, bytes: &[u8]) --> Result<MeasureUnit> and also MeasureUnitParser::parse_str(&self, id : &str) --> Result<> --> this is an implementation for FromStr trait.

NOTE: we need a MeasureUnitParser that takes the units provider and parse the strings to return MeasureUnit.

Also, for the Converter, we need ConverterFactory

File a TODO issue to split the data between the MeasureUnitParser and ConverterFactory

and start with 5. fn convert_f64(&self, value: f64) --> f64 6. fn convert_big_rational(&self, value: BigRational) --> BigRational

LGTM tentatively : @younies , @sffc , @robertbastian , @Manishearth

younies avatar Nov 28 '23 16:11 younies

Design the FFI for units conersion.

  • @younies - On FFI I want to be able to interface with f64.

option 0

Convert(input: IcuRatio) --> IcuRatio.

IcuRatio::from_f64()
IcuRatio::to_f64()

IcuRatio::to_u64()

option 1

Converter::convert_f64(input: f64) --> f64.
Converter::convert_exact(input: IcuRatio) -> IcuRatio

conv.convert_exact(IcuRatio::fraction(7, 3))
conv.convert_exact(IcuRatio::from(7).pow(-4)))
conv.convert_f64(10e-4))
  • @robertbastian I prefer this over 0, there's no expectation that convert(123.4) == convert2(IcuRatio::from_u64(123.4)).to_u64()
  • @sffc - I like this because we can change the internal of IcuRatio
  • @robertbastian - But that's horrible because we can't advertise performance characteristics; we should just use the standard Rust type
pub struct IcuRatio(pub BigRational);

option 2

No IcuRatio on FFI

// String syntax: [-]iii.fffE[-]eee
Converter::convert_decimal(input: string) -> Result<string>
Converter::convert_f64(input: f64) -> f64

Eliminated: the user might want to use IcuRatio across multiple call sites

option 3

Converter::convert_decimal(input: FixedDecimal) -> FixedDecimal
Converter::convert_f64(input: f64) -> f64

Eliminated: FixedDecimal is not efficient for math, and it can't represent ratios like 1/3

option 4

Converter::convert_f64(input: f64) -> f64.
Converter::convert_big_rational(input: BigRational) -> BigRational

conv.convert_big_rational(...)
conv.convert_big_rational(...)
conv.convert_f64(10e-4))

Expose subset of BigRational API over FFI as IcuRational (bikeshed)

  • @Manishearth - Not super happy of putting non-ICU4X types on FFI
  • @robertbastian - If we want to use standard Rust types in Rust, that's the cost
  • @sffc - I'd prefer naming it ICU4XBigRational or keeping it in the namespace at least

Note: Ratio<BigInt> has a type alias to BigRational

LGTM: @sffc @robertbastian @younies @Manishearth

sffc avatar Apr 17 '24 05:04 sffc