sakurs_core/api/
processor.rs1use std::io::Read;
4use std::sync::Arc;
5use std::time::Instant;
6
7use crate::api::{Config, Error, Input, Language, Output};
8use crate::application::{DeltaStackProcessor, ExecutionMode, ProcessorConfig};
9use crate::domain::language::{ConfigurableLanguageRules, LanguageRules};
10
11pub struct SentenceProcessor {
13 processor: DeltaStackProcessor,
14 config: Config,
15}
16
17impl SentenceProcessor {
18 pub fn new() -> Self {
20 Self::with_config(Config::default()).expect("Default config should always be valid")
21 }
22
23 pub fn with_config(config: Config) -> Result<Self, Error> {
25 let language_rules = Self::create_language_rules(&config.language);
26 let processor_config = Self::build_processor_config(&config)?;
27 let processor = DeltaStackProcessor::new(processor_config, language_rules);
28
29 Ok(Self { processor, config })
30 }
31
32 pub fn with_custom_rules(
34 config: Config,
35 language_rules: Arc<dyn LanguageRules>,
36 ) -> Result<Self, Error> {
37 let processor_config = Self::build_processor_config(&config)?;
38 let processor = DeltaStackProcessor::new(processor_config, language_rules);
39
40 Ok(Self { processor, config })
41 }
42
43 pub fn with_language(lang_code: impl Into<String>) -> Result<Self, Error> {
45 let config = Config::builder().language(lang_code)?.build()?;
46 Self::with_config(config)
47 }
48
49 fn create_language_rules(language: &Language) -> Arc<dyn LanguageRules> {
51 match language {
52 Language::English => Arc::new(
53 ConfigurableLanguageRules::from_code("en")
54 .expect("English configuration should be embedded"),
55 ),
56 Language::Japanese => Arc::new(
57 ConfigurableLanguageRules::from_code("ja")
58 .expect("Japanese configuration should be embedded"),
59 ),
60 }
61 }
62
63 pub fn process(&self, input: Input) -> Result<Output, Error> {
65 let start = Instant::now();
66
67 let text = input.into_text()?;
69
70 let mode = if let Some(threads) = self.config.threads {
72 if threads == 1 {
73 ExecutionMode::Sequential
74 } else {
75 ExecutionMode::Parallel {
76 threads: Some(threads),
77 }
78 }
79 } else {
80 ExecutionMode::Adaptive
81 };
82
83 let result = self.processor.process(&text, mode)?;
85
86 let duration = start.elapsed();
88 Ok(Output::from_delta_stack_result(result, &text, duration))
89 }
90
91 pub fn process_stream<R: Read + Send + Sync + 'static>(
93 &self,
94 reader: R,
95 ) -> Result<Output, Error> {
96 self.process(Input::from_reader(reader))
97 }
98
99 pub fn config(&self) -> &Config {
101 &self.config
102 }
103
104 fn build_processor_config(config: &Config) -> Result<ProcessorConfig, Error> {
106 Ok(ProcessorConfig {
107 chunk_size: config.chunk_size,
108 parallel_threshold: config.parallel_threshold,
109 max_threads: config.threads,
110 overlap_size: config.overlap_size,
111 })
112 }
113}
114
115impl Default for SentenceProcessor {
116 fn default() -> Self {
117 Self::new()
118 }
119}