Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repository = "https://github.com/NSoiffer/MathCAT"
homepage = "https://nsoiffer.github.io/MathCAT/"
documentation = "https://nsoiffer.github.io/MathCAT/"
edition = "2018"
exclude = ["src/main.rs", "docs", "PythonScripts"] # should have "Rules/", but then one can't run build.rs to build the zip file
exclude = ["src/main.rs", "examples/**", "docs", "PythonScripts"] # should have "Rules/", but then one can't run build.rs to build the zip file


[features]
Expand Down
106 changes: 106 additions & 0 deletions examples/stateless-example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use env_logger;
use lazy_static::lazy_static;
use libmathcat::{errors::Error, stateless_interface::*};
use std::{ops::Deref, path::Path, sync::mpsc, thread};

const EXPR_1: &'static str = r#"<math><mrow><msup><mi>sin</mi><mn>2</mn></msup><mo>⁡</mo><mspace></mspace><mi>x</mi></mrow></math>"#;
const EXPR_2: &'static str = r#"<math><mrow><msup><mi>cos</mi><mn>2</mn></msup><mo>⁡</mo><mspace></mspace><mi>x</mi></mrow></math>"#;

struct MathCatHolder {
language: &'static str,
mathcat: MathCat,
}

// `mathcat` is full of RCs, need to figure out what to do here to explain to Rust
// that it's OK to use a non-mut MathCat across threads because all Rcs are actually
// owned by the `MathCat` instance.
unsafe impl Sync for MathCatHolder {}

fn build_mathcat(language: &'static str) -> Result<MathCatHolder, Error> {
let rules_dir = std::env::current_exe().unwrap().parent().unwrap().join("../../../Rules");
let rules_dir = rules_dir.as_os_str().to_str().unwrap().to_string();

let mut builder = MathCatBuilder::new();
builder.set_rules_dir(Path::new(&rules_dir));
builder.set_pref("Language", language);
Ok(MathCatHolder { language: language, mathcat: builder.build()? })
}

