Skip to main content

ass_core/parser/ast/event/
event_struct.rs

1//! `Event` struct with construction defaults and timing accessors
2//!
3//! Defines the zero-copy [`Event`] node for the `[Events]` section together
4//! with its dialogue/comment predicates, centisecond time helpers, and the
5//! [`Default`] template implementation.
6
7use super::{EventType, Span};
8
9/// Event from `[Events\]` section (dialogue, comments, etc.)
10///
11/// Represents a single event in the subtitle timeline. Events can be dialogue
12/// lines, comments, or other commands with associated timing and styling.
13/// All fields use zero-copy string references for maximum efficiency.
14///
15/// # Examples
16///
17/// ```rust
18/// use ass_core::parser::ast::{Event, EventType};
19///
20/// let event = Event {
21///     event_type: EventType::Dialogue,
22///     start: "0:00:05.00",
23///     end: "0:00:10.00",
24///     text: "Hello, world!",
25///     ..Event::default()
26/// };
27///
28/// assert!(event.is_dialogue());
29/// ```
30#[derive(Debug, Clone, PartialEq, Eq)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize))]
32pub struct Event<'a> {
33    /// Event type (Dialogue, Comment, etc.)
34    pub event_type: EventType,
35
36    /// Layer for drawing order (higher layers drawn on top)
37    pub layer: &'a str,
38
39    /// Start time in ASS time format (H:MM:SS.CS)
40    pub start: &'a str,
41
42    /// End time in ASS time format (H:MM:SS.CS)
43    pub end: &'a str,
44
45    /// Style name reference
46    pub style: &'a str,
47
48    /// Character name or speaker
49    pub name: &'a str,
50
51    /// Left margin override (pixels)
52    pub margin_l: &'a str,
53
54    /// Right margin override (pixels)
55    pub margin_r: &'a str,
56
57    /// Vertical margin override (pixels) (V4+)
58    pub margin_v: &'a str,
59
60    /// Top margin override (pixels) (V4++)
61    pub margin_t: Option<&'a str>,
62
63    /// Bottom margin override (pixels) (V4++)
64    pub margin_b: Option<&'a str>,
65
66    /// Effect specification for special rendering
67    pub effect: &'a str,
68
69    /// Text content with possible style overrides
70    pub text: &'a str,
71
72    /// Span in source text where this event is defined
73    pub span: Span,
74}
75
76impl Event<'_> {
77    /// Check if this is a dialogue event
78    ///
79    /// Returns `true` for events that should be displayed during playback.
80    #[must_use]
81    pub const fn is_dialogue(&self) -> bool {
82        matches!(self.event_type, EventType::Dialogue)
83    }
84
85    /// Check if this is a comment event
86    ///
87    /// Returns `true` for events that are comments and not displayed.
88    #[must_use]
89    pub const fn is_comment(&self) -> bool {
90        matches!(self.event_type, EventType::Comment)
91    }
92
93    /// Parse start time to centiseconds
94    ///
95    /// Converts the start time string to centiseconds for timing calculations.
96    /// Uses the standard ASS time format parser.
97    ///
98    /// # Errors
99    ///
100    /// Returns an error if the time format is invalid or cannot be parsed.
101    pub fn start_time_cs(&self) -> Result<u32, crate::utils::CoreError> {
102        crate::utils::parse_ass_time(self.start)
103    }
104
105    /// Parse end time to centiseconds
106    ///
107    /// Converts the end time string to centiseconds for timing calculations.
108    /// Uses the standard ASS time format parser.
109    ///
110    /// # Errors
111    ///
112    /// Returns an error if the time format is invalid or cannot be parsed.
113    pub fn end_time_cs(&self) -> Result<u32, crate::utils::CoreError> {
114        crate::utils::parse_ass_time(self.end)
115    }
116
117    /// Get duration in centiseconds
118    ///
119    /// Calculates the event duration by subtracting start time from end time.
120    /// Returns 0 if start time is greater than end time.
121    ///
122    /// # Errors
123    ///
124    /// Returns an error if either start or end time format is invalid.
125    pub fn duration_cs(&self) -> Result<u32, crate::utils::CoreError> {
126        let start = self.start_time_cs()?;
127        let end = self.end_time_cs()?;
128        Ok(end.saturating_sub(start))
129    }
130}
131
132impl Default for Event<'_> {
133    /// Create default event with safe initial values
134    ///
135    /// Provides a valid default event that can be used as a template
136    /// or for testing purposes.
137    fn default() -> Self {
138        Self {
139            event_type: EventType::Dialogue,
140            layer: "0",
141            start: "0:00:00.00",
142            end: "0:00:00.00",
143            style: "Default",
144            name: "",
145            margin_l: "0",
146            margin_r: "0",
147            margin_v: "0",
148            margin_t: None,
149            margin_b: None,
150            effect: "",
151            text: "",
152            span: Span::new(0, 0, 0, 0),
153        }
154    }
155}