ass_editor/core/document/
constructors.rs1use super::EditorDocument;
8#[cfg(feature = "std")]
9use super::EventSender;
10use crate::core::errors::{EditorError, Result};
11use crate::core::history::UndoManager;
12use ass_core::parser::Script;
13
14#[cfg(feature = "std")]
15use crate::events::DocumentEvent;
16
17#[cfg(not(feature = "std"))]
18use alloc::{format, string::String};
19
20impl EditorDocument {
21 pub fn new() -> Self {
23 Self {
24 #[cfg(feature = "rope")]
25 text_rope: ropey::Rope::new(),
26 #[cfg(not(feature = "rope"))]
27 text_content: String::new(),
28 id: Self::generate_id(),
29 modified: false,
30 file_path: None,
31 #[cfg(feature = "plugins")]
32 registry_integration: None,
33 history: UndoManager::new(),
34 #[cfg(feature = "std")]
35 event_tx: None,
36 #[cfg(feature = "stream")]
37 incremental_parser: crate::core::incremental::IncrementalParser::new(),
38 validator: crate::utils::validator::LazyValidator::new(),
39 }
40 }
41
42 #[cfg(feature = "std")]
44 pub fn with_event_channel(event_tx: EventSender) -> Self {
45 let mut doc = Self::new();
46 doc.event_tx = Some(event_tx);
47 doc
48 }
49
50 #[cfg(feature = "std")]
52 pub fn from_file(path: &str) -> Result<Self> {
53 use std::fs;
54 let content = fs::read_to_string(path).map_err(|e| EditorError::IoError(e.to_string()))?;
55 let mut doc = Self::from_content(&content)?;
56 doc.file_path = Some(path.to_string());
57 Ok(doc)
58 }
59
60 #[cfg(feature = "std")]
62 pub fn save(&mut self) -> Result<()> {
63 if let Some(path) = self.file_path.clone() {
64 self.save_to_file(&path)
65 } else {
66 Err(EditorError::IoError(
67 "No file path set for document".to_string(),
68 ))
69 }
70 }
71
72 #[cfg(feature = "std")]
74 pub fn save_to_file(&mut self, path: &str) -> Result<()> {
75 use std::fs;
76 let content = self.text();
77 fs::write(path, content).map_err(|e| EditorError::IoError(e.to_string()))?;
78 self.modified = false;
79 self.file_path = Some(path.to_string());
80 Ok(())
81 }
82
83 pub fn with_id(id: String) -> Self {
85 let mut doc = Self::new();
86 doc.id = id;
87 doc
88 }
89
90 #[cfg(feature = "std")]
92 pub(super) fn emit(&mut self, event: DocumentEvent) {
93 if let Some(tx) = &mut self.event_tx {
94 let _ = tx.send(event);
95 }
96 }
97
98 #[cfg(feature = "std")]
100 pub fn set_event_channel(&mut self, event_tx: EventSender) {
101 self.event_tx = Some(event_tx);
102 }
103
104 #[cfg(feature = "std")]
106 pub fn has_event_channel(&self) -> bool {
107 self.event_tx.is_some()
108 }
109
110 pub fn from_content(content: &str) -> Result<Self> {
141 let _ = Script::parse(content).map_err(EditorError::from)?;
143
144 #[cfg(feature = "stream")]
145 let mut incremental_parser = crate::core::incremental::IncrementalParser::new();
146 #[cfg(feature = "stream")]
147 incremental_parser.initialize_cache(content);
148
149 Ok(Self {
150 #[cfg(feature = "rope")]
151 text_rope: ropey::Rope::from_str(content),
152 #[cfg(not(feature = "rope"))]
153 text_content: content.to_string(),
154 id: Self::generate_id(),
155 modified: false,
156 file_path: None,
157 #[cfg(feature = "plugins")]
158 registry_integration: None,
159 history: UndoManager::new(),
160 #[cfg(feature = "std")]
161 event_tx: None,
162 #[cfg(feature = "stream")]
163 incremental_parser,
164 validator: crate::utils::validator::LazyValidator::new(),
165 })
166 }
167
168 fn generate_id() -> String {
170 #[cfg(feature = "std")]
172 {
173 use std::time::{SystemTime, UNIX_EPOCH};
174 let timestamp = SystemTime::now()
175 .duration_since(UNIX_EPOCH)
176 .unwrap_or_default()
177 .as_nanos();
178 format!("doc_{timestamp}")
179 }
180 #[cfg(not(feature = "std"))]
181 {
182 use core::sync::atomic::{AtomicU32, Ordering};
183 static COUNTER: AtomicU32 = AtomicU32::new(0);
184 let id = COUNTER.fetch_add(1, Ordering::Relaxed).wrapping_add(1);
185 format!("doc_{id}")
186 }
187 }
188}