diff --git a/src/builtins/core/date.rs b/src/builtins/core/date.rs index 579b098d8..06056fe84 100644 --- a/src/builtins/core/date.rs +++ b/src/builtins/core/date.rs @@ -431,6 +431,22 @@ impl PlainDate { partial.calendar.date_from_partial(&partial, overflow) } + // Converts a UTF-8 encoded string into a `PlainDate`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let parse_record = parse_date_time(s)?; + + let calendar = parse_record + .calendar + .map(Calendar::try_from_utf8) + .transpose()? + .unwrap_or_default(); + + // Assertion: PlainDate must exist on a DateTime parse. + let date = parse_record.date.temporal_unwrap()?; + + Self::try_new(date.year, date.month, date.day, calendar) + } + /// Creates a date time with values from a `PartialDate`. pub fn with( &self, @@ -726,18 +742,7 @@ impl FromStr for PlainDate { type Err = TemporalError; fn from_str(s: &str) -> Result { - let parse_record = parse_date_time(s)?; - - let calendar = parse_record - .calendar - .map(Calendar::try_from_utf8) - .transpose()? - .unwrap_or_default(); - - // Assertion: PlainDate must exist on a DateTime parse. - let date = parse_record.date.temporal_unwrap()?; - - Self::try_new(date.year, date.month, date.day, calendar) + Self::from_utf8(s.as_bytes()) } } diff --git a/src/builtins/core/datetime.rs b/src/builtins/core/datetime.rs index 71ad0ebf9..8cc56c3b6 100644 --- a/src/builtins/core/datetime.rs +++ b/src/builtins/core/datetime.rs @@ -449,6 +449,34 @@ impl PlainDateTime { Self::from_date_and_time(date, PlainTime::new_unchecked(iso_time)) } + // Converts a UTF-8 encoded string into a `PlainDateTime`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let parse_record = parse_date_time(s)?; + + let calendar = parse_record + .calendar + .map(Calendar::try_from_utf8) + .transpose()? + .unwrap_or_default(); + + let time = parse_record + .time + .map(IsoTime::from_time_record) + .transpose()? + .unwrap_or_default(); + + let parsed_date = parse_record.date.temporal_unwrap()?; + + let date = IsoDate::new_with_overflow( + parsed_date.year, + parsed_date.month, + parsed_date.day, + ArithmeticOverflow::Reject, + )?; + + Ok(Self::new_unchecked(IsoDateTime::new(date, time)?, calendar)) + } + /// Creates a new `DateTime` with the fields of a `PartialDateTime`. /// /// ```rust @@ -816,30 +844,7 @@ impl FromStr for PlainDateTime { type Err = TemporalError; fn from_str(s: &str) -> Result { - let parse_record = parse_date_time(s)?; - - let calendar = parse_record - .calendar - .map(Calendar::try_from_utf8) - .transpose()? - .unwrap_or_default(); - - let time = parse_record - .time - .map(IsoTime::from_time_record) - .transpose()? - .unwrap_or_default(); - - let parsed_date = parse_record.date.temporal_unwrap()?; - - let date = IsoDate::new_with_overflow( - parsed_date.year, - parsed_date.month, - parsed_date.day, - ArithmeticOverflow::Reject, - )?; - - Ok(Self::new_unchecked(IsoDateTime::new(date, time)?, calendar)) + Self::from_utf8(s.as_bytes()) } } diff --git a/src/builtins/core/duration.rs b/src/builtins/core/duration.rs index 89408cd8c..06d2efa99 100644 --- a/src/builtins/core/duration.rs +++ b/src/builtins/core/duration.rs @@ -257,6 +257,113 @@ impl Duration { ) } + // Converts a UTF-8 encoded string into a `Duration`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let parse_record = IsoDurationParser::from_utf8(s) + .parse() + .map_err(|e| TemporalError::range().with_message(format!("{e}")))?; + + let (hours, minutes, seconds, millis, micros, nanos) = match parse_record.time { + Some(TimeDurationRecord::Hours { hours, fraction }) => { + let unadjusted_fraction = + fraction.and_then(|x| x.to_nanoseconds()).unwrap_or(0) as u64; + let fractional_hours_ns = unadjusted_fraction * 3600; + let minutes = fractional_hours_ns.div_euclid(60 * 1_000_000_000); + let fractional_minutes_ns = fractional_hours_ns.rem_euclid(60 * 1_000_000_000); + + let seconds = fractional_minutes_ns.div_euclid(1_000_000_000); + let fractional_seconds = fractional_minutes_ns.rem_euclid(1_000_000_000); + + let milliseconds = fractional_seconds.div_euclid(1_000_000); + let rem = fractional_seconds.rem_euclid(1_000_000); + + let microseconds = rem.div_euclid(1_000); + let nanoseconds = rem.rem_euclid(1_000); + + ( + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds, + ) + } + // Minutes variant is defined as { hours: u32, minutes: u32, fraction: u64 } + Some(TimeDurationRecord::Minutes { + hours, + minutes, + fraction, + }) => { + let unadjusted_fraction = + fraction.and_then(|x| x.to_nanoseconds()).unwrap_or(0) as u64; + let fractional_minutes_ns = unadjusted_fraction * 60; + let seconds = fractional_minutes_ns.div_euclid(1_000_000_000); + let fractional_seconds = fractional_minutes_ns.rem_euclid(1_000_000_000); + + let milliseconds = fractional_seconds.div_euclid(1_000_000); + let rem = fractional_seconds.rem_euclid(1_000_000); + + let microseconds = rem.div_euclid(1_000); + let nanoseconds = rem.rem_euclid(1_000); + + ( + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds, + ) + } + // Seconds variant is defined as { hours: u32, minutes: u32, seconds: u32, fraction: u32 } + Some(TimeDurationRecord::Seconds { + hours, + minutes, + seconds, + fraction, + }) => { + let ns = fraction.and_then(|x| x.to_nanoseconds()).unwrap_or(0); + let milliseconds = ns.div_euclid(1_000_000); + let rem = ns.rem_euclid(1_000_000); + + let microseconds = rem.div_euclid(1_000); + let nanoseconds = rem.rem_euclid(1_000); + + ( + hours, + minutes, + seconds, + milliseconds as u64, + microseconds as u64, + nanoseconds as u64, + ) + } + None => (0, 0, 0, 0, 0, 0), + }; + + let (years, months, weeks, days) = if let Some(date) = parse_record.date { + (date.years, date.months, date.weeks, date.days) + } else { + (0, 0, 0, 0) + }; + + let sign = parse_record.sign as i64; + + Self::new( + years as i64 * sign, + months as i64 * sign, + weeks as i64 * sign, + days as i64 * sign, + hours as i64 * sign, + minutes as i64 * sign, + seconds as i64 * sign, + millis as i64 * sign, + micros as i128 * sign as i128, + nanos as i128 * sign as i128, + ) + } + /// Return if the Durations values are within their valid ranges. #[inline] #[must_use] diff --git a/src/builtins/core/instant.rs b/src/builtins/core/instant.rs index 15382d077..6bfaeb08c 100644 --- a/src/builtins/core/instant.rs +++ b/src/builtins/core/instant.rs @@ -163,6 +163,51 @@ impl Instant { Self::try_new(epoch_nanos) } + // Converts a UTF-8 encoded string into a `Instant`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let ixdtf_record = parse_instant(s)?; + + // Find the offset + let ns_offset = match ixdtf_record.offset { + UtcOffsetRecordOrZ::Offset(offset) => { + let ns = offset + .fraction + .and_then(|x| x.to_nanoseconds()) + .unwrap_or(0); + (offset.hour as i64 * NANOSECONDS_PER_HOUR + + i64::from(offset.minute) * NANOSECONDS_PER_MINUTE + + i64::from(offset.second) * NANOSECONDS_PER_SECOND + + i64::from(ns)) + * offset.sign as i64 + } + UtcOffsetRecordOrZ::Z => 0, + }; + + let time_nanoseconds = ixdtf_record + .time + .fraction + .and_then(|x| x.to_nanoseconds()) + .unwrap_or(0); + let (millisecond, rem) = time_nanoseconds.div_rem_euclid(&1_000_000); + let (microsecond, nanosecond) = rem.div_rem_euclid(&1_000); + + let balanced = IsoDateTime::balance( + ixdtf_record.date.year, + ixdtf_record.date.month.into(), + ixdtf_record.date.day.into(), + ixdtf_record.time.hour.into(), + ixdtf_record.time.minute.into(), + ixdtf_record.time.second.clamp(0, 59).into(), + millisecond.into(), + microsecond.into(), + i128::from(nanosecond) - i128::from(ns_offset), + ); + + let nanoseconds = balanced.as_nanoseconds()?; + + Ok(Self(nanoseconds)) + } + /// Adds a `Duration` to the current `Instant`, returning an error if the `Duration` /// contains a `DateDuration`. #[inline] @@ -274,48 +319,9 @@ impl Instant { impl FromStr for Instant { type Err = TemporalError; - fn from_str(s: &str) -> Result { - let ixdtf_record = parse_instant(s)?; - - // Find the offset - let ns_offset = match ixdtf_record.offset { - UtcOffsetRecordOrZ::Offset(offset) => { - let ns = offset - .fraction - .and_then(|x| x.to_nanoseconds()) - .unwrap_or(0); - (offset.hour as i64 * NANOSECONDS_PER_HOUR - + i64::from(offset.minute) * NANOSECONDS_PER_MINUTE - + i64::from(offset.second) * NANOSECONDS_PER_SECOND - + i64::from(ns)) - * offset.sign as i64 - } - UtcOffsetRecordOrZ::Z => 0, - }; - - let time_nanoseconds = ixdtf_record - .time - .fraction - .and_then(|x| x.to_nanoseconds()) - .unwrap_or(0); - let (millisecond, rem) = time_nanoseconds.div_rem_euclid(&1_000_000); - let (microsecond, nanosecond) = rem.div_rem_euclid(&1_000); - let balanced = IsoDateTime::balance( - ixdtf_record.date.year, - ixdtf_record.date.month.into(), - ixdtf_record.date.day.into(), - ixdtf_record.time.hour.into(), - ixdtf_record.time.minute.into(), - ixdtf_record.time.second.clamp(0, 59).into(), - millisecond.into(), - microsecond.into(), - i128::from(nanosecond) - i128::from(ns_offset), - ); - - let nanoseconds = balanced.as_nanoseconds()?; - - Ok(Self(nanoseconds)) + fn from_str(s: &str) -> Result { + Self::from_utf8(s.as_bytes()) } } diff --git a/src/builtins/core/month_day.rs b/src/builtins/core/month_day.rs index 381788ad3..1ac528141 100644 --- a/src/builtins/core/month_day.rs +++ b/src/builtins/core/month_day.rs @@ -49,6 +49,38 @@ impl PlainMonthDay { Ok(Self::new_unchecked(iso, calendar)) } + // Converts a UTF-8 encoded string into a `PlainMonthDay`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let record = crate::parsers::parse_month_day(s)?; + + let calendar = record + .calendar + .map(Calendar::try_from_utf8) + .transpose()? + .unwrap_or_default(); + + // ParseISODateTime + // Step 4.a.ii.3 + // If goal is TemporalMonthDayString or TemporalYearMonthString, calendar is + // not empty, and the ASCII-lowercase of calendar is not "iso8601", throw a + // RangeError exception. + if !calendar.is_iso() { + return Err(TemporalError::range().with_message("non-ISO calendar not supported.")); + } + + let date = record.date; + + let date = date.temporal_unwrap()?; + + Self::new_with_overflow( + date.month, + date.day, + calendar, + ArithmeticOverflow::Reject, + None, + ) + } + pub fn with( &self, _partial: PartialDate, @@ -118,33 +150,6 @@ impl FromStr for PlainMonthDay { type Err = TemporalError; fn from_str(s: &str) -> Result { - let record = crate::parsers::parse_month_day(s)?; - - let calendar = record - .calendar - .map(Calendar::try_from_utf8) - .transpose()? - .unwrap_or_default(); - - // ParseISODateTime - // Step 4.a.ii.3 - // If goal is TemporalMonthDayString or TemporalYearMonthString, calendar is - // not empty, and the ASCII-lowercase of calendar is not "iso8601", throw a - // RangeError exception. - if !calendar.is_iso() { - return Err(TemporalError::range().with_message("non-ISO calendar not supported.")); - } - - let date = record.date; - - let date = date.temporal_unwrap()?; - - Self::new_with_overflow( - date.month, - date.day, - calendar, - ArithmeticOverflow::Reject, - None, - ) + Self::from_utf8(s.as_bytes()) } } diff --git a/src/builtins/core/time.rs b/src/builtins/core/time.rs index 82014f7bd..797fee3ca 100644 --- a/src/builtins/core/time.rs +++ b/src/builtins/core/time.rs @@ -306,6 +306,13 @@ impl PlainTime { Ok(Self::new_unchecked(iso)) } + // Converts a UTF-8 encoded string into a `PlainTime`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let result = parse_time(s)?; + let iso = IsoTime::from_time_record(result)?; + Ok(Self::new_unchecked(iso)) + } + /// Creates a new `PlainTime` using the current `PlainTime` fields as a fallback. /// /// ```rust @@ -486,9 +493,7 @@ impl FromStr for PlainTime { type Err = TemporalError; fn from_str(s: &str) -> Result { - let result = parse_time(s)?; - let iso = IsoTime::from_time_record(result)?; - Ok(Self::new_unchecked(iso)) + Self::from_utf8(s.as_bytes()) } } diff --git a/src/builtins/core/year_month.rs b/src/builtins/core/year_month.rs index 15fdea711..71b021982 100644 --- a/src/builtins/core/year_month.rs +++ b/src/builtins/core/year_month.rs @@ -220,6 +220,46 @@ impl PlainYearMonth { partial.calendar.year_month_from_partial(&partial, overflow) } + // Converts a UTF-8 encoded string into a `PlainYearMonth`. + pub fn from_utf8(s: &[u8]) -> TemporalResult { + let record = crate::parsers::parse_year_month(s)?; + let calendar = record + .calendar + .map(Calendar::try_from_utf8) + .transpose()? + .unwrap_or_default(); + + // ParseISODateTime + // Step 4.a.ii.3 + // If goal is TemporalMonthDayString or TemporalYearMonthString, calendar is + // not empty, and the ASCII-lowercase of calendar is not "iso8601", throw a + // RangeError exception. + if !calendar.is_iso() { + return Err(TemporalError::range().with_message("non-ISO calendar not supported.")); + } + + let date = record.date.temporal_unwrap()?; + + // The below steps are from `ToTemporalYearMonth` + // 10. Let isoDate be CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]). + let iso = IsoDate::new_unchecked(date.year, date.month, date.day); + + // 11. If ISOYearMonthWithinLimits(isoDate) is false, throw a RangeError exception. + if !year_month_within_limits(iso.year, iso.month) { + return Err(TemporalError::range().with_message("Exceeded valid range.")); + } + + let intermediate = Self::new_unchecked(iso, calendar); + // 12. Set result to ISODateToFields(calendar, isoDate, year-month). + let partial = PartialDate::try_from_year_month(&intermediate)?; + // 13. NOTE: The following operation is called with constrain regardless of the + // value of overflow, in order for the calendar to store a canonical value in the + // [[Day]] field of the [[ISODate]] internal slot of the result. + // 14. Set isoDate to ? CalendarYearMonthFromFields(calendar, result, constrain). + // 15. Return ! CreateTemporalYearMonth(isoDate, calendar). + PlainYearMonth::from_partial(partial, ArithmeticOverflow::Constrain) + } + /// Returns the iso year value for this `YearMonth`. #[inline] #[must_use] @@ -391,42 +431,7 @@ impl FromStr for PlainYearMonth { type Err = TemporalError; fn from_str(s: &str) -> Result { - let record = crate::parsers::parse_year_month(s)?; - let calendar = record - .calendar - .map(Calendar::try_from_utf8) - .transpose()? - .unwrap_or_default(); - - // ParseISODateTime - // Step 4.a.ii.3 - // If goal is TemporalMonthDayString or TemporalYearMonthString, calendar is - // not empty, and the ASCII-lowercase of calendar is not "iso8601", throw a - // RangeError exception. - if !calendar.is_iso() { - return Err(TemporalError::range().with_message("non-ISO calendar not supported.")); - } - - let date = record.date.temporal_unwrap()?; - - // The below steps are from `ToTemporalYearMonth` - // 10. Let isoDate be CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]). - let iso = IsoDate::new_unchecked(date.year, date.month, date.day); - - // 11. If ISOYearMonthWithinLimits(isoDate) is false, throw a RangeError exception. - if !year_month_within_limits(iso.year, iso.month) { - return Err(TemporalError::range().with_message("Exceeded valid range.")); - } - - let intermediate = Self::new_unchecked(iso, calendar); - // 12. Set result to ISODateToFields(calendar, isoDate, year-month). - let partial = PartialDate::try_from_year_month(&intermediate)?; - // 13. NOTE: The following operation is called with constrain regardless of the - // value of overflow, in order for the calendar to store a canonical value in the - // [[Day]] field of the [[ISODate]] internal slot of the result. - // 14. Set isoDate to ? CalendarYearMonthFromFields(calendar, result, constrain). - // 15. Return ! CreateTemporalYearMonth(isoDate, calendar). - PlainYearMonth::from_partial(partial, ArithmeticOverflow::Constrain) + Self::from_utf8(s.as_bytes()) } } diff --git a/src/options/relative_to.rs b/src/options/relative_to.rs index 0c86010f7..0cfee9b7d 100644 --- a/src/options/relative_to.rs +++ b/src/options/relative_to.rs @@ -40,7 +40,7 @@ impl RelativeTo { source: &str, provider: &impl TimeZoneProvider, ) -> TemporalResult { - let result = parse_date_time(source)?; + let result = parse_date_time(source.as_bytes())?; let Some(annotation) = result.tz else { let date_record = result.date.temporal_unwrap()?; diff --git a/src/parsers.rs b/src/parsers.rs index 4c621fb60..0fa82a9db 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -648,7 +648,7 @@ enum ParseVariant { } #[inline] -fn parse_ixdtf(source: &str, variant: ParseVariant) -> TemporalResult { +fn parse_ixdtf(source: &[u8], variant: ParseVariant) -> TemporalResult { fn cast_handler<'a>( _: &mut IxdtfParser<'a>, handler: impl FnMut(Annotation<'a>) -> Option>, @@ -658,7 +658,7 @@ fn parse_ixdtf(source: &str, variant: ParseVariant) -> TemporalResult = None; let mut critical_duplicate_calendar = false; - let mut parser = IxdtfParser::from_str(source); + let mut parser = IxdtfParser::from_utf8(source); let handler = cast_handler(&mut parser, |annotation: Annotation<'_>| { if annotation.key == "u-ca".as_bytes() { @@ -706,7 +706,7 @@ fn parse_ixdtf(source: &str, variant: ParseVariant) -> TemporalResult TemporalResult { +pub(crate) fn parse_date_time(source: &[u8]) -> TemporalResult { let record = parse_ixdtf(source, ParseVariant::DateTime)?; if record.offset == Some(UtcOffsetRecordOrZ::Z) { @@ -719,7 +719,7 @@ pub(crate) fn parse_date_time(source: &str) -> TemporalResult #[inline] pub(crate) fn parse_zoned_date_time(source: &str) -> TemporalResult { - let record = parse_ixdtf(source, ParseVariant::DateTime)?; + let record = parse_ixdtf(source.as_bytes(), ParseVariant::DateTime)?; // TODO: Support rejecting subminute precision in time zone annootations if record.tz.is_none() { @@ -738,7 +738,7 @@ pub(crate) struct IxdtfParseInstantRecord { /// A utility function for parsing an `Instant` string #[inline] -pub(crate) fn parse_instant(source: &str) -> TemporalResult { +pub(crate) fn parse_instant(source: &[u8]) -> TemporalResult { let record = parse_ixdtf(source, ParseVariant::DateTime)?; let IxdtfParseRecord { @@ -758,7 +758,7 @@ pub(crate) fn parse_instant(source: &str) -> TemporalResult TemporalResult { +pub(crate) fn parse_year_month(source: &[u8]) -> TemporalResult { let ym_record = parse_ixdtf(source, ParseVariant::YearMonth); if let Ok(ym) = ym_record { @@ -780,14 +780,14 @@ pub(crate) fn parse_year_month(source: &str) -> TemporalResult /// A utilty function for parsing a `MonthDay` String. #[inline] -pub(crate) fn parse_month_day(source: &str) -> TemporalResult { +pub(crate) fn parse_month_day(source: &[u8]) -> TemporalResult { let md_record = parse_ixdtf(source, ParseVariant::MonthDay); // Error needs to be a RangeError md_record.map_err(|e| TemporalError::range().with_message(format!("{e}"))) } #[inline] -pub(crate) fn parse_time(source: &str) -> TemporalResult { +pub(crate) fn parse_time(source: &[u8]) -> TemporalResult { let time_record = parse_ixdtf(source, ParseVariant::Time); let time_err = match time_record { @@ -812,13 +812,13 @@ pub(crate) fn parse_time(source: &str) -> TemporalResult { #[inline] pub(crate) fn parse_allowed_calendar_formats(s: &str) -> Option<&[u8]> { - if let Ok(r) = parse_ixdtf(s, ParseVariant::DateTime).map(|r| r.calendar) { + if let Ok(r) = parse_ixdtf(s.as_bytes(), ParseVariant::DateTime).map(|r| r.calendar) { return Some(r.unwrap_or(&[])); } else if let Ok(r) = IxdtfParser::from_str(s).parse_time().map(|r| r.calendar) { return Some(r.unwrap_or(&[])); - } else if let Ok(r) = parse_ixdtf(s, ParseVariant::YearMonth).map(|r| r.calendar) { + } else if let Ok(r) = parse_ixdtf(s.as_bytes(), ParseVariant::YearMonth).map(|r| r.calendar) { return Some(r.unwrap_or(&[])); - } else if let Ok(r) = parse_ixdtf(s, ParseVariant::MonthDay).map(|r| r.calendar) { + } else if let Ok(r) = parse_ixdtf(s.as_bytes(), ParseVariant::MonthDay).map(|r| r.calendar) { return Some(r.unwrap_or(&[])); } None diff --git a/src/parsers/timezone.rs b/src/parsers/timezone.rs index f84f42750..300b8d19a 100644 --- a/src/parsers/timezone.rs +++ b/src/parsers/timezone.rs @@ -9,7 +9,7 @@ use super::{parse_ixdtf, ParseVariant}; #[inline] pub(crate) fn parse_allowed_timezone_formats(s: &str) -> Option { let (offset, annotation) = if let Ok((offset, annotation)) = - parse_ixdtf(s, ParseVariant::DateTime).map(|r| (r.offset, r.tz)) + parse_ixdtf(s.as_bytes(), ParseVariant::DateTime).map(|r| (r.offset, r.tz)) { (offset, annotation) } else if let Ok((offset, annotation)) = IxdtfParser::from_str(s) @@ -18,11 +18,11 @@ pub(crate) fn parse_allowed_timezone_formats(s: &str) -> Option { { (offset, annotation) } else if let Ok((offset, annotation)) = - parse_ixdtf(s, ParseVariant::YearMonth).map(|r| (r.offset, r.tz)) + parse_ixdtf(s.as_bytes(), ParseVariant::YearMonth).map(|r| (r.offset, r.tz)) { (offset, annotation) } else if let Ok((offset, annotation)) = - parse_ixdtf(s, ParseVariant::MonthDay).map(|r| (r.offset, r.tz)) + parse_ixdtf(s.as_bytes(), ParseVariant::MonthDay).map(|r| (r.offset, r.tz)) { (offset, annotation) } else { diff --git a/temporal_capi/src/duration.rs b/temporal_capi/src/duration.rs index 0bdad7375..b263cd7df 100644 --- a/temporal_capi/src/duration.rs +++ b/temporal_capi/src/duration.rs @@ -7,7 +7,7 @@ pub mod ffi { use crate::error::ffi::TemporalError; use alloc::boxed::Box; use alloc::string::String; - use core::str::{self, FromStr}; + use core::str::FromStr; use diplomat_runtime::DiplomatOption; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; use num_traits::FromPrimitive; @@ -154,9 +154,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::Duration::from_str(s) + temporal_rs::Duration::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/instant.rs b/temporal_capi/src/instant.rs index 134115c29..49523dc3e 100644 --- a/temporal_capi/src/instant.rs +++ b/temporal_capi/src/instant.rs @@ -7,7 +7,7 @@ pub mod ffi { use crate::options::ffi::{DifferenceSettings, RoundingOptions}; use alloc::boxed::Box; use alloc::string::String; - use core::str::{self, FromStr}; + use core::str::FromStr; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; #[cfg(feature = "compiled_data")] @@ -50,9 +50,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::Instant::from_str(s) + temporal_rs::Instant::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/plain_date.rs b/temporal_capi/src/plain_date.rs index f5c091f5b..d664fe05b 100644 --- a/temporal_capi/src/plain_date.rs +++ b/temporal_capi/src/plain_date.rs @@ -20,7 +20,7 @@ pub mod ffi { use diplomat_runtime::{DiplomatOption, DiplomatStrSlice, DiplomatWrite}; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; - use core::str::{self, FromStr}; + use core::str::FromStr; #[diplomat::opaque] pub struct PlainDate(pub(crate) temporal_rs::PlainDate); @@ -103,9 +103,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::PlainDate::from_str(s) + temporal_rs::PlainDate::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/plain_date_time.rs b/temporal_capi/src/plain_date_time.rs index 4060aa9a2..e0d888f9d 100644 --- a/temporal_capi/src/plain_date_time.rs +++ b/temporal_capi/src/plain_date_time.rs @@ -17,7 +17,7 @@ pub mod ffi { use crate::plain_time::ffi::{PartialTime, PlainTime}; use alloc::string::String; use core::fmt::Write; - use core::str::{self, FromStr}; + use core::str::FromStr; use diplomat_runtime::DiplomatWrite; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; @@ -119,9 +119,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::PlainDateTime::from_str(s) + temporal_rs::PlainDateTime::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/plain_month_day.rs b/temporal_capi/src/plain_month_day.rs index 90de91c70..3c7e1e9cd 100644 --- a/temporal_capi/src/plain_month_day.rs +++ b/temporal_capi/src/plain_month_day.rs @@ -11,7 +11,7 @@ pub mod ffi { use alloc::string::String; use core::fmt::Write; - use core::str::{self, FromStr}; + use core::str::FromStr; use diplomat_runtime::DiplomatWrite; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; @@ -57,9 +57,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::PlainMonthDay::from_str(s) + temporal_rs::PlainMonthDay::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/plain_time.rs b/temporal_capi/src/plain_time.rs index 6571c2ac8..f8c562543 100644 --- a/temporal_capi/src/plain_time.rs +++ b/temporal_capi/src/plain_time.rs @@ -11,7 +11,7 @@ pub mod ffi { }; use alloc::string::String; use core::fmt::Write; - use core::str::{self, FromStr}; + use core::str::FromStr; use diplomat_runtime::{DiplomatOption, DiplomatWrite}; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; @@ -80,9 +80,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::PlainTime::from_str(s) + temporal_rs::PlainTime::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) } diff --git a/temporal_capi/src/plain_year_month.rs b/temporal_capi/src/plain_year_month.rs index f53049779..e6fd13320 100644 --- a/temporal_capi/src/plain_year_month.rs +++ b/temporal_capi/src/plain_year_month.rs @@ -14,7 +14,7 @@ pub mod ffi { use diplomat_runtime::DiplomatWrite; use diplomat_runtime::{DiplomatStr, DiplomatStr16}; - use core::str::{self, FromStr}; + use core::str::FromStr; #[diplomat::opaque] pub struct PlainYearMonth(pub(crate) temporal_rs::PlainYearMonth); @@ -50,9 +50,7 @@ pub mod ffi { } pub fn from_utf8(s: &DiplomatStr) -> Result, TemporalError> { - // TODO(#275) This should not need to validate - let s = str::from_utf8(s).map_err(|_| temporal_rs::TemporalError::range())?; - temporal_rs::PlainYearMonth::from_str(s) + temporal_rs::PlainYearMonth::from_utf8(s) .map(|c| Box::new(Self(c))) .map_err(Into::into) }