use crate::G2pToken;
use crate::error::Result;
use crate::semantic::{Language, SentenceUnit};
use std::sync::Arc;
use super::{Entry, Renderer, load_phoneme_data, promote_clauses, stable_cut_index};
pub struct StreamingSentencePhonemeUpgrade {
language: Language,
phdata: Arc<crate::phoneme::PhonemeData>,
}
impl StreamingSentencePhonemeUpgrade {
pub fn new(language: Language) -> Result<Self> {
let phdata = load_phoneme_data(language)?;
Ok(Self { language, phdata })
}
pub fn new_session(&self) -> StreamingSentencePhonemeUpgradeSession {
StreamingSentencePhonemeUpgradeSession {
language: self.language,
phdata: Arc::clone(&self.phdata),
pending: Vec::new(),
renderer: Renderer::new(self.language),
clause_has_primary_stress: false,
}
}
}
pub struct StreamingSentencePhonemeUpgradeSession {
language: Language,
phdata: Arc<crate::phoneme::PhonemeData>,
pending: Vec<Entry>,
renderer: Renderer,
clause_has_primary_stress: bool,
}
impl StreamingSentencePhonemeUpgradeSession {
pub fn push(&mut self, unit: SentenceUnit) -> Vec<G2pToken> {
let output = self.push_units(unit);
self.renderer.render_partial(&output, &self.phdata)
}
pub fn finish(&mut self) -> Vec<G2pToken> {
let output = self.flush_pending();
self.renderer.render(&output, &self.phdata)
}
fn push_units(&mut self, unit: SentenceUnit) -> Vec<SentenceUnit> {
if matches!(unit, SentenceUnit::ClauseBoundary(_)) {
let mut output = self.flush_pending();
output.push(unit);
self.clause_has_primary_stress = false;
return output;
}
self.pending.push(Entry::from_sentence_unit(&unit));
let cutoff = stable_cut_index(&self.pending, false);
let mut working = self.pending.clone();
promote_clauses(&mut working, &self.phdata, false);
let mut output = Vec::new();
for entry in working.drain(0..cutoff) {
if entry.has_primary_stress() {
self.clause_has_primary_stress = true;
}
output.push(entry.convert_to_sentence_unit(self.language, &self.phdata));
}
self.pending.drain(0..cutoff);
output
}
fn flush_pending(&mut self) -> Vec<SentenceUnit> {
if self.pending.is_empty() {
return Vec::new();
}
let mut working = self.pending.clone();
promote_clauses(&mut working, &self.phdata, self.clause_has_primary_stress);
let mut output = Vec::with_capacity(self.pending.len());
for entry in working {
output.push(entry.convert_to_sentence_unit(self.language, &self.phdata));
}
self.pending.clear();
output
}
}