diff --git a/src/wasm/table.rs b/src/wasm/table.rs index 8b964845..34b8b048 100644 --- a/src/wasm/table.rs +++ b/src/wasm/table.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; + use serde::Deserialize; use serde::Serialize; @@ -6,6 +8,7 @@ use super::macros::to_wasm; use super::to_wasm::ToWasm; use super::AdditionalProperties; use crate::compare::ElispFact; +use crate::types::GetAffiliatedKeywords; use crate::types::Table; use crate::wasm::to_wasm::ToWasmStandardProperties; @@ -13,6 +16,18 @@ use crate::wasm::to_wasm::ToWasmStandardProperties; pub struct WasmTable { #[serde(flatten)] pub(crate) additional_properties: AdditionalProperties, + #[serde(rename = "tblfm")] + pub(crate) formulas: Option, + #[serde(rename = "type")] + pub(crate) table_type: String, + pub(crate) value: Option, // Always None +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "string-set")] +#[serde(rename = "string-set")] +struct WasmStringSet { + value: BTreeSet, } to_wasm!( @@ -21,8 +36,12 @@ to_wasm!( original, wasm_context, { WasmAstNode::Table(original) }, - { "TODO".into() }, + { "table".into() }, { + let additional_properties = original + .get_affiliated_keywords() + .to_wasm(wasm_context.clone())?; + let children = original .children .iter() @@ -36,7 +55,20 @@ to_wasm!( Ok(( children, WasmTable { - additional_properties: AdditionalProperties::default(), + additional_properties, + formulas: if original.formulas.is_empty() { + None + } else { + Some(WasmStringSet { + value: original + .formulas + .iter() + .map(|kw| kw.value.to_owned()) + .collect(), + }) + }, + table_type: "org".to_owned(), + value: None, }, )) } diff --git a/src/wasm_test/compare.rs b/src/wasm_test/compare.rs index f93fcbf8..cf5fb317 100644 --- a/src/wasm_test/compare.rs +++ b/src/wasm_test/compare.rs @@ -1,4 +1,6 @@ +use std::borrow::Borrow; use std::borrow::Cow; +use std::collections::BTreeSet; use std::collections::HashMap; use super::diff::WasmDiffResult; @@ -58,6 +60,10 @@ fn compare_json_value<'b, 's>( // We hit an object tree additional property. compare_number_lines(source, el, wasm) } + (serde_json::Value::Object(wasm), Token::List(el)) if wasm.contains_key("string-set") => { + // We hit an object tree additional property. + compare_string_set(source, el, wasm) + } (serde_json::Value::Object(w), Token::TextWithProperties(e)) if is_plain_text(w) => { compare_plain_text(source, e, w) } @@ -719,6 +725,50 @@ fn compare_number_lines<'e, 's, 'w>( Ok(result) } +fn compare_string_set<'e, 's, 'w>( + source: &'s str, + emacs: &'e Vec>, + wasm: &'w serde_json::Map, +) -> Result, Box> { + let mut result = WasmDiffResult::default(); + let wasm_list = wasm + .get("value") + .ok_or(r#"Wasm string set should have a "value" attribute."#)? + .as_array() + .ok_or(r#"Wasm string set "value" attribute should be a list."#)?; + let wasm_strings = wasm_list + .iter() + .map(|v| v.as_str().ok_or("Non-string in wasm string set.")) + .collect::, &'static str>>()?; + let emacs_strings = emacs + .iter() + .map(|v| v.as_atom()) + .collect::, Box>>()? + .into_iter() + .map(|s| unquote(s)) + .collect::, Box>>()?; + let emacs_strings = emacs_strings + .iter() + .map(|s| s.borrow()) + .collect::>(); + + let mismatched: Vec<_> = emacs_strings + .symmetric_difference(&wasm_strings) + .copied() + .collect(); + if !mismatched.is_empty() { + result.status.push(WasmDiffStatus::Bad( + format!( + "String set mismatch. MismatchedValues=({values:?}).", + values = mismatched.join(", ") + ) + .into(), + )); + } + + Ok(result) +} + fn is_plain_text<'e, 's, 'w>(wasm: &'w serde_json::Map) -> bool { if let Some(serde_json::Value::String(node_type)) = wasm.get("ast-node") { node_type == "plain-text"