From 80e45ba07460dfa7189ec25b4c82babbf3437d43 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 27 Aug 2025 17:08:41 -0700 Subject: [PATCH 1/6] Move TimeZoneProvider to timezone_provider crate (#526) Work towards https://github.com/boa-dev/temporal/issues/409 This moves the TimeZoneProvider trait to the timezone_provider crate. There's a lot of stuff that gets moved as a result. Some important things to note: - TimeZoneProvider now operates on its own IsoDateTime type - TimeZoneProvider produces UtcOffsetSeconds, not UtcOffsets - the utils *mostly* got moved to timezone_provider::utils, but it's doc(hidden). --- src/builtins/core/calendar.rs | 5 +-- src/builtins/core/calendar/fields.rs | 4 +- src/builtins/core/calendar/types.rs | 10 ++--- src/builtins/core/date.rs | 4 +- src/builtins/core/duration.rs | 3 +- src/builtins/core/timezone.rs | 4 +- src/error.rs | 60 ++++++++++++++++------------ src/parsers.rs | 15 ++++--- src/sys.rs | 5 +-- temporal_capi/src/error.rs | 9 +---- 10 files changed, 55 insertions(+), 64 deletions(-) diff --git a/src/builtins/core/calendar.rs b/src/builtins/core/calendar.rs index 9b5674a1e..a106f61e4 100644 --- a/src/builtins/core/calendar.rs +++ b/src/builtins/core/calendar.rs @@ -12,7 +12,6 @@ use crate::{ parsers::parse_allowed_calendar_formats, TemporalError, TemporalResult, }; -use alloc::string::ToString; use core::str::FromStr; use icu_calendar::{ @@ -142,9 +141,9 @@ impl Calendar { // TODO: Determine the best way to handle "julian" here. // Not supported by `CalendarAlgorithm` let icu_locale_value = Value::try_from_utf8(&bytes.to_ascii_lowercase()) - .map_err(|e| TemporalError::range().with_message(e.to_string()))?; + .map_err(|_| TemporalError::range().with_message("unknown calendar"))?; let algorithm = CalendarAlgorithm::try_from(&icu_locale_value) - .map_err(|e| TemporalError::range().with_message(e.to_string()))?; + .map_err(|_| TemporalError::range().with_message("unknown calendar"))?; let calendar_kind = match AnyCalendarKind::try_from(algorithm) { Ok(c) => c, // Handle `islamic` calendar idenitifier. diff --git a/src/builtins/core/calendar/fields.rs b/src/builtins/core/calendar/fields.rs index 55e565f7c..a7bd8c58d 100644 --- a/src/builtins/core/calendar/fields.rs +++ b/src/builtins/core/calendar/fields.rs @@ -1,5 +1,3 @@ -use alloc::format; - use tinystr::TinyAsciiStr; use super::types::month_to_month_code; @@ -260,7 +258,7 @@ impl YearMonthCalendarFields { .era() .map(|t| TinyAsciiStr::<19>::try_from_utf8(t.as_bytes())) .transpose() - .map_err(|e| TemporalError::general(format!("{e}")))?, + .map_err(|_| TemporalError::general("Invalid era"))?, year_month.era_year(), ) } else { diff --git a/src/builtins/core/calendar/types.rs b/src/builtins/core/calendar/types.rs index 3df53a7af..5b7d77475 100644 --- a/src/builtins/core/calendar/types.rs +++ b/src/builtins/core/calendar/types.rs @@ -3,8 +3,6 @@ use tinystr::tinystr; use tinystr::TinyAsciiStr; -use alloc::format; - use crate::fields::CalendarFields; use crate::iso::{constrain_iso_day, is_valid_iso_day}; use crate::options::ArithmeticOverflow; @@ -162,10 +160,8 @@ impl EraYear { return Err(TemporalError::range().with_message("Invalid era provided.")); }; if !era_info.range.contains(&era_year) { - return Err(TemporalError::range().with_message(format!( - "Year is not valid for the era {}", - era_info.name.as_str() - ))); + return Err(TemporalError::range() + .with_message("Year is not valid for the provided era")); } let calculated_arith = era_info.arithmetic_year_for(era_year); // or a RangeError exception if the fields are sufficient but their values are internally inconsistent @@ -544,7 +540,7 @@ pub(crate) fn month_to_month_code(month: u8) -> TemporalResult { let first = month / 10; let second = month % 10; let tinystr = TinyAsciiStr::<4>::try_from_raw([b'M', first + 48, second + 48, b'\0']) - .map_err(|e| TemporalError::range().with_message(format!("tinystr error {e}")))?; + .map_err(|_| TemporalError::range().with_message("Invalid month code"))?; Ok(MonthCode(tinystr)) } diff --git a/src/builtins/core/date.rs b/src/builtins/core/date.rs index ba1a57714..d99ac3046 100644 --- a/src/builtins/core/date.rs +++ b/src/builtins/core/date.rs @@ -18,7 +18,7 @@ use crate::{ provider::{NeverProvider, TimeZoneProvider}, MonthCode, TemporalError, TemporalResult, TimeZone, }; -use alloc::{format, string::String}; +use alloc::string::String; use core::{cmp::Ordering, str::FromStr}; use icu_calendar::AnyCalendarKind; use writeable::Writeable; @@ -620,7 +620,7 @@ impl PlainDate { .era() .map(|e| { TinyAsciiStr::<19>::try_from_utf8(e.as_bytes()) - .map_err(|e| TemporalError::general(format!("{e}"))) + .map_err(|_| TemporalError::general("Parsing era failed")) }) .transpose()?; let fields = YearMonthCalendarFields::new() diff --git a/src/builtins/core/duration.rs b/src/builtins/core/duration.rs index fc604ae61..3d98cc90a 100644 --- a/src/builtins/core/duration.rs +++ b/src/builtins/core/duration.rs @@ -13,7 +13,6 @@ use crate::{ provider::TimeZoneProvider, temporal_assert, Sign, TemporalError, TemporalResult, NS_PER_DAY, }; -use alloc::format; use alloc::string::String; use core::{cmp::Ordering, str::FromStr}; use ixdtf::{ @@ -697,7 +696,7 @@ impl 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}")))?; + .map_err(|e| TemporalError::from_ixdtf(e))?; fn fraction_to_unadjusted_ns(fraction: Option) -> Result { if let Some(fraction) = fraction { diff --git a/src/builtins/core/timezone.rs b/src/builtins/core/timezone.rs index 2d06b72ae..a81ca79a7 100644 --- a/src/builtins/core/timezone.rs +++ b/src/builtins/core/timezone.rs @@ -1,6 +1,6 @@ //! This module implements the Temporal `TimeZone` and components. -use alloc::string::{String, ToString}; +use alloc::string::String; use ixdtf::encoding::Utf8; use ixdtf::{ @@ -78,7 +78,7 @@ impl UtcOffset { pub fn from_utf8(source: &[u8]) -> TemporalResult { let record = TimeZoneParser::from_utf8(source) .parse_offset() - .map_err(|e| TemporalError::range().with_message(e.to_string()))?; + .map_err(|e| TemporalError::from_ixdtf(e))?; Self::from_ixdtf_record(record) } diff --git a/src/error.rs b/src/error.rs index 309654b65..c3c4b4125 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,5 @@ //! This module implements `TemporalError`. -use alloc::borrow::Cow; -use alloc::format; use core::fmt; use timezone_provider::TimeZoneProviderError; @@ -40,7 +38,7 @@ impl fmt::Display for ErrorKind { #[derive(Debug, Clone, PartialEq)] pub struct TemporalError { kind: ErrorKind, - msg: Cow<'static, str>, + msg: ErrorMessage, } impl TemporalError { @@ -49,17 +47,14 @@ impl TemporalError { const fn new(kind: ErrorKind) -> Self { Self { kind, - msg: Cow::Borrowed(""), + msg: ErrorMessage::None, } } /// Create a generic error #[inline] #[must_use] - pub fn general(msg: S) -> Self - where - S: Into>, - { + pub fn general(msg: &'static str) -> Self { Self::new(ErrorKind::Generic).with_message(msg) } @@ -96,7 +91,7 @@ impl TemporalError { #[cfg(debug_assertions)] Self { kind: ErrorKind::Assert, - msg: Cow::Borrowed(core::panic::Location::caller().file()), + msg: ErrorMessage::String(core::panic::Location::caller().file()), } } @@ -110,11 +105,8 @@ impl TemporalError { /// Add a message to the error. #[inline] #[must_use] - pub fn with_message(mut self, msg: S) -> Self - where - S: Into>, - { - self.msg = msg.into(); + pub fn with_message(mut self, msg: &'static str) -> Self { + self.msg = ErrorMessage::String(msg); self } @@ -122,7 +114,7 @@ impl TemporalError { #[inline] #[must_use] pub(crate) fn with_enum(mut self, msg: ErrorMessage) -> Self { - self.msg = msg.to_string().into(); + self.msg = msg; self } @@ -133,22 +125,19 @@ impl TemporalError { self.kind } - /// Returns the error message. + /// Extracts the error message. #[inline] #[must_use] - pub fn message(&self) -> &str { - &self.msg + pub fn into_message(self) -> &'static str { + self.msg.to_string() } - /// Extracts the error message. - #[inline] - #[must_use] - pub fn into_message(self) -> Cow<'static, str> { - self.msg + pub(crate) fn from_icu4x(error: DateError) -> Self { + TemporalError::range().with_message("TODO DATE ERROR") } - pub fn from_icu4x(error: DateError) -> Self { - TemporalError::range().with_message(format!("{error}")) + pub(crate) fn from_ixdtf(error: ixdtf::ParseError) -> Self { + TemporalError::range().with_message("TODO IXDTF ERROR") } } @@ -156,7 +145,7 @@ impl fmt::Display for TemporalError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.kind)?; - let msg = self.msg.trim(); + let msg = self.msg.to_string(); if !msg.is_empty() { write!(f, ": {msg}")?; } @@ -205,6 +194,10 @@ pub(crate) enum ErrorMessage { // Other OffsetNeedsDisambiguation, + + // Typed + None, + String(&'static str), } impl ErrorMessage { @@ -245,6 +238,21 @@ impl ErrorMessage { Self::OffsetNeedsDisambiguation => { "Offsets could not be determined without disambiguation" } + Self::None => "", + Self::String(s) => s, + } + } +} + +impl From for TemporalError { + fn from(other: TimeZoneProviderError) -> Self { + match other { + TimeZoneProviderError::InstantOutOfRange => { + Self::range().with_enum(ErrorMessage::InstantOutOfRange) + } + TimeZoneProviderError::Assert(s) => Self::assert().with_message(s), + TimeZoneProviderError::Range(s) => Self::range().with_message(s), + _ => Self::assert().with_message("Unknown TimeZoneProviderError"), } } } diff --git a/src/parsers.rs b/src/parsers.rs index 86b56ff2b..41e603347 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -5,7 +5,6 @@ use crate::{ options::{DisplayCalendar, DisplayOffset, DisplayTimeZone}, Sign, TemporalError, TemporalResult, }; -use alloc::format; use ixdtf::{ encoding::Utf8, parsers::IxdtfParser, @@ -693,7 +692,7 @@ fn parse_ixdtf(source: &[u8], variant: ParseVariant) -> TemporalResult parser.parse_with_annotation_handler(handler), ParseVariant::Time => parser.parse_time_with_annotation_handler(handler), } - .map_err(|e| TemporalError::range().with_message(format!("{e}")))?; + .map_err(|e| TemporalError::from_ixdtf(e))?; record.calendar = first_calendar.map(|v| v.value); @@ -823,7 +822,7 @@ fn check_offset(record: IxdtfParseRecord<'_, Utf8>) -> TemporalResult TemporalResult> { let ym_record = parse_ixdtf(source, ParseVariant::YearMonth); - let Err(ref e) = ym_record else { + let Err(e) = ym_record else { return ym_record.and_then(check_offset); }; @@ -832,14 +831,14 @@ pub(crate) fn parse_year_month(source: &[u8]) -> TemporalResult check_offset(dt), // Format and return the error from parsing YearMonth. - _ => Err(TemporalError::range().with_message(format!("{e}"))), + _ => Err(e), } } /// A utilty function for parsing a `MonthDay` String. pub(crate) fn parse_month_day(source: &[u8]) -> TemporalResult> { let md_record = parse_ixdtf(source, ParseVariant::MonthDay); - let Err(ref e) = md_record else { + let Err(e) = md_record else { return md_record.and_then(check_offset); }; @@ -848,7 +847,7 @@ pub(crate) fn parse_month_day(source: &[u8]) -> TemporalResult check_offset(dt), // Format and return the error from parsing MonthDay. - _ => Err(TemporalError::range().with_message(format!("{e}"))), + _ => Err(e), } } @@ -868,7 +867,7 @@ fn check_time_record(record: IxdtfParseRecord) -> TemporalResult TemporalResult { let time_record = parse_ixdtf(source, ParseVariant::Time); - let Err(ref e) = time_record else { + let Err(e) = time_record else { return time_record.and_then(check_time_record); }; @@ -877,7 +876,7 @@ pub(crate) fn parse_time(source: &[u8]) -> TemporalResult { match dt_parse { Ok(dt) => check_time_record(dt), // Format and return the error from parsing MonthDay. - _ => Err(TemporalError::range().with_message(format!("{e}"))), + _ => Err(e), } } diff --git a/src/sys.rs b/src/sys.rs index e635a544b..4d01cd517 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -5,7 +5,6 @@ use crate::TemporalResult; use crate::unix_time::EpochNanoseconds; use crate::TemporalError; use crate::TimeZone; -use alloc::string::ToString; use web_time::{SystemTime, UNIX_EPOCH}; // TODO: Need to implement SystemTime handling for non_std. @@ -54,7 +53,7 @@ pub(crate) fn get_system_timezone() -> TemporalResult { .map(|s| { TimeZone::try_from_identifier_str_with_provider(&s, &*crate::builtins::TZ_PROVIDER) }) - .map_err(|e| TemporalError::general(e.to_string()))? + .map_err(|_| TemporalError::general("Error fetching system time"))? } /// Returns the system time in nanoseconds. @@ -64,6 +63,6 @@ pub(crate) fn get_system_nanoseconds() -> TemporalResult { SystemTime::now() .duration_since(UNIX_EPOCH) - .map_err(|e| TemporalError::general(e.to_string())) + .map_err(|_| TemporalError::general("Error fetching system time")) .map(|d| EpochNanoseconds::from(d.as_nanos() as i128)) } diff --git a/temporal_capi/src/error.rs b/temporal_capi/src/error.rs index 4696e88df..779c1e374 100644 --- a/temporal_capi/src/error.rs +++ b/temporal_capi/src/error.rs @@ -1,5 +1,3 @@ -use alloc::borrow::Cow; - #[diplomat::bridge] #[diplomat::abi_rename = "temporal_rs_{0}"] #[diplomat::attr(auto, namespace = "temporal_rs")] @@ -41,14 +39,9 @@ impl From for ffi::TemporalError { fn from(other: temporal_rs::TemporalError) -> Self { let kind = other.kind().into(); let msg = other.into_message(); - let msg = if let Cow::Borrowed(s) = msg { - Some(s) - } else { - None - }; Self { kind, - msg: msg.map(Into::into).into(), + msg: Some(msg.into()).into(), } } } From 504aadc9db7a7d2970042598a062770039675042 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Aug 2025 16:21:20 -0700 Subject: [PATCH 2/6] Add handling for ICU4X errors --- src/error.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/error.rs b/src/error.rs index c3c4b4125..b616838d8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -133,11 +133,11 @@ impl TemporalError { } pub(crate) fn from_icu4x(error: DateError) -> Self { - TemporalError::range().with_message("TODO DATE ERROR") + TemporalError::range().with_enum(ErrorMessage::Icu4xDate(error)) } pub(crate) fn from_ixdtf(error: ixdtf::ParseError) -> Self { - TemporalError::range().with_message("TODO IXDTF ERROR") + TemporalError::range().with_enum(ErrorMessage::Ixdtf(error)) } } @@ -155,7 +155,7 @@ impl fmt::Display for TemporalError { } /// The error message -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug)] pub(crate) enum ErrorMessage { // Range InstantOutOfRange, @@ -198,6 +198,8 @@ pub(crate) enum ErrorMessage { // Typed None, String(&'static str), + Ixdtf(ixdtf::ParseError), + Icu4xDate(DateError), } impl ErrorMessage { @@ -240,6 +242,18 @@ impl ErrorMessage { } Self::None => "", Self::String(s) => s, + // Todo: produce helpful strings + // https://github.com/unicode-org/icu4x/issues/6904 + Self::Ixdtf(s) => "IXDTF parsing error", + Self::Icu4xDate(DateError::Range { field, .. }) => match field { + "year" => "Year out of range.", + "month" => "Month out of range.", + "day" => "Day out of range.", + _ => "Field out of range.", + }, + Self::Icu4xDate(DateError::UnknownEra) => "Unknown era.", + Self::Icu4xDate(DateError::UnknownMonthCode(..)) => "Unknown month code.", + Self::Icu4xDate(_) => "Date error.", } } } From 00a2357af3f205c9c19007a0746dfc44835030c9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Aug 2025 16:21:46 -0700 Subject: [PATCH 3/6] Make errors Copy --- src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index b616838d8..3c7250147 100644 --- a/src/error.rs +++ b/src/error.rs @@ -35,7 +35,7 @@ impl fmt::Display for ErrorKind { } /// The error type for `boa_temporal`. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct TemporalError { kind: ErrorKind, msg: ErrorMessage, From b7bdf0522662e1252cb3268527274fddf232f206 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Aug 2025 16:25:16 -0700 Subject: [PATCH 4/6] Add ixdtf error strings --- src/error.rs | 118 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 5 deletions(-) diff --git a/src/error.rs b/src/error.rs index 3c7250147..438fdc15d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ //! This module implements `TemporalError`. use core::fmt; +use ixdtf::ParseError; use timezone_provider::TimeZoneProviderError; use icu_calendar::DateError; @@ -136,7 +137,7 @@ impl TemporalError { TemporalError::range().with_enum(ErrorMessage::Icu4xDate(error)) } - pub(crate) fn from_ixdtf(error: ixdtf::ParseError) -> Self { + pub(crate) fn from_ixdtf(error: ParseError) -> Self { TemporalError::range().with_enum(ErrorMessage::Ixdtf(error)) } } @@ -198,7 +199,7 @@ pub(crate) enum ErrorMessage { // Typed None, String(&'static str), - Ixdtf(ixdtf::ParseError), + Ixdtf(ParseError), Icu4xDate(DateError), } @@ -242,9 +243,7 @@ impl ErrorMessage { } Self::None => "", Self::String(s) => s, - // Todo: produce helpful strings - // https://github.com/unicode-org/icu4x/issues/6904 - Self::Ixdtf(s) => "IXDTF parsing error", + Self::Ixdtf(s) => ixdtf_error_to_static_string(s), Self::Icu4xDate(DateError::Range { field, .. }) => match field { "year" => "Year out of range.", "month" => "Month out of range.", @@ -271,6 +270,115 @@ impl From for TemporalError { } } +// ICU4X will get this API natively eventually +// https://github.com/unicode-org/icu4x/issues/6904 +pub fn ixdtf_error_to_static_string(error: ParseError) -> &'static str { + match error { + ParseError::ImplAssert => "Implementation error: this error must not throw.", + + ParseError::NonAsciiCodePoint => "Code point was not ASCII", + + ParseError::ParseFloat => "Invalid float while parsing fraction part.", + + ParseError::AbruptEnd { .. } => "Parsing ended abruptly.", + + ParseError::InvalidEnd => "Unexpected character found after parsing was completed.", + // Date related errors + ParseError::InvalidMonthRange => "Parsed month value not in a valid range.", + + ParseError::InvalidDayRange => "Parsed day value not in a valid range.", + + ParseError::DateYear => "Invalid chracter while parsing year value.", + + ParseError::DateExtendedYear => "Invalid character while parsing extended year value.", + + ParseError::DateMonth => "Invalid character while parsing month value.", + + ParseError::DateDay => "Invalid character while parsing day value.", + + ParseError::DateUnexpectedEnd => "Unexpected end while parsing a date value.", + + ParseError::TimeRequired => "Time is required.", + + ParseError::TimeHour => "Invalid character while parsing hour value.", + + ParseError::TimeMinuteSecond => { + "Invalid character while parsing minute/second value in (0, 59] range." + } + + ParseError::TimeSecond => "Invalid character while parsing second value in (0, 60] range.", + + ParseError::FractionPart => "Invalid character while parsing fraction part value.", + + ParseError::DateSeparator => "Invalid character while parsing date separator.", + + ParseError::TimeSeparator => "Invalid character while parsing time separator.", + + ParseError::DecimalSeparator => "Invalid character while parsing decimal separator.", + // Annotation Related Errors + ParseError::InvalidAnnotation => "Invalid annotation.", + + ParseError::AnnotationOpen => "Invalid annotation open character.", + + ParseError::AnnotationClose => "Invalid annotation close character.", + + ParseError::AnnotationChar => "Invalid annotation character.", + + ParseError::AnnotationKeyValueSeparator => { + "Invalid annotation key-value separator character." + } + + ParseError::AnnotationKeyLeadingChar => "Invalid annotation key leading character.", + + ParseError::AnnotationKeyChar => "Invalid annotation key character.", + + ParseError::AnnotationValueCharPostHyphen => { + "Expected annotation value character must exist after hyphen." + } + + ParseError::AnnotationValueChar => "Invalid annotation value character.", + + ParseError::InvalidMinutePrecisionOffset => "Offset must be minute precision", + + ParseError::CriticalDuplicateCalendar => { + "Duplicate calendars cannot be provided when one is critical." + } + + ParseError::UnrecognizedCritical => "Unrecognized annoation is marked as critical.", + + ParseError::TzLeadingChar => "Invalid time zone leading character.", + + ParseError::IanaCharPostSeparator => "Expected time zone character after '/'.", + + ParseError::IanaChar => "Invalid IANA time zone character after '/'.", + + ParseError::UtcTimeSeparator => "Invalid time zone character after '/'.", + + ParseError::OffsetNeedsSign => "UTC offset needs a sign", + + ParseError::MonthDayHyphen => "MonthDay must begin with a month or '--'", + + ParseError::DurationDisgnator => "Invalid duration designator.", + + ParseError::DurationValueExceededRange => { + "Provided Duration field value exceeds supported range." + } + + ParseError::DateDurationPartOrder => "Invalid date duration part order.", + + ParseError::TimeDurationPartOrder => "Invalid time duration part order.", + + ParseError::TimeDurationDesignator => "Invalid time duration designator.", + + ParseError::AmbiguousTimeMonthDay => "Time is ambiguous with MonthDay", + + ParseError::AmbiguousTimeYearMonth => "Time is ambiguous with YearMonth", + + ParseError::InvalidMonthDay => "MonthDay was not valid.", + _ => "General IXDTF parsing error", + } +} + impl From for TemporalError { fn from(other: TimeZoneProviderError) -> Self { match other { From d108f08a869a0d608db63426749e81b9e67d30c9 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 28 Aug 2025 16:26:58 -0700 Subject: [PATCH 5/6] Use From --- src/builtins/core/calendar.rs | 45 ++++++++++++++--------------------- src/builtins/core/duration.rs | 4 +--- src/builtins/core/timezone.rs | 4 +--- src/error.rs | 20 +++++++++------- src/parsers.rs | 3 +-- 5 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/builtins/core/calendar.rs b/src/builtins/core/calendar.rs index a106f61e4..18ca96c99 100644 --- a/src/builtins/core/calendar.rs +++ b/src/builtins/core/calendar.rs @@ -207,15 +207,12 @@ impl Calendar { ); } - let calendar_date = self - .0 - .from_codes( - resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), - resolved_fields.era_year.year, - IcuMonthCode(resolved_fields.month_code.0), - resolved_fields.day, - ) - .map_err(TemporalError::from_icu4x)?; + let calendar_date = self.0.from_codes( + resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), + resolved_fields.era_year.year, + IcuMonthCode(resolved_fields.month_code.0), + resolved_fields.day, + )?; let iso = self.0.to_iso(&calendar_date); PlainDate::new_with_overflow( Iso.extended_year(&iso), @@ -266,15 +263,12 @@ impl Calendar { } // We trust ResolvedCalendarFields to have calculated an appropriate reference year for us - let calendar_date = self - .0 - .from_codes( - resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), - resolved_fields.era_year.year, - IcuMonthCode(resolved_fields.month_code.0), - resolved_fields.day, - ) - .map_err(TemporalError::from_icu4x)?; + let calendar_date = self.0.from_codes( + resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), + resolved_fields.era_year.year, + IcuMonthCode(resolved_fields.month_code.0), + resolved_fields.day, + )?; let iso = self.0.to_iso(&calendar_date); PlainMonthDay::new_with_overflow( Iso.month(&iso).ordinal, @@ -309,15 +303,12 @@ impl Calendar { } // NOTE: This might preemptively throw as `ICU4X` does not support regulating. - let calendar_date = self - .0 - .from_codes( - resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), - resolved_fields.era_year.year, - IcuMonthCode(resolved_fields.month_code.0), - resolved_fields.day, - ) - .map_err(TemporalError::from_icu4x)?; + let calendar_date = self.0.from_codes( + resolved_fields.era_year.era.as_ref().map(|e| e.0.as_str()), + resolved_fields.era_year.year, + IcuMonthCode(resolved_fields.month_code.0), + resolved_fields.day, + )?; let iso = self.0.to_iso(&calendar_date); PlainYearMonth::new_with_overflow( Iso.year_info(&iso).year, diff --git a/src/builtins/core/duration.rs b/src/builtins/core/duration.rs index 3d98cc90a..c8f53de5a 100644 --- a/src/builtins/core/duration.rs +++ b/src/builtins/core/duration.rs @@ -694,9 +694,7 @@ 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::from_ixdtf(e))?; + let parse_record = IsoDurationParser::::from_utf8(s).parse()?; fn fraction_to_unadjusted_ns(fraction: Option) -> Result { if let Some(fraction) = fraction { diff --git a/src/builtins/core/timezone.rs b/src/builtins/core/timezone.rs index a81ca79a7..3704a9f76 100644 --- a/src/builtins/core/timezone.rs +++ b/src/builtins/core/timezone.rs @@ -76,9 +76,7 @@ impl UtcOffset { } pub fn from_utf8(source: &[u8]) -> TemporalResult { - let record = TimeZoneParser::from_utf8(source) - .parse_offset() - .map_err(|e| TemporalError::from_ixdtf(e))?; + let record = TimeZoneParser::from_utf8(source).parse_offset()?; Self::from_ixdtf_record(record) } diff --git a/src/error.rs b/src/error.rs index 438fdc15d..7047cedbd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -132,14 +132,6 @@ impl TemporalError { pub fn into_message(self) -> &'static str { self.msg.to_string() } - - pub(crate) fn from_icu4x(error: DateError) -> Self { - TemporalError::range().with_enum(ErrorMessage::Icu4xDate(error)) - } - - pub(crate) fn from_ixdtf(error: ParseError) -> Self { - TemporalError::range().with_enum(ErrorMessage::Ixdtf(error)) - } } impl fmt::Display for TemporalError { @@ -155,6 +147,18 @@ impl fmt::Display for TemporalError { } } +impl From for TemporalError { + fn from(error: DateError) -> Self { + TemporalError::range().with_enum(ErrorMessage::Icu4xDate(error)) + } +} + +impl From for TemporalError { + fn from(error: ParseError) -> Self { + TemporalError::range().with_enum(ErrorMessage::Ixdtf(error)) + } +} + /// The error message #[derive(Clone, Copy, PartialEq, Debug)] pub(crate) enum ErrorMessage { diff --git a/src/parsers.rs b/src/parsers.rs index 41e603347..87202ff1b 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -691,8 +691,7 @@ fn parse_ixdtf(source: &[u8], variant: ParseVariant) -> TemporalResult parser.parse_month_day_with_annotation_handler(handler), ParseVariant::DateTime => parser.parse_with_annotation_handler(handler), ParseVariant::Time => parser.parse_time_with_annotation_handler(handler), - } - .map_err(|e| TemporalError::from_ixdtf(e))?; + }?; record.calendar = first_calendar.map(|v| v.value); From 2c91490bbf21720b2381d56ac4f3d402f30e9043 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 29 Aug 2025 15:13:27 -0700 Subject: [PATCH 6/6] fix --- src/error.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/error.rs b/src/error.rs index 7047cedbd..c542333fb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -382,16 +382,3 @@ pub fn ixdtf_error_to_static_string(error: ParseError) -> &'static str { _ => "General IXDTF parsing error", } } - -impl From for TemporalError { - fn from(other: TimeZoneProviderError) -> Self { - match other { - TimeZoneProviderError::InstantOutOfRange => { - Self::range().with_enum(ErrorMessage::InstantOutOfRange) - } - TimeZoneProviderError::Assert(s) => Self::assert().with_message(s), - TimeZoneProviderError::Range(s) => Self::range().with_message(s), - _ => Self::assert().with_message("Unknown TimeZoneProviderError"), - } - } -}