use crate::error::Result; use crate::store::BaseData; use serde::{Deserialize, Serialize}; use std::fmt::Debug; /// Represents an index key for an object field #[derive(Debug, Clone, PartialEq, Eq)] pub struct IndexKey { /// The name of the index key (field name) pub name: &'static str, /// The value of the index key for this object instance pub value: String, } impl IndexKey { pub fn new(name: &'static str, value: impl ToString) -> Self { Self { name, value: value.to_string(), } } } /// Core trait that all OSIRIS objects must implement /// Similar to heromodels Model trait but adapted for OSIRIS pub trait Object: Debug + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync { /// Get the object type name (used for routing/identification) fn object_type() -> &'static str where Self: Sized; /// Get a reference to the base data fn base_data(&self) -> &BaseData; /// Get a mutable reference to the base data fn base_data_mut(&mut self) -> &mut BaseData; /// Get the unique ID for this object fn id(&self) -> &str { &self.base_data().id } /// Set the unique ID for this object fn set_id(&mut self, id: impl ToString) { self.base_data_mut().id = id.to_string(); } /// Get the namespace for this object fn namespace(&self) -> &str { &self.base_data().ns } /// Returns a list of index keys for this object instance /// These are generated from fields marked with #[index] /// The default implementation returns base_data indexes only fn index_keys(&self) -> Vec { let base = self.base_data(); let mut keys = Vec::new(); // Index MIME type if present if let Some(mime) = &base.mime { keys.push(IndexKey::new("mime", mime)); } keys } /// Return a list of field names which have an index applied /// This should be implemented by the derive macro fn indexed_fields() -> Vec<&'static str> where Self: Sized, { Vec::new() } /// Get the full-text searchable content for this object /// Override this to provide custom searchable text fn searchable_text(&self) -> Option { None } /// Serialize the object to JSON fn to_json(&self) -> Result { serde_json::to_string(self).map_err(Into::into) } /// Deserialize the object from JSON fn from_json(json: &str) -> Result where Self: Sized, { serde_json::from_str(json).map_err(Into::into) } /// Update the modified timestamp fn touch(&mut self) { self.base_data_mut().update_modified(); } } /// Trait for objects that can be stored in OSIRIS /// This is automatically implemented for all types that implement Object pub trait Storable: Object { /// Prepare the object for storage (update timestamps, etc.) fn prepare_for_storage(&mut self) { self.touch(); } } // Blanket implementation impl Storable for T {}