Lookup unicode "pronunciation" of char. Note: TTS is not supported here (not needed and a little less efficient)
(&'r mut self, str: &str, mathml: Element<'c>)
| 2425 | /// Lookup unicode "pronunciation" of char. |
| 2426 | /// Note: TTS is not supported here (not needed and a little less efficient) |
| 2427 | pub fn replace_chars(&'r mut self, str: &str, mathml: Element<'c>) -> Result<String> { |
| 2428 | if is_quoted_string(str) { |
| 2429 | return Ok(unquote_string(str).to_string()); |
| 2430 | } |
| 2431 | let rules = self.speech_rules; |
| 2432 | let mut chars = str.chars(); |
| 2433 | // in a string, avoid "a" -> "eigh", "." -> "point", etc |
| 2434 | if rules.translate_single_chars_only { |
| 2435 | let ch = chars.next().unwrap_or(' '); |
| 2436 | if chars.next().is_none() { |
| 2437 | // single char |
| 2438 | return replace_single_char(self, ch, mathml) |
| 2439 | } else { |
| 2440 | // more than one char -- fix up non-breaking space |
| 2441 | return Ok(str.replace('\u{00A0}', " ").replace(['\u{2061}', '\u{2062}', '\u{2063}', '\u{2064}'], "")); |
| 2442 | } |
| 2443 | }; |
| 2444 | |
| 2445 | let result = chars |
| 2446 | .map(|ch| replace_single_char(self, ch, mathml)) |
| 2447 | .collect::<Result<Vec<String>>>()? |
| 2448 | .join(""); |
| 2449 | return Ok( result ); |
| 2450 | |
| 2451 | fn replace_single_char<'c, 's:'c, 'm, 'r>(rules_with_context: &'r mut SpeechRulesWithContext<'c,'s,'m>, ch: char, mathml: Element<'c>) -> Result<String> { |
| 2452 | let ch_as_u32 = ch as u32; |
| 2453 | let mut unicode = rules_with_context.speech_rules.unicode_short.borrow(); |
| 2454 | let mut replacements = unicode.get( &ch_as_u32 ); |
| 2455 | if replacements.is_none() { |
| 2456 | // see if it in the full unicode table (if it isn't loaded already) |
| 2457 | if rules_with_context.speech_rules.unicode_full.borrow().is_empty() { |
| 2458 | info!("*** Loading full unicode {} for char '{}'/{:#06x}", rules_with_context.speech_rules.name, ch, ch_as_u32); |
| 2459 | rules_with_context.speech_rules.read_unicode(None, false)?; |
| 2460 | info!("# Unicode defs = {}/{}", rules_with_context.speech_rules.unicode_short.borrow().len(), rules_with_context.speech_rules.unicode_full.borrow().len()); |
| 2461 | |
| 2462 | } |
| 2463 | unicode = rules_with_context.speech_rules.unicode_full.borrow(); |
| 2464 | replacements = unicode.get( &ch_as_u32 ); |
| 2465 | if replacements.is_none() { |
| 2466 | // debug!("*** Did not find unicode {} for char '{}'/{:#06x}", rules_with_context.speech_rules.name, ch, ch_as_u32); |
| 2467 | rules_with_context.translate_count = 0; // not in loop |
| 2468 | return Ok(String::from(ch)); // no replacement, so just return the char and hope for the best |
| 2469 | } |
| 2470 | }; |
| 2471 | |
| 2472 | // map across all the parts of the replacement, collect them up into a Vec, and then concat them together |
| 2473 | let result = replacements.unwrap() |
| 2474 | .iter() |
| 2475 | .map(|replacement| |
| 2476 | rules_with_context.replace(replacement, mathml) |
| 2477 | .chain_err(|| format!("Unicode replacement error: {}", replacement)) ) |
| 2478 | .collect::<Result<Vec<String>>>()? |
| 2479 | .join(" "); |
| 2480 | rules_with_context.translate_count = 0; // found a replacement, so not in a loop |
| 2481 | return Ok(result); |
| 2482 | } |
| 2483 | } |
| 2484 | } |
no test coverage detected