Skip to main content

ass_core/analysis/events/text_analysis/
analysis.rs

1//! `TextAnalysis` type definition and analysis entry points.
2//!
3//! Defines the [`TextAnalysis`] result structure plus the public `analyze`
4//! constructors. The bulk of the parsing logic lives in the `parser` submodule
5//! and the accessors plus Unicode helpers live in the `helpers` submodule.
6
7use crate::{
8    analysis::events::tags::{OverrideTag, TagDiagnostic},
9    Result,
10};
11
12#[cfg(feature = "plugins")]
13use crate::plugin::ExtensionRegistry;
14use alloc::{string::String, vec::Vec};
15
16/// Analysis results for dialogue text content
17///
18/// Contains extracted plain text, override tag information, and Unicode
19/// complexity indicators. Uses zero-copy references where possible.
20#[derive(Debug, Clone)]
21pub struct TextAnalysis<'a> {
22    /// Plain text with override tags removed
23    pub(super) plain_text: String,
24    /// Unicode character count
25    pub(super) char_count: usize,
26    /// Line count after processing linebreaks
27    pub(super) line_count: usize,
28    /// Contains bidirectional text (RTL scripts)
29    pub(super) has_bidi_text: bool,
30    /// Contains complex Unicode beyond basic Latin
31    pub(super) has_complex_unicode: bool,
32    /// Parsed override tags
33    pub(super) override_tags: Vec<OverrideTag<'a>>,
34    /// Parse diagnostics collected during analysis
35    pub(super) parse_diagnostics: Vec<TagDiagnostic<'a>>,
36}
37
38impl<'a> TextAnalysis<'a> {
39    /// Analyze dialogue text content comprehensively
40    ///
41    /// Extracts plain text, parses override tags, and analyzes Unicode
42    /// complexity. Uses zero-copy references for tag arguments.
43    ///
44    /// # Arguments
45    ///
46    /// * `text` - Original dialogue text with potential override tags
47    ///
48    /// # Returns
49    ///
50    /// Complete text analysis results or parsing error.
51    ///
52    /// # Example
53    ///
54    /// ```rust
55    /// # use ass_core::analysis::events::text_analysis::TextAnalysis;
56    /// let text = "Hello {\\b1}world{\\b0}!";
57    /// let analysis = TextAnalysis::analyze(text)?;
58    /// assert_eq!(analysis.plain_text(), "Hello world!");
59    /// assert_eq!(analysis.override_tags().len(), 2);
60    /// # Ok::<(), Box<dyn std::error::Error>>(())
61    /// ```
62    ///
63    /// # Errors
64    ///
65    /// Returns an error if text parsing fails or contains invalid override tags.
66    pub fn analyze(text: &'a str) -> Result<Self> {
67        #[cfg(feature = "plugins")]
68        return Self::analyze_with_registry(text, None);
69        #[cfg(not(feature = "plugins"))]
70        return Self::analyze_impl(text);
71    }
72
73    /// Analyze dialogue text content with extension registry support
74    ///
75    /// Same as [`analyze`](Self::analyze) but allows custom tag handlers via registry.
76    /// Unhandled tags fall back to standard processing.
77    ///
78    /// # Arguments
79    ///
80    /// * `text` - Original dialogue text with potential override tags
81    /// * `registry` - Optional registry for custom tag handlers
82    ///
83    /// # Returns
84    ///
85    /// Complete text analysis results or parsing error.
86    ///
87    /// # Errors
88    ///
89    /// Returns an error if text parsing fails or contains invalid override tags.
90    #[cfg(feature = "plugins")]
91    pub fn analyze_with_registry(
92        text: &'a str,
93        registry: Option<&ExtensionRegistry>,
94    ) -> Result<Self> {
95        Self::analyze_impl_with_registry(text, registry)
96    }
97
98    /// Internal implementation without plugins support
99    #[cfg(not(feature = "plugins"))]
100    fn analyze_impl(text: &'a str) -> Result<Self> {
101        Self::analyze_impl_with_registry(text)
102    }
103}