diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 3e644dd..bcdb2fe 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -26,9 +26,7 @@ use super::util::compare_children; use super::util::compare_standard_properties; use super::util::get_property; use super::util::get_property_boolean; -use super::util::get_property_numeric; use super::util::get_property_quoted_string; -use super::util::get_property_unquoted_atom; use crate::compare::compare_field::ComparePropertiesResult; use crate::compare::compare_field::EmacsField; use crate::compare::macros::compare_properties; @@ -47,7 +45,6 @@ use crate::types::Comment; use crate::types::CommentBlock; use crate::types::Date; use crate::types::DayOfMonth; -use crate::types::DayOfMonthInner; use crate::types::DiarySexp; use crate::types::Document; use crate::types::DocumentElement; @@ -65,7 +62,6 @@ use crate::types::GetStandardProperties; use crate::types::Heading; use crate::types::HorizontalRule; use crate::types::Hour; -use crate::types::HourInner; use crate::types::InlineBabelCall; use crate::types::InlineSourceBlock; use crate::types::Italic; @@ -75,9 +71,7 @@ use crate::types::LatexFragment; use crate::types::LineBreak; use crate::types::LinkType; use crate::types::Minute; -use crate::types::MinuteInner; use crate::types::Month; -use crate::types::MonthInner; use crate::types::NodeProperty; use crate::types::OrgMacro; use crate::types::Paragraph; @@ -94,7 +88,6 @@ use crate::types::RadioLink; use crate::types::RadioTarget; use crate::types::RegularLink; use crate::types::RepeaterType; -use crate::types::RepeaterWarningDelayValueType; use crate::types::Section; use crate::types::SpecialBlock; use crate::types::SrcBlock; @@ -119,7 +112,6 @@ use crate::types::Verbatim; use crate::types::VerseBlock; use crate::types::WarningDelayType; use crate::types::Year; -use crate::types::YearInner; #[derive(Debug)] pub enum DiffEntry<'b, 's> { @@ -4000,279 +3992,180 @@ fn compare_superscript<'b, 's>( } fn compare_timestamp<'b, 's>( - _source: &'s str, + source: &'s str, emacs: &'b Token<'s>, rust: &'b Timestamp<'s>, ) -> Result, Box> { let mut this_status = DiffStatus::Good; + let mut child_status = Vec::new(); let mut message = None; - // Compare type - let timestamp_type = get_property_unquoted_atom(emacs, ":type")?; - match (timestamp_type, &rust.timestamp_type) { - (Some("diary"), TimestampType::Diary) => {} - (Some("active"), TimestampType::Active) => {} - (Some("inactive"), TimestampType::Inactive) => {} - (Some("active-range"), TimestampType::ActiveRange) => {} - (Some("inactive-range"), TimestampType::InactiveRange) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Timestamp type mismatch (emacs != rust) {:?} != {:?}", - timestamp_type, rust.timestamp_type - )); - } - } + assert_no_children(emacs, &mut this_status, &mut message)?; - // Compare range-type - let range_type = get_property_unquoted_atom(emacs, ":range-type")?; - match (range_type, &rust.range_type) { - (Some("daterange"), TimestampRangeType::DateRange) => {} - (Some("timerange"), TimestampRangeType::TimeRange) => {} - (None, TimestampRangeType::None) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Range type mismatch (emacs != rust) {:?} != {:?}", - range_type, rust.range_type - )); - } - } - - // Compare raw-value - let raw_value = get_property_quoted_string(emacs, ":raw-value")? - .ok_or("Timestamps should have a :raw-value.")?; - if raw_value != rust.get_raw_value() { - this_status = DiffStatus::Bad; - message = Some(format!( - "Raw value mismatch (emacs != rust) {:?} != {:?}", - raw_value, - rust.get_raw_value() - )); - } - - // Compare start - let year_start: Option = get_property_numeric(emacs, ":year-start")?; - let month_start: Option = get_property_numeric(emacs, ":month-start")?; - let day_of_month_start: Option = get_property_numeric(emacs, ":day-start")?; - let rust_year_start = rust.start.as_ref().map(Date::get_year).map(Year::get_value); - let rust_month_start = rust - .start - .as_ref() - .map(Date::get_month) - .map(Month::get_value); - let rust_day_of_month_start = rust - .start - .as_ref() - .map(Date::get_day_of_month) - .map(DayOfMonth::get_value); - if year_start != rust_year_start { - this_status = DiffStatus::Bad; - message = Some(format!( - "year start mismatch (emacs != rust) {:?} != {:?}", - year_start, rust_year_start - )); - } - if month_start != rust_month_start { - this_status = DiffStatus::Bad; - message = Some(format!( - "month start mismatch (emacs != rust) {:?} != {:?}", - month_start, rust_month_start - )); - } - if day_of_month_start != rust_day_of_month_start { - this_status = DiffStatus::Bad; - message = Some(format!( - "day of month start mismatch (emacs != rust) {:?} != {:?}", - day_of_month_start, rust_day_of_month_start - )); - } - - // Compare end - let year_end: Option = get_property_numeric(emacs, ":year-end")?; - let month_end: Option = get_property_numeric(emacs, ":month-end")?; - let day_of_month_end: Option = get_property_numeric(emacs, ":day-end")?; - let rust_year_end = rust.end.as_ref().map(Date::get_year).map(Year::get_value); - let rust_month_end = rust.end.as_ref().map(Date::get_month).map(Month::get_value); - let rust_day_of_month_end = rust - .end - .as_ref() - .map(Date::get_day_of_month) - .map(DayOfMonth::get_value); - if year_end != rust_year_end { - this_status = DiffStatus::Bad; - message = Some(format!( - "year end mismatch (emacs != rust) {:?} != {:?}", - year_end, rust_year_end - )); - } - if month_end != rust_month_end { - this_status = DiffStatus::Bad; - message = Some(format!( - "month end mismatch (emacs != rust) {:?} != {:?}", - month_end, rust_month_end - )); - } - if day_of_month_end != rust_day_of_month_end { - this_status = DiffStatus::Bad; - message = Some(format!( - "day of month end mismatch (emacs != rust) {:?} != {:?}", - day_of_month_end, rust_day_of_month_end - )); - } - - // Compare time start - let hour_start: Option = get_property_numeric(emacs, ":hour-start")?; - let minute_start: Option = get_property_numeric(emacs, ":minute-start")?; - let rust_hour_start = rust - .start_time - .as_ref() - .map(Time::get_hour) - .map(Hour::get_value); - let rust_minute_start = rust - .start_time - .as_ref() - .map(Time::get_minute) - .map(Minute::get_value); - if hour_start != rust_hour_start { - this_status = DiffStatus::Bad; - message = Some(format!( - "hour start mismatch (emacs != rust) {:?} != {:?}", - hour_start, rust_hour_start - )); - } - if minute_start != rust_minute_start { - this_status = DiffStatus::Bad; - message = Some(format!( - "minute start mismatch (emacs != rust) {:?} != {:?}", - minute_start, rust_minute_start - )); - } - - // Compare time end - let hour_end: Option = get_property_numeric(emacs, ":hour-end")?; - let minute_end: Option = get_property_numeric(emacs, ":minute-end")?; - let rust_hour_end = rust - .end_time - .as_ref() - .map(Time::get_hour) - .map(Hour::get_value); - let rust_minute_end = rust - .end_time - .as_ref() - .map(Time::get_minute) - .map(Minute::get_value); - if hour_end != rust_hour_end { - this_status = DiffStatus::Bad; - message = Some(format!( - "hour end mismatch (emacs != rust) {:?} != {:?}", - hour_end, rust_hour_end - )); - } - if minute_end != rust_minute_end { - this_status = DiffStatus::Bad; - message = Some(format!( - "minute end mismatch (emacs != rust) {:?} != {:?}", - minute_end, rust_minute_end - )); - } - - // Compare repeater - let repeater_type = get_property_unquoted_atom(emacs, ":repeater-type")?; - let repeater_value: Option = - get_property_numeric(emacs, ":repeater-value")?; - let repeater_unit = get_property_unquoted_atom(emacs, ":repeater-unit")?; - let rust_repeater_type = rust - .repeater - .as_ref() - .map(|repeater| &repeater.repeater_type); - let rust_repeater_value = rust.repeater.as_ref().map(|repeater| repeater.value); - let rust_repeater_unit = rust.repeater.as_ref().map(|repeater| &repeater.unit); - match (repeater_type, rust_repeater_type) { - (Some("cumulate"), Some(RepeaterType::Cumulative)) => {} - (Some("catch-up"), Some(RepeaterType::CatchUp)) => {} - (Some("restart"), Some(RepeaterType::Restart)) => {} - (None, None) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Repeater type mismatch (emacs != rust) {:?} != {:?}", - repeater_type, rust_repeater_type - )); - } - } - if repeater_value != rust_repeater_value { - this_status = DiffStatus::Bad; - message = Some(format!( - "Repeater value mismatch (emacs != rust) {:?} != {:?}", - repeater_value, rust_repeater_value - )); - } - match (repeater_unit, rust_repeater_unit) { - (Some("hour"), Some(TimeUnit::Hour)) => {} - (Some("day"), Some(TimeUnit::Day)) => {} - (Some("week"), Some(TimeUnit::Week)) => {} - (Some("month"), Some(TimeUnit::Month)) => {} - (Some("year"), Some(TimeUnit::Year)) => {} - (None, None) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Repeater unit mismatch (emacs != rust) {:?} != {:?}", - repeater_unit, rust_repeater_unit - )); - } - } - - // Compare warning_delay - let warning_delay_type = get_property_unquoted_atom(emacs, ":warning-type")?; - let warning_delay_value: Option = - get_property_numeric(emacs, ":warning-value")?; - let warning_delay_unit = get_property_unquoted_atom(emacs, ":warning-unit")?; - let rust_warning_delay_type = rust - .warning_delay - .as_ref() - .map(|warning_delay| &warning_delay.warning_delay_type); - let rust_warning_delay_value = rust - .warning_delay - .as_ref() - .map(|warning_delay| warning_delay.value); - let rust_warning_delay_unit = rust - .warning_delay - .as_ref() - .map(|warning_delay| &warning_delay.unit); - match (warning_delay_type, rust_warning_delay_type) { - (Some("all"), Some(WarningDelayType::All)) => {} - (Some("first"), Some(WarningDelayType::First)) => {} - (None, None) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Warning delay type mismatch (emacs != rust) {:?} != {:?}", - warning_delay_type, rust_warning_delay_type - )); - } - } - if warning_delay_value != rust_warning_delay_value { - this_status = DiffStatus::Bad; - message = Some(format!( - "Warning delay value mismatch (emacs != rust) {:?} != {:?}", - warning_delay_value, rust_warning_delay_value - )); - } - match (warning_delay_unit, rust_warning_delay_unit) { - (Some("hour"), Some(TimeUnit::Hour)) => {} - (Some("day"), Some(TimeUnit::Day)) => {} - (Some("week"), Some(TimeUnit::Week)) => {} - (Some("month"), Some(TimeUnit::Month)) => {} - (Some("year"), Some(TimeUnit::Year)) => {} - (None, None) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Warning delay unit mismatch (emacs != rust) {:?} != {:?}", - warning_delay_unit, rust_warning_delay_unit - )); + for diff in compare_properties!( + source, + emacs, + rust, + ( + EmacsField::Required(":type"), + |r| Some(match r.timestamp_type { + TimestampType::Diary => "diary", + TimestampType::Active => "active", + TimestampType::Inactive => "inactive", + TimestampType::ActiveRange => "active-range", + TimestampType::InactiveRange => "inactive-range", + }), + compare_property_unquoted_atom + ), + ( + EmacsField::Required(":range-type"), + |r| match r.range_type { + TimestampRangeType::DateRange => Some("daterange"), + TimestampRangeType::TimeRange => Some("timerange"), + TimestampRangeType::None => None, + }, + compare_property_unquoted_atom + ), + ( + EmacsField::Required(":raw-value"), + |r| Some(r.get_raw_value()), + compare_property_quoted_string + ), + ( + EmacsField::Required(":year-start"), + |r| r.start.as_ref().map(Date::get_year).map(Year::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":month-start"), + |r| r.start.as_ref().map(Date::get_month).map(Month::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":day-start"), + |r| r + .start + .as_ref() + .map(Date::get_day_of_month) + .map(DayOfMonth::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":year-end"), + |r| r.end.as_ref().map(Date::get_year).map(Year::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":month-end"), + |r| r.end.as_ref().map(Date::get_month).map(Month::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":day-end"), + |r| r + .end + .as_ref() + .map(Date::get_day_of_month) + .map(DayOfMonth::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":hour-start"), + |r| r + .start_time + .as_ref() + .map(Time::get_hour) + .map(Hour::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":minute-start"), + |r| r + .start_time + .as_ref() + .map(Time::get_minute) + .map(Minute::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":hour-end"), + |r| r.end_time.as_ref().map(Time::get_hour).map(Hour::get_value), + compare_property_numeric + ), + ( + EmacsField::Required(":minute-end"), + |r| r + .end_time + .as_ref() + .map(Time::get_minute) + .map(Minute::get_value), + compare_property_numeric + ), + ( + EmacsField::Optional(":repeater-type"), + |r| match r.repeater.as_ref().map(|repeater| &repeater.repeater_type) { + Some(RepeaterType::Cumulative) => Some("cumulate"), + Some(RepeaterType::CatchUp) => Some("catch-up"), + Some(RepeaterType::Restart) => Some("restart"), + None => None, + }, + compare_property_unquoted_atom + ), + ( + EmacsField::Optional(":repeater-unit"), + |r| match r.repeater.as_ref().map(|repeater| &repeater.unit) { + Some(TimeUnit::Hour) => Some("hour"), + Some(TimeUnit::Day) => Some("day"), + Some(TimeUnit::Week) => Some("week"), + Some(TimeUnit::Month) => Some("month"), + Some(TimeUnit::Year) => Some("year"), + None => None, + }, + compare_property_unquoted_atom + ), + ( + EmacsField::Optional(":repeater-value"), + |r| r.repeater.as_ref().map(|repeater| repeater.value), + compare_property_numeric + ), + ( + EmacsField::Optional(":warning-type"), + |r| match r + .warning_delay + .as_ref() + .map(|repeater| &repeater.warning_delay_type) + { + Some(WarningDelayType::All) => Some("all"), + Some(WarningDelayType::First) => Some("first"), + None => None, + }, + compare_property_unquoted_atom + ), + ( + EmacsField::Optional(":warning-unit"), + |r| match r.warning_delay.as_ref().map(|repeater| &repeater.unit) { + Some(TimeUnit::Hour) => Some("hour"), + Some(TimeUnit::Day) => Some("day"), + Some(TimeUnit::Week) => Some("week"), + Some(TimeUnit::Month) => Some("month"), + Some(TimeUnit::Year) => Some("year"), + None => None, + }, + compare_property_unquoted_atom + ), + ( + EmacsField::Optional(":warning-value"), + |r| r.warning_delay.as_ref().map(|repeater| repeater.value), + compare_property_numeric + ) + ) { + match diff { + ComparePropertiesResult::NoChange => {} + ComparePropertiesResult::SelfChange(new_status, new_message) => { + this_status = new_status; + message = new_message + } + ComparePropertiesResult::DiffEntry(diff_entry) => child_status.push(diff_entry), } } @@ -4280,7 +4173,7 @@ fn compare_timestamp<'b, 's>( status: this_status, name: rust.get_elisp_name(), message, - children: Vec::new(), + children: child_status, rust_source: rust.get_source(), emacs_token: emacs, }