Skip to content

Commit a45297c

Browse files
committed
Second try to add a no-unsafe flag. This is better than the first attempt, but there are still areas for improvement. Getting this commited because AI has twice suggested wiping this out and starting over to fix some minor problem.
Both version compile and have the same problems with the navigation tests (which still need to be fixed from earlier). The indentation is badly messed up in places.
1 parent 73eb202 commit a45297c

File tree

10 files changed

+393
-336
lines changed

10 files changed

+393
-336
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ exclude = ["src/main.rs", "docs", "PythonScripts"] # should have "Rules/", bu
1515
"include-zip" = []
1616
"enable-logs" = ["android_logger"]
1717
"tts" = [ "natural-tts" ]
18+
"no-unsafe" = ["sxd-document/no-unsafe", "sxd-xpath/no-unsafe"]
1819

1920

2021
[dependencies]
21-
sxd-document = "0.3"
22-
sxd-xpath = "0.4"
22+
sxd-document = { path = "../sxd-document" }
23+
sxd-xpath = { path = "../sxd-xpath-no-unsafe" }
2324
yaml-rust = "0.4"
2425
# yaml-rust = { version = "0.11", package = "yaml-rust2" }
2526
strum = "0.27.2"

src/braille.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use strum_macros::Display;
33
use sxd_document::dom::{Element, ChildOfElement};
44
use sxd_document::Package;
5+
use sxd_document::{as_str, as_opt_str};
56
use crate::definitions::SPEECH_DEFINITIONS;
67
use crate::errors::*;
78
use crate::pretty_print::mml_to_string;
@@ -326,7 +327,8 @@ pub fn get_navigation_node_from_braille_position(mathml: Element, position: usiz
326327
/// find the navigation node that most tightly encapsulates the target position (0-based)
327328
/// 'node' is the current node we are on inside of 'mathml'
328329
fn find_navigation_node<'e>(mathml: Element<'e>, node: Element<'e>, target_position: usize) -> Result<SearchState<'e>> {
329-
let node_id = match node.attribute_value("id") {
330+
let raw_node_id = node.attribute_value("id");
331+
let node_id = match as_opt_str!(raw_node_id) {
330332
Some(id) => id,
331333
None => bail!("'id' is not present on mathml: {}", mml_to_string(node)),
332334
};
@@ -444,7 +446,7 @@ pub fn get_navigation_node_from_braille_position(mathml: Element, position: usiz
444446
return BRAILLE_DEFINITIONS.with(|definitions| {
445447
let definitions = definitions.borrow();
446448
let comparison_operators = definitions.get_hashset("ComparisonOperators").unwrap();
447-
return comparison_operators.contains(as_text(node));
449+
return comparison_operators.contains(as_str!(as_text(node)));
448450
});
449451
}
450452

@@ -478,7 +480,7 @@ pub fn get_navigation_node_from_braille_position(mathml: Element, position: usiz
478480

479481
fn estimate_braille_chars(child: ChildOfElement, n_number_indicator: usize) -> usize {
480482
let node = as_element(child);
481-
let leaf_name = name(node);
483+
let leaf_name = as_str!(name(node));
482484
if is_leaf(node) {
483485
let text = as_text(node);
484486
// len() is close since mn's probably have ASCII digits and lower case vars are common (count as) and other chars need extra braille chars
@@ -2238,7 +2240,7 @@ impl NemethNestingChars {
22382240
max_value += repeat_char;
22392241
node.set_attribute_value(NEMETH_FRAC_LEVEL, &max_value);
22402242
return max_value;
2241-
} else if FIRST_CHILD_ONLY.contains(&name) {
2243+
} else if FIRST_CHILD_ONLY.contains(&as_str!(name)) {
22422244
// only look at the base -- ignore scripts/index
22432245
return NemethNestingChars::nemeth_frac_value(as_element(children[0]), repeat_char);
22442246
} else {
@@ -2273,11 +2275,11 @@ impl NemethNestingChars {
22732275
if let ParentOfChild::Element(e) = parent_of_child {
22742276
parent = e;
22752277
} else {
2276-
return Err( sxd_xpath::function::Error::Other("Internal error in nemeth_root_value: didn't find 'math' tag".to_string()) );
2278+
return Err( sxd_xpath::function::Error::Other { what: "Internal error in nemeth_root_value: didn't find 'math' tag".to_string() } );
22772279
}
22782280
}
22792281
}
2280-
return Err( XPathError::Other("Internal error in nemeth_root_value: didn't find 'math' tag".to_string()) );
2282+
return Err( XPathError::Other { what: "Internal error in nemeth_root_value: didn't find 'math' tag".to_string() } );
22812283
}
22822284
}
22832285

@@ -2308,7 +2310,7 @@ impl Function for NemethNestingChars {
23082310
} else if name == "msqrt" || name == "mroot" {
23092311
return Ok( Value::String( NemethNestingChars::nemeth_root_value(el, &repeat_char)? ) );
23102312
} else {
2311-
return Err(XPathError::Other(format!("NestingChars chars should be used only on 'mfrac'. '{}' was passed in", name)));
2313+
return Err(XPathError::Other { what: format!("NestingChars chars should be used only on 'mfrac'. '{}' was passed in", name) });
23122314
}
23132315
} else {
23142316
// not an element, so nothing to do
@@ -2330,11 +2332,11 @@ impl BrailleChars {
23302332
"Vietnam" => BrailleChars:: get_braille_vietnam_chars(node, text_range),
23312333
"Swedish" => BrailleChars:: get_braille_ueb_chars(node, text_range), // FIX: need to figure out what to implement
23322334
"Finnish" => BrailleChars:: get_braille_ueb_chars(node, text_range), // FIX: need to figure out what to implement
2333-
_ => return Err(sxd_xpath::function::Error::Other(format!("get_braille_chars: unknown braille code '{code}'")))
2335+
_ => return Err(sxd_xpath::function::Error::Other { what: format!("get_braille_chars: unknown braille code '{code}'") })
23342336
};
23352337
return match result {
23362338
Ok(string) => Ok(make_quoted_string(string)),
2337-
Err(err) => return Err(sxd_xpath::function::Error::Other(err.to_string())),
2339+
Err(err) => return Err(sxd_xpath::function::Error::Other { what: err.to_string() }),
23382340
}
23392341
}
23402342

@@ -2346,8 +2348,8 @@ impl BrailleChars {
23462348
static PICK_APART_CHAR: LazyLock<Regex> = LazyLock::new(|| {
23472349
Regex::new(r"(?P<face>[SB𝔹TIR]*)(?P<lang>[EDGVHU]?)(?P<cap>C?)(?P<letter>L?)(?P<num>[N]?)(?P<char>.)").unwrap()
23482350
});
2349-
let math_variant = node.attribute_value("mathvariant");
2350-
// FIX: cover all the options -- use phf::Map
2351+
let raw_math_variant = node.attribute_value("mathvariant");
2352+
let math_variant = as_opt_str!(raw_math_variant);
23512353
let attr_typeface = match math_variant {
23522354
None => "R",
23532355
Some(variant) => match variant {
@@ -2360,7 +2362,7 @@ impl BrailleChars {
23602362
_ => "R", // normal and unknown
23612363
},
23622364
};
2363-
let text = BrailleChars::substring(as_text(node), &text_range);
2365+
let text = BrailleChars::substring(as_str!(as_text(node)), &text_range);
23642366
let braille_chars = braille_replace_chars(&text, node)?;
23652367
// debug!("Nemeth chars: text='{}', braille_chars='{}'", &text, &braille_chars);
23662368

@@ -2422,8 +2424,9 @@ impl BrailleChars {
24222424
Regex::new(r"(?P<bold>B??)(?P<italic>I??)(?P<face>[S𝔹TD]??)s??(?P<cap>C??)(?P<greek>G??)(?P<char>[NL].)").unwrap()
24232425
});
24242426

2425-
let math_variant = node.attribute_value("mathvariant");
2426-
let text = BrailleChars::substring(as_text(node), &text_range);
2427+
let raw_math_variant = node.attribute_value("mathvariant");
2428+
let math_variant = as_opt_str!(raw_math_variant);
2429+
let text = BrailleChars::substring(as_str!(as_text(node)), &text_range);
24272430
let mut braille_chars = braille_replace_chars(&text, node)?;
24282431

24292432
// debug!("get_braille_ueb_chars: before/after unicode.yaml: '{}'/'{}'", text, braille_chars);
@@ -2475,8 +2478,9 @@ impl BrailleChars {
24752478
Regex::new(r"(?P<bold>B??)(?P<italic>I??)(?P<face>[S𝔹TD]??)s??(?P<cap>C??)(?P<greek>G??)(?P<char>[NL].)").unwrap()
24762479
});
24772480

2478-
let math_variant = node.attribute_value("mathvariant");
2479-
let text = BrailleChars::substring(as_text(node), &text_range);
2481+
let raw_math_variant = node.attribute_value("mathvariant");
2482+
let math_variant = as_opt_str!(raw_math_variant);
2483+
let text = BrailleChars::substring(as_str!(as_text(node)), &text_range);
24802484
let text = add_separator(text);
24812485

24822486
let braille_chars = braille_replace_chars(&text, node)?;
@@ -2609,13 +2613,14 @@ impl BrailleChars {
26092613
return false;
26102614

26112615
fn child_meets_conditions(node: Element) -> bool {
2612-
let name = name(node);
2616+
let name = as_str!(name(node));
26132617
return match name {
26142618
"mi" | "mn" => true,
26152619
"mo" => !crate::canonicalize::is_relational_op(node),
26162620
"mtext" => {
2617-
let text = as_text(node).trim();
2618-
return text=="?" || text=="-?-" || text.is_empty(); // various forms of "fill in missing content" (see also Nemeth_RULEs.yaml, "omissions")
2621+
let raw_text = as_text(node);
2622+
let text = raw_text.trim();
2623+
return text=="?" || text=="-?-" || text.is_empty();
26192624
},
26202625
"mrow" => {
26212626
if IsBracketed::is_bracketed(node, "", "", false, false) {
@@ -2630,7 +2635,7 @@ impl BrailleChars {
26302635
true
26312636
},
26322637
"menclose" => {
2633-
if let Some(notation) = node.attribute_value("notation") {
2638+
if let Some(notation) = as_opt_str!(node.attribute_value("notation")) {
26342639
if notation != "bottom" || notation != "box" {
26352640
return false;
26362641
}
@@ -2675,7 +2680,7 @@ impl Function for BrailleChars {
26752680
use crate::canonicalize::create_mathml_element;
26762681
let mut args = Args(args);
26772682
if let Err(e) = args.exactly(2).or_else(|_| args.exactly(4)) {
2678-
return Err( XPathError::Other(format!("BrailleChars requires 2 or 4 args: {e}")));
2683+
return Err( XPathError::Other { what: format!("BrailleChars requires 2 or 4 args: {e}") });
26792684
};
26802685

26812686
let range = if args.len() == 4 {
@@ -2707,7 +2712,7 @@ impl Function for BrailleChars {
27072712
};
27082713

27092714
if !is_leaf(node) {
2710-
return Err( XPathError::Other(format!("BrailleChars called on non-leaf element '{}'", mml_to_string(node))) );
2715+
return Err( XPathError::Other { what: format!("BrailleChars called on non-leaf element '{}'", mml_to_string(node)) } );
27112716
}
27122717
return Ok( Value::String( BrailleChars::get_braille_chars(node, &braille_code, range)? ) );
27132718
}
@@ -2773,7 +2778,7 @@ impl NeedsToBeGrouped {
27732778
/// FIX: what needs to be implemented?
27742779
fn needs_grouping_for_finnish(mathml: Element, is_base: bool) -> bool {
27752780
use crate::xpath_functions::IsInDefinition;
2776-
let mut node_name = name(mathml);
2781+
let mut node_name = as_str!(name(mathml));
27772782
if mathml.attribute_value("data-roman-numeral").is_some() {
27782783
node_name = "mi"; // roman numerals don't follow number rules
27792784
}
@@ -2804,7 +2809,7 @@ impl NeedsToBeGrouped {
28042809
}
28052810
},
28062811
"mi" | "mo" | "mtext" => {
2807-
let text = as_text(mathml);
2812+
let text = as_str!(as_text(mathml));
28082813
let parent = get_parent(mathml); // there is always a "math" node
28092814
let parent_name = name(parent); // there is always a "math" node
28102815
if is_base && (parent_name == "msub" || parent_name == "msup" || parent_name == "msubsup") && !text.contains([' ', '\u{00A0}']) {
@@ -2864,15 +2869,15 @@ impl NeedsToBeGrouped {
28642869
// if the number is irregular, return the ordinal form, otherwise return 'None'.
28652870
fn needs_grouping_for_swedish(mathml: Element, is_base: bool) -> bool {
28662871
use crate::xpath_functions::IsInDefinition;
2867-
let mut node_name = name(mathml);
2872+
let mut node_name = as_str!(name(mathml));
28682873
if mathml.attribute_value("data-roman-numeral").is_some() {
28692874
node_name = "mi"; // roman numerals don't follow number rules
28702875
}
28712876

28722877
match node_name {
28732878
"mn" => return false,
28742879
"mi" | "mo" | "mtext" => {
2875-
let text = as_text(mathml);
2880+
let text = as_str!(as_text(mathml));
28762881
let parent = get_parent(mathml); // there is always a "math" node
28772882
let parent_name = name(parent); // there is always a "math" node
28782883
if is_base && (parent_name == "msub" || parent_name == "msup" || parent_name == "msubsup") && !text.contains([' ', '\u{00A0}']) {
@@ -2931,7 +2936,7 @@ impl NeedsToBeGrouped {
29312936
// 8. If none of the foregoing apply, the item is simply the [this element's] individual symbol.
29322937

29332938
use crate::xpath_functions::IsInDefinition;
2934-
let mut node_name = name(mathml);
2939+
let mut node_name = as_str!(name(mathml));
29352940
if mathml.attribute_value("data-roman-numeral").is_some() {
29362941
node_name = "mi"; // roman numerals don't follow number rules
29372942
}
@@ -2960,7 +2965,7 @@ impl NeedsToBeGrouped {
29602965
}
29612966
},
29622967
"mi" | "mo" | "mtext" => {
2963-
let text = as_text(mathml);
2968+
let text = as_str!(as_text(mathml));
29642969
let parent = get_parent(mathml); // there is always a "math" node
29652970
let parent_name = name(parent); // there is always a "math" node
29662971
if is_base && (parent_name == "msub" || parent_name == "msup" || parent_name == "msubsup") && !text.contains([' ', '\u{00A0}']) {
@@ -3016,12 +3021,12 @@ impl Function for NeedsToBeGrouped {
30163021
"UEB" => NeedsToBeGrouped::needs_grouping_for_ueb(e, is_base),
30173022
"Finnish" => NeedsToBeGrouped::needs_grouping_for_finnish(e, is_base),
30183023
"Swedish" => NeedsToBeGrouped::needs_grouping_for_swedish(e, is_base),
3019-
_ => return Err(XPathError::Other(format!("NeedsToBeGrouped: braille code arg '{braille_code:?}' is not a known code ('UEB', 'CMU', or 'Swedish')"))),
3024+
_ => return Err(XPathError::Other { what: format!("NeedsToBeGrouped: braille code arg '{braille_code:?}' is not a known code ('UEB', 'CMU', or 'Swedish')") }),
30203025
};
30213026
return Ok( Value::Boolean( answer ) );
30223027
}
30233028

3024-
return Err(XPathError::Other(format!("NeedsToBeGrouped: first arg '{node:?}' is not a node")));
3029+
return Err(XPathError::Other { what: format!("NeedsToBeGrouped: first arg '{node:?}' is not a node") });
30253030
}
30263031
}
30273032

0 commit comments

Comments
 (0)