im-core 0.1.0

Rust IM SDK for Awiki clients built on Agent Network Protocol (ANP)
Documentation
#[cfg(feature = "sqlite")]
pub(crate) mod actor;

pub(crate) mod attachment_manifest_cache;
pub(crate) mod contacts;
#[cfg(feature = "sqlite")]
pub(crate) mod conversation_summaries;
pub(crate) mod conversations;
pub(crate) mod email;
pub(crate) mod groups;
pub(crate) mod messages;
pub(crate) mod owner_scope;
pub(crate) mod read_state;
pub(crate) mod sync_state;

#[cfg(feature = "sqlite")]
pub(crate) mod schema;

#[cfg(feature = "sqlite")]
#[allow(dead_code)]
pub(crate) trait LocalStateStore {
    fn ensure_schema(&self) -> crate::ImResult<()>;

    fn current_schema_version(&self) -> crate::ImResult<i64>;

    fn store_message(&mut self, _record: messages::MessageRecord) -> crate::ImResult<()> {
        Err(unsupported_operation("store_message"))
    }

    fn store_messages(&mut self, _records: &[messages::MessageRecord]) -> crate::ImResult<()> {
        Err(unsupported_operation("store_messages"))
    }

    fn upsert_contact(&mut self, _record: contacts::ContactRecord) -> crate::ImResult<()> {
        Err(unsupported_operation("upsert_contact"))
    }

    fn upsert_group(&mut self, _record: groups::GroupRecord) -> crate::ImResult<()> {
        Err(unsupported_operation("upsert_group"))
    }

    fn upsert_group_member(&mut self, _record: groups::GroupMemberRecord) -> crate::ImResult<()> {
        Err(unsupported_operation("upsert_group_member"))
    }

    fn list_conversations(
        &self,
        _owner_did: &str,
        _limit: i64,
    ) -> crate::ImResult<Vec<conversations::ConversationRecord>> {
        Err(unsupported_operation("list_conversations"))
    }
}

#[cfg(feature = "sqlite")]
impl LocalStateStore for rusqlite::Connection {
    fn ensure_schema(&self) -> crate::ImResult<()> {
        schema::ensure_schema(self)
    }

    fn current_schema_version(&self) -> crate::ImResult<i64> {
        schema::current_schema_version(self)
    }

    fn store_message(&mut self, record: messages::MessageRecord) -> crate::ImResult<()> {
        messages::upsert_message(self, &record)
    }

    fn store_messages(&mut self, records: &[messages::MessageRecord]) -> crate::ImResult<()> {
        messages::upsert_messages(self, records)
    }
}

#[cfg(feature = "sqlite")]
pub(crate) fn open_writable(path: &std::path::Path) -> crate::ImResult<rusqlite::Connection> {
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent)?;
    }
    let connection = rusqlite::Connection::open(path).map_err(local_state_unavailable)?;
    configure(&connection)?;
    schema::ensure_schema(&connection)?;
    Ok(connection)
}

#[cfg(feature = "sqlite")]
pub(crate) fn configure(connection: &rusqlite::Connection) -> crate::ImResult<()> {
    connection
        .pragma_update(None, "journal_mode", "WAL")
        .map_err(local_state_unavailable)?;
    connection
        .pragma_update(None, "foreign_keys", "ON")
        .map_err(local_state_unavailable)?;
    connection
        .pragma_update(None, "busy_timeout", 5000)
        .map_err(local_state_unavailable)?;
    connection
        .pragma_update(None, "mmap_size", 0)
        .map_err(local_state_unavailable)?;
    Ok(())
}

#[cfg(feature = "sqlite")]
pub(crate) fn local_state_unavailable(err: impl std::fmt::Display) -> crate::ImError {
    crate::ImError::LocalStateUnavailable {
        detail: err.to_string(),
    }
}

#[cfg(feature = "sqlite")]
#[allow(dead_code)]
fn unsupported_operation(name: &str) -> crate::ImError {
    crate::ImError::unsupported(format!("local_state.{name}"))
}