fn main() -> Result<(), Error> {
// Run with RUST_LOG=debug to see some debugging information.l
env_logger::builder()
.format_timestamp(None)
.format_module_path(false)
.format_indent(Some(2))
.format_level(false)
.init();

lazy_static! {
static ref mathcat_en: MathCatHolder = build_mathcat("en").unwrap();
static ref mathcat_es: MathCatHolder = build_mathcat("es").unwrap();
}

// Initialization is not thread-safe, ensure everything is initialized:
let _ = mathcat_en.deref();
let _ = mathcat_es.deref();

// Once initialized, MathCat instances are thread-compatible.
let (tx, rx) = mpsc::channel();
let mut threads = Vec::<thread::JoinHandle<Result<(), mpsc::SendError<(&'static str, Result<String, libmathcat::errors::Error>)>>>>::new();
{
let tx = tx.clone();
threads.push(thread::spawn(move || {
tx.send((
mathcat_en.language,
mathcat_en.mathcat.mathml_to_spoken_text(EXPR_1)))
}));
}
{
let tx = tx.clone();
threads.push(thread::spawn(move || {
tx.send((
mathcat_en.language,
mathcat_en.mathcat.mathml_to_spoken_text(EXPR_2)))
}));
}
{
let tx = tx.clone();
threads.push(thread::spawn(move || {
tx.send((
mathcat_es.language,
mathcat_es.mathcat.mathml_to_spoken_text(EXPR_1)))
}));
}
{
let tx = tx.clone();
threads.push(thread::spawn(move || {
tx.send((
mathcat_es.language,
mathcat_es.mathcat.mathml_to_spoken_text(EXPR_2)))
}));
}

let rcv_thread = thread::spawn(move || {
let mut pending = 4;
let mut has_errors = false;
while let Ok((language, result)) = rx.recv() {
match result {
Ok(text) => println!("{}: {}", language, text),
Err(e) => {
has_errors = true;
println!("{}: Error!\n{:?}", language, e);
}
};
pending -= 1;
if pending == 0 { break; }
}
has_errors
});

for thread in threads {
let _ = thread.join().unwrap();
}
let has_errors = rcv_thread.join().unwrap();
if has_errors { std::process::exit(1); }
Ok(())
}
59 changes: 31 additions & 28 deletions src/braille.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,38 @@ pub fn braille_mathml(mathml: Element, nav_node_id: &str) -> Result<(String, usi
return BRAILLE_RULES.with(|rules| {
rules.borrow_mut().read_files()?;
let rules = rules.borrow();
let new_package = Package::new();
let mut rules_with_context = SpeechRulesWithContext::new(&rules, new_package.as_document(), nav_node_id);
let braille_string = rules_with_context.match_pattern::<String>(mathml)
.chain_err(|| "Pattern match/replacement failure!")?;
// debug!("braille_mathml: braille string: {}", &braille_string);
let braille_string = braille_string.replace(' ', "");
let pref_manager = rules_with_context.get_rules().pref_manager.borrow();
let highlight_style = pref_manager.pref_to_string("BrailleNavHighlight");
let braille_code = pref_manager.pref_to_string("BrailleCode");
let braille = match braille_code.as_str() {
"Nemeth" => nemeth_cleanup(pref_manager, braille_string),
"UEB" => ueb_cleanup(pref_manager, braille_string),
"Vietnam" => vietnam_cleanup(pref_manager, braille_string),
"CMU" => cmu_cleanup(pref_manager, braille_string),
"Finnish" => finnish_cleanup(pref_manager, braille_string),
"Swedish" => swedish_cleanup(pref_manager, braille_string),
"LaTeX" => LaTeX_cleanup(pref_manager, braille_string),
"ASCIIMath" => ASCIIMath_cleanup(pref_manager, braille_string),
_ => braille_string.trim_matches('⠀').to_string(), // probably needs cleanup if someone has another code, but this will have to get added by hand
};
return SPEECH_DEFINITIONS.with_borrow(|definitions| {
let new_package = Package::new();
let mut rules_with_context =
SpeechRulesWithContext::new(&rules, definitions, new_package.as_document(), nav_node_id);
let braille_string = rules_with_context.match_pattern::<String>(mathml)
.chain_err(|| "Pattern match/replacement failure!")?;
// debug!("braille_mathml: braille string: {}", &braille_string);
let braille_string = braille_string.replace(' ', "");
let pref_manager = rules_with_context.get_rules().pref_manager.borrow();
let highlight_style = pref_manager.pref_to_string("BrailleNavHighlight");
let braille_code = pref_manager.pref_to_string("BrailleCode");
let braille = match braille_code.as_str() {
"Nemeth" => nemeth_cleanup(pref_manager, braille_string),
"UEB" => ueb_cleanup(pref_manager, braille_string),
"Vietnam" => vietnam_cleanup(pref_manager, braille_string),
"CMU" => cmu_cleanup(pref_manager, braille_string),
"Finnish" => finnish_cleanup(pref_manager, braille_string),
"Swedish" => swedish_cleanup(pref_manager, braille_string),
"LaTeX" => LaTeX_cleanup(pref_manager, braille_string),
"ASCIIMath" => ASCIIMath_cleanup(pref_manager, braille_string),
_ => braille_string.trim_matches('⠀').to_string(), // probably needs cleanup if someone has another code, but this will have to get added by hand
};

return Ok(
if highlight_style != "Off" {
highlight_braille_chars(braille, &braille_code, highlight_style == "All")
} else {
let end = braille.len()/3;
(braille, 0, end)
}
);
return Ok(
if highlight_style != "Off" {
highlight_braille_chars(braille, &braille_code, highlight_style == "All")
} else {
let end = braille.len()/3;
(braille, 0, end)
}
);
});
});

/// highlight with dots 7 & 8 based on the highlight style
Expand Down
Loading