1#![cfg_attr(coverage, feature(coverage_attribute))]
2#![allow(clippy::needless_return)]
3#![allow(clippy::needless_option_as_deref)]
4
5pub mod errors {
25 pub use anyhow::{anyhow, bail, Error, Result, Context};
26}
27
28pub mod interface;
29#[cfg(feature = "include-zip")]
30pub use shim_filesystem::ZIPPED_RULE_FILES;
31
32mod canonicalize;
33mod infer_intent;
34pub mod speech;
35mod braille;
36mod navigate;
37mod prefs;
38mod tts;
39mod xpath_functions;
40mod definitions;
41pub mod pretty_print;
42mod chemistry;
43
44pub mod shim_filesystem; pub use interface::*;
46use crate::errors::{bail, Result};
47
48#[cfg(test)]
49pub fn init_logger() {
50 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug"))
51 .is_test(true)
52 .format_timestamp(None)
53 .format_module_path(false)
54 .format_indent(None)
55 .format_level(false)
56 .init();
57}
58
59pub fn abs_rules_dir_path() -> String {
61 cfg_if::cfg_if! {
62 if #[cfg(feature = "include-zip")] {
63 return "Rules".to_string();
64 } else {
65 return std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
67 .join("Rules")
68 .to_str()
69 .expect("CARGO_MANIFEST_DIR and Rules path must be UTF-8")
70 .to_string();
71 }
72 }
73}
74
75pub fn are_strs_canonically_equal_with_locale(test: &str, target: &str, ignore_attrs: &[&str], block_separators: &str, decimal_separators: &str) -> Result<()> {
76 use crate::{interface::*, pretty_print::mml_to_string};
77 use sxd_document_no_unsafe::parser;
78 use crate::canonicalize::canonicalize;
79 use std::panic::{catch_unwind, AssertUnwindSafe};
80
81 crate::interface::init_panic_handler();
82 let result = catch_unwind(AssertUnwindSafe(|| {
83 crate::interface::set_rules_dir(abs_rules_dir_path()).unwrap();
85 set_preference("Language", "en").unwrap();
86 set_preference("BlockSeparators", block_separators).unwrap();
87 set_preference("DecimalSeparators", decimal_separators).unwrap();
88 crate::speech::SPEECH_RULES.with(|rules| rules.borrow_mut().read_files().unwrap());
89
90 let package1 = &parser::parse(test).expect("Failed to parse test input");
91 let mathml = get_element(package1);
92 trim_element(mathml, false);
93 let mathml_test = canonicalize(mathml).unwrap();
94
95 let package2 = &parser::parse(target).expect("Failed to parse target input");
96 let mathml_target = get_element(package2);
97 trim_element(mathml_target, false);
98
99 match is_same_element(mathml_test, mathml_target, ignore_attrs) {
100 Ok(_) => Ok( () ),
101 Err(e) => {
102 bail!("{}\nResult:\n{}\nTarget:\n{}", e, mml_to_string(mathml_test), mml_to_string(mathml_target));
103 },
104 }
105 }));
106 match crate::interface::report_any_panic(result) {
107 Ok(()) => Ok(()),
108 Err(e) => {
109 Err(e)
110 }
111 }
112}
113
114pub fn are_strs_canonically_equal(test: &str, target: &str, ignore_attrs: &[&str]) -> bool {
116 are_strs_canonically_equal_with_locale(test, target, ignore_attrs, ", \u{00A0}\u{202F}", ".").is_ok()
117}
118
119pub fn are_strs_canonically_equal_result(test: &str, target: &str, ignore_attrs: &[&str]) -> Result<()> {
121 are_strs_canonically_equal_with_locale(test, target, ignore_attrs, ", \u{00A0}\u{202F}", ".")
122}