Skip to content

Commit

Permalink
Next round of try_from_str et al. (#5085)
Browse files Browse the repository at this point in the history
#4931

Covers all types that had a `try_from_bytes`.

There are still a lot of types that implement `FromStr`, but don't have
any inherent methods. Those will be next.
  • Loading branch information
robertbastian committed Jun 20, 2024
1 parent 0bec39c commit 63931f8
Show file tree
Hide file tree
Showing 66 changed files with 585 additions and 525 deletions.
8 changes: 3 additions & 5 deletions components/calendar/src/any_calendar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,12 +1017,10 @@ impl AnyCalendarKind {
AnyCalendarKind::Gregorian => value!("gregory"),
AnyCalendarKind::Hebrew => value!("hebrew"),
AnyCalendarKind::Indian => value!("indian"),
AnyCalendarKind::IslamicCivil => Value::try_from_bytes(b"islamic-civil").unwrap(),
AnyCalendarKind::IslamicCivil => Value::try_from_str("islamic-civil").unwrap(),
AnyCalendarKind::IslamicObservational => value!("islamic"),
AnyCalendarKind::IslamicTabular => Value::try_from_bytes(b"islamic-tbla").unwrap(),
AnyCalendarKind::IslamicUmmAlQura => {
Value::try_from_bytes(b"islamic-umalqura").unwrap()
}
AnyCalendarKind::IslamicTabular => Value::try_from_str("islamic-tbla").unwrap(),
AnyCalendarKind::IslamicUmmAlQura => Value::try_from_str("islamic-umalqura").unwrap(),
AnyCalendarKind::Iso => value!("iso"),
AnyCalendarKind::Japanese => value!("japanese"),
AnyCalendarKind::JapaneseExtended => value!("japanext"),
Expand Down
3 changes: 1 addition & 2 deletions components/datetime/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions components/datetime/src/any/zoned_datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ impl ZonedDateTimeFormatter {
/// use icu::datetime::ZonedDateTimeFormatter;
/// use icu::locale::locale;
/// use icu::timezone::CustomTimeZone;
/// use std::str::FromStr;
/// use writeable::assert_writeable_eq;
///
/// let mut options = components::Bag::default();
Expand All @@ -174,7 +173,7 @@ impl ZonedDateTimeFormatter {
///
/// let datetime =
/// DateTime::try_new_iso_datetime(2021, 04, 08, 16, 12, 37).unwrap();
/// let time_zone = CustomTimeZone::from_str("-07:00").unwrap();
/// let time_zone = CustomTimeZone::try_from_str("-07:00").unwrap();
/// let any_datetime = datetime.to_any();
///
/// assert_writeable_eq!(
Expand Down Expand Up @@ -330,7 +329,6 @@ impl ZonedDateTimeFormatter {
/// use icu::datetime::ZonedDateTimeFormatter;
/// use icu::locale::locale;
/// use icu::timezone::CustomTimeZone;
/// use std::str::FromStr;
/// use writeable::assert_writeable_eq;
///
/// let options = length::Bag::from_date_time_style(
Expand All @@ -348,7 +346,7 @@ impl ZonedDateTimeFormatter {
///
/// let datetime =
/// DateTime::try_new_iso_datetime(2021, 04, 08, 16, 12, 37).unwrap();
/// let time_zone = CustomTimeZone::from_str("-07:00").unwrap();
/// let time_zone = CustomTimeZone::try_from_str("-07:00").unwrap();
/// let any_datetime = datetime.to_any();
///
/// assert_writeable_eq!(
Expand Down Expand Up @@ -576,7 +574,6 @@ fn buffer_constructor() {
use icu::datetime::ZonedDateTimeFormatter;
use icu::locale::locale;
use icu::timezone::CustomTimeZone;
use std::str::FromStr;
use writeable::assert_writeable_eq;

let provider = icu_provider_blob::BlobDataProvider::try_new_from_static_blob(include_bytes!(
Expand All @@ -597,7 +594,7 @@ fn buffer_constructor() {
&DateTime::try_new_iso_datetime(2021, 04, 08, 16, 12, 37)
.unwrap()
.to_any(),
&CustomTimeZone::from_str("-07:00").unwrap()
&CustomTimeZone::try_from_str("-07:00").unwrap()
)
.unwrap(),
"Apr 8, 2021, 4:12:37 PM GMT-07:00"
Expand Down
3 changes: 1 addition & 2 deletions components/datetime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
//! TypedDateTimeFormatter,
//! };
//! use icu::locale::{locale, Locale};
//! use std::str::FromStr;
//! use writeable::assert_writeable_eq;
//!
//! // See the next code example for a more ergonomic example with .into().
Expand All @@ -47,7 +46,7 @@
//! ));
//!
//! // You can work with a formatter that can select the calendar at runtime:
//! let locale = Locale::from_str("en-u-ca-gregory").unwrap();
//! let locale = Locale::try_from_str("en-u-ca-gregory").unwrap();
//! let dtf = DateTimeFormatter::try_new(&locale.into(), options.clone())
//! .expect("Failed to create DateTimeFormatter instance.");
//!
Expand Down
9 changes: 3 additions & 6 deletions components/datetime/src/zoned_datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ use crate::{
/// use icu::datetime::{options::length, TypedZonedDateTimeFormatter};
/// use icu::locale::locale;
/// use icu::timezone::CustomTimeZone;
/// use std::str::FromStr;
/// use writeable::assert_writeable_eq;
///
/// let options = length::Bag::from_date_time_style(
Expand All @@ -70,7 +69,7 @@ use crate::{
///
/// let datetime =
/// DateTime::try_new_gregorian_datetime(2020, 9, 12, 12, 34, 28).unwrap();
/// let time_zone = CustomTimeZone::from_str("-07:00").unwrap();
/// let time_zone = CustomTimeZone::try_from_str("-07:00").unwrap();
///
/// let formatted_date = zdtf.format(&datetime, &time_zone);
///
Expand Down Expand Up @@ -368,7 +367,6 @@ impl<C: CldrCalendar> TypedZonedDateTimeFormatter<C> {
/// use icu::datetime::{options::length, TypedZonedDateTimeFormatter};
/// use icu::locale::locale;
/// use icu::timezone::CustomTimeZone;
/// use std::str::FromStr;
/// use writeable::assert_writeable_eq;
///
/// let options = length::Bag::from_date_time_style(
Expand All @@ -385,7 +383,7 @@ impl<C: CldrCalendar> TypedZonedDateTimeFormatter<C> {
///
/// let datetime =
/// DateTime::try_new_gregorian_datetime(2020, 9, 12, 12, 34, 28).unwrap();
/// let time_zone = CustomTimeZone::from_str("-07:00").unwrap();
/// let time_zone = CustomTimeZone::try_from_str("-07:00").unwrap();
///
/// let formatted_date = zdtf.format(&datetime, &time_zone);
///
Expand All @@ -409,7 +407,6 @@ impl<C: CldrCalendar> TypedZonedDateTimeFormatter<C> {
/// use icu::datetime::{options::length, TypedZonedDateTimeFormatter};
/// use icu::locale::locale;
/// use icu::timezone::CustomTimeZone;
/// use std::str::FromStr;
///
/// let options = length::Bag::from_date_time_style(
/// length::Date::Medium,
Expand All @@ -425,7 +422,7 @@ impl<C: CldrCalendar> TypedZonedDateTimeFormatter<C> {
///
/// let datetime =
/// DateTime::try_new_gregorian_datetime(2020, 9, 12, 12, 34, 28).unwrap();
/// let time_zone = CustomTimeZone::from_str("-07:00").unwrap();
/// let time_zone = CustomTimeZone::try_from_str("-07:00").unwrap();
///
/// let formatted_string = zdtf.format_to_string(&datetime, &time_zone);
///
Expand Down
4 changes: 2 additions & 2 deletions components/datetime/tests/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ use patterns::{
dayperiods::{DayPeriodExpectation, DayPeriodTests},
time_zones::{TimeZoneConfig, TimeZoneExpectation, TimeZoneTests},
};
use std::str::FromStr;
use tinystr::tinystr;
use writeable::assert_writeable_eq;

Expand Down Expand Up @@ -98,7 +97,8 @@ fn test_fixture(fixture_name: &str, file: &str) {
None => format!("\n file: {fixture_name}.json\n"),
};
for (locale, output_value) in fx.output.values {
let locale = Locale::from_str(&locale).expect("Expected parseable locale in fixture");
let locale =
Locale::try_from_str(&locale).expect("Expected parseable locale in fixture");
if let Some(kind) = AnyCalendarKind::get_for_locale(&locale) {
match kind {
AnyCalendarKind::Buddhist => assert_fixture_element(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -723,25 +723,25 @@ impl<'a, 'b> Insertable<'a, 'b> {
/// Push a `&str` on the replacement.
pub(crate) fn push_str(&mut self, s: &str) {
// SAFETY: s is valid UTF-8 by type
unsafe { self.push_bytes(s.as_bytes()) };
unsafe { self.push_utf8(s.as_bytes()) };
debug_assert!(self.curr <= self.end());
}

/// # Safety
/// The caller must ensure that `bytes` is valid UTF-8.
unsafe fn push_bytes(&mut self, bytes: &[u8]) {
if self.free_range().len() >= bytes.len() {
/// The caller must ensure that `code_units` is valid UTF-8.
unsafe fn push_utf8(&mut self, code_units: &[u8]) {
if self.free_range().len() >= code_units.len() {
// SAFETY: The caller guarantees these are valid UTF-8
self._rep.content[self.curr..self.curr + bytes.len()].copy_from_slice(bytes);
self.curr += bytes.len();
self._rep.content[self.curr..self.curr + code_units.len()].copy_from_slice(code_units);
self.curr += code_units.len();
return;
}
// eprintln!("WARNING: free space not sufficient for Insertable::push_bytes");

// SAFETY: The caller guarantees these are valid UTF-8
self._rep
.content
.splice(self.free_range(), bytes.iter().copied());
.splice(self.free_range(), code_units.iter().copied());
// SAFETY: The free range did not have enough space. The above splice replaces the completey
// remaining free range with the replacement, so there are no more un-replaced bytes left
// in the replacement range.
Expand Down
27 changes: 16 additions & 11 deletions components/experimental/src/units/measureunit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'data> MeasureUnitParser<'data> {
/// NOTE:
/// if the unit id is found, the function will return (unit id, part without the unit id and without `-` at the beginning of the remaining part if it exists).
/// if the unit id is not found, the function will return an error.
fn get_unit_id<'a>(&'a self, part: &'a [u8]) -> Result<(u16, &[u8]), InvalidUnitError> {
fn get_unit_id<'a>(&self, part: &'a [u8]) -> Result<(u16, &'a [u8]), InvalidUnitError> {
let mut cursor = self.units_trie.cursor();
let mut longest_match = Err(InvalidUnitError);

Expand All @@ -49,7 +49,7 @@ impl<'data> MeasureUnitParser<'data> {
longest_match
}

fn get_power<'a>(&'a self, part: &'a [u8]) -> Result<(u8, &[u8]), InvalidUnitError> {
fn get_power<'a>(&self, part: &'a [u8]) -> Result<(u8, &'a [u8]), InvalidUnitError> {
let (power, part_without_power) = get_power(part);

// If the power is not found, return the part as it is.
Expand All @@ -67,7 +67,7 @@ impl<'data> MeasureUnitParser<'data> {
/// Get the SI prefix.
/// NOTE:
/// if the prefix is not found, the function will return (SiPrefix { power: 0, base: Base::Decimal }, part).
fn get_si_prefix<'a>(&'a self, part: &'a [u8]) -> (SiPrefix, &[u8]) {
fn get_si_prefix<'a>(&self, part: &'a [u8]) -> (SiPrefix, &'a [u8]) {
let (si_prefix, part_without_si_prefix) = get_si_prefix(part);
if part_without_si_prefix.len() == part.len() {
return (si_prefix, part);
Expand All @@ -85,17 +85,22 @@ impl<'data> MeasureUnitParser<'data> {
/// Returns:
/// - Ok(MeasureUnit) if the identifier is valid.
/// - Err(InvalidUnitError) if the identifier is invalid.
pub fn try_from_bytes(&self, identifier: &'data [u8]) -> Result<MeasureUnit, InvalidUnitError> {
if identifier.starts_with(b"-") || identifier.ends_with(b"-") {
#[inline]
pub fn try_from_str(&self, s: &str) -> Result<MeasureUnit, InvalidUnitError> {
self.try_from_utf8(s.as_bytes())
}

/// See [`Self::try_from_str`]
pub fn try_from_utf8(&self, mut code_units: &[u8]) -> Result<MeasureUnit, InvalidUnitError> {
if code_units.starts_with(b"-") || code_units.ends_with(b"-") {
return Err(InvalidUnitError);
}

let mut measure_unit_items = Vec::<MeasureUnitItem>::new();
let mut identifier = identifier;
let mut sign = 1;
while !identifier.is_empty() {
while !code_units.is_empty() {
// First: extract the power.
let (power, identifier_part_without_power) = self.get_power(identifier)?;
let (power, identifier_part_without_power) = self.get_power(code_units)?;

// Second: extract the si_prefix and the unit_id.
let (si_prefix, unit_id, identifier_part_without_unit_id) =
Expand All @@ -118,9 +123,9 @@ impl<'data> MeasureUnitParser<'data> {
}
// If the sign is negative, this means that the identifier may contain more than one `per-` keyword.
Err(_) if sign == 1 => {
if let Some(remainder) = identifier.strip_prefix(b"per-") {
if let Some(remainder) = code_units.strip_prefix(b"per-") {
sign = -1;
identifier = remainder;
code_units = remainder;
continue;
}

Expand All @@ -138,7 +143,7 @@ impl<'data> MeasureUnitParser<'data> {
unit_id,
});

identifier = match identifier_part_without_unit_id.strip_prefix(b"-") {
code_units = match identifier_part_without_unit_id.strip_prefix(b"-") {
Some(remainder) => remainder,
None if identifier_part_without_unit_id.is_empty() => {
identifier_part_without_unit_id
Expand Down
10 changes: 5 additions & 5 deletions components/experimental/tests/units/units_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ fn test_cldr_unit_tests() {

for test in tests {
let input_unit = parser
.try_from_bytes(test.input_unit.as_bytes())
.try_from_str(&test.input_unit)
.expect("Failed to parse input unit");
let output_unit = parser
.try_from_bytes(test.output_unit.as_bytes())
.try_from_str(&test.output_unit)
.expect("Failed to parse output unit");

let converter: UnitsConverter<Ratio<BigInt>> = converter_factory
Expand Down Expand Up @@ -211,10 +211,10 @@ fn test_units_non_convertible() {

for (input, output) in non_convertible_units.iter() {
let input_unit = parser
.try_from_bytes(input.as_bytes())
.try_from_str(input)
.expect("Failed to parse input unit");
let output_unit = parser
.try_from_bytes(output.as_bytes())
.try_from_str(output)
.expect("Failed to parse output unit");

let result: Option<UnitsConverter<f64>> =
Expand Down Expand Up @@ -290,7 +290,7 @@ fn test_unparsable_units() {

unparsable_units.iter().for_each(|unit| {
assert!(
parser.try_from_bytes(unit.as_bytes()).is_err(),
parser.try_from_str(unit).is_err(),
"Unit '{}' should be unparsable but was parsed successfully.",
unit
);
Expand Down
3 changes: 1 addition & 2 deletions components/icu/examples/tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use icu::plurals::{PluralCategory, PluralRules};
use icu::timezone::CustomTimeZone;
use icu_collections::codepointinvlist::CodePointInversionListBuilder;
use std::env;
use std::str::FromStr;

fn print<T: AsRef<str>>(_input: T) {
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -53,7 +52,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
)
.expect("Failed to create TypedDateTimeFormatter.");
let today_date = DateTime::try_new_gregorian_datetime(2020, 10, 10, 18, 56, 0).unwrap();
let today_tz = CustomTimeZone::from_str("Z").unwrap(); // Z refers to the utc timezone
let today_tz = CustomTimeZone::try_from_str("Z").unwrap(); // Z refers to the utc timezone

let formatted_dt = dtf.format(&today_date, &today_tz);

Expand Down
Loading

0 comments on commit 63931f8

Please sign in to comment.