use crate::commands::{CommandResult, EditorCommand};
use crate::core::errors::EditorError;
use crate::core::{EditorDocument, Result};
#[cfg(feature = "std")]
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[cfg(not(feature = "std"))]
use alloc::sync::Arc;
#[cfg(feature = "concurrency")]
#[derive(Debug, Clone)]
pub struct SyncDocument {
inner: Arc<RwLock<EditorDocument>>,
command_lock: Arc<Mutex<()>>,
}
#[cfg(feature = "concurrency")]
impl SyncDocument {
pub fn new(document: EditorDocument) -> Self {
Self {
inner: Arc::new(RwLock::new(document)),
command_lock: Arc::new(Mutex::new(())),
}
}
pub fn from_document(document: EditorDocument) -> Self {
Self::new(document)
}
pub fn read(&self) -> Result<RwLockReadGuard<'_, EditorDocument>> {
self.inner
.read()
.map_err(|_| EditorError::ThreadSafetyError {
message: "Failed to acquire read lock".to_string(),
})
}
pub fn write(&self) -> Result<RwLockWriteGuard<'_, EditorDocument>> {
self.inner
.write()
.map_err(|_| EditorError::ThreadSafetyError {
message: "Failed to acquire write lock".to_string(),
})
}
pub fn execute_command<C: EditorCommand>(&self, command: C) -> Result<CommandResult> {
let _guard = self
.command_lock
.lock()
.map_err(|_| EditorError::ThreadSafetyError {
message: "Failed to acquire command lock".to_string(),
})?;
let mut doc = self.write()?;
command.execute(&mut doc)
}
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, EditorDocument>> {
self.inner.try_read().ok()
}
pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, EditorDocument>> {
self.inner.try_write().ok()
}
pub fn text(&self) -> Result<String> {
let doc = self.read()?;
Ok(doc.text())
}
pub fn len(&self) -> Result<usize> {
let doc = self.read()?;
Ok(doc.len())
}
pub fn is_empty(&self) -> Result<bool> {
let doc = self.read()?;
Ok(doc.is_empty())
}
pub fn id(&self) -> Result<String> {
let doc = self.read()?;
Ok(doc.id().to_string())
}
pub fn with_read<F, R>(&self, f: F) -> Result<R>
where
F: FnOnce(&EditorDocument) -> R,
{
let doc = self.read()?;
Ok(f(&doc))
}
pub fn with_write<F, R>(&self, f: F) -> Result<R>
where
F: FnOnce(&mut EditorDocument) -> Result<R>,
{
let mut doc = self.write()?;
f(&mut doc)
}
pub fn clone_document(&self) -> Result<EditorDocument> {
let doc = self.read()?;
EditorDocument::from_content(&doc.text())
}
pub fn validate(&self) -> Result<()> {
let doc = self.read()?;
doc.validate()
}
pub fn validate_comprehensive(&self) -> Result<Vec<crate::utils::validator::ValidationIssue>> {
self.with_write(|doc| {
let result = doc.validate_comprehensive()?;
Ok(result.issues)
})
}
}