use crate::appstate::hash::HashState;
use crate::store::error::Result;
use async_trait::async_trait;
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use wacore_appstate::processor::AppStateMutationMAC;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AppStateSyncKey {
pub key_data: Vec<u8>,
pub fingerprint: Vec<u8>,
pub timestamp: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LidPnMappingEntry {
pub lid: String,
pub phone_number: String,
pub created_at: i64,
pub updated_at: i64,
pub learning_source: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TcTokenEntry {
pub token: Vec<u8>,
pub token_timestamp: i64,
pub sender_timestamp: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceInfo {
pub device_id: u32,
pub key_index: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceListRecord {
pub user: String,
pub devices: Vec<DeviceInfo>,
pub timestamp: i64,
pub phash: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub raw_id: Option<u32>,
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait SignalStore: Send + Sync {
async fn put_identity(&self, address: &str, key: [u8; 32]) -> Result<()>;
async fn load_identity(&self, address: &str) -> Result<Option<[u8; 32]>>;
async fn delete_identity(&self, address: &str) -> Result<()>;
async fn get_session(&self, address: &str) -> Result<Option<Bytes>>;
async fn put_session(&self, address: &str, session: &[u8]) -> Result<()>;
async fn delete_session(&self, address: &str) -> Result<()>;
async fn has_session(&self, address: &str) -> Result<bool> {
Ok(self.get_session(address).await?.is_some())
}
async fn store_prekey(&self, id: u32, record: &[u8], uploaded: bool) -> Result<()>;
async fn store_prekeys_batch(&self, keys: &[(u32, Bytes)], uploaded: bool) -> Result<()> {
for (id, record) in keys {
self.store_prekey(*id, record, uploaded).await?;
}
Ok(())
}
async fn load_prekey(&self, id: u32) -> Result<Option<Bytes>>;
async fn load_prekeys_batch(&self, ids: &[u32]) -> Result<Vec<(u32, Bytes)>> {
let mut result = Vec::with_capacity(ids.len());
for &id in ids {
if let Some(record) = self.load_prekey(id).await? {
result.push((id, record));
}
}
Ok(result)
}
async fn remove_prekey(&self, id: u32) -> Result<()>;
async fn get_max_prekey_id(&self) -> Result<u32>;
async fn store_signed_prekey(&self, id: u32, record: &[u8]) -> Result<()>;
async fn load_signed_prekey(&self, id: u32) -> Result<Option<Vec<u8>>>;
async fn load_all_signed_prekeys(&self) -> Result<Vec<(u32, Vec<u8>)>>;
async fn remove_signed_prekey(&self, id: u32) -> Result<()>;
async fn put_sender_key(&self, address: &str, record: &[u8]) -> Result<()>;
async fn get_sender_key(&self, address: &str) -> Result<Option<Vec<u8>>>;
async fn delete_sender_key(&self, address: &str) -> Result<()>;
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait AppSyncStore: Send + Sync {
async fn get_sync_key(&self, key_id: &[u8]) -> Result<Option<AppStateSyncKey>>;
async fn set_sync_key(&self, key_id: &[u8], key: AppStateSyncKey) -> Result<()>;
async fn get_version(&self, name: &str) -> Result<HashState>;
async fn set_version(&self, name: &str, state: HashState) -> Result<()>;
async fn put_mutation_macs(
&self,
name: &str,
version: u64,
mutations: &[AppStateMutationMAC],
) -> Result<()>;
async fn get_mutation_mac(&self, name: &str, index_mac: &[u8]) -> Result<Option<Vec<u8>>>;
async fn delete_mutation_macs(&self, name: &str, index_macs: &[Vec<u8>]) -> Result<()>;
async fn get_latest_sync_key_id(&self) -> Result<Option<Vec<u8>>>;
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait ProtocolStore: Send + Sync {
async fn get_sender_key_devices(&self, group_jid: &str) -> Result<Vec<(String, bool)>>;
async fn set_sender_key_status(&self, group_jid: &str, entries: &[(&str, bool)]) -> Result<()>;
async fn clear_sender_key_devices(&self, group_jid: &str) -> Result<()>;
async fn delete_sender_key_device_rows(&self, device_jids: &[&str]) -> Result<()>;
async fn clear_all_sender_key_devices(&self) -> Result<()>;
async fn get_lid_mapping(&self, lid: &str) -> Result<Option<LidPnMappingEntry>>;
async fn get_pn_mapping(&self, phone: &str) -> Result<Option<LidPnMappingEntry>>;
async fn put_lid_mapping(&self, entry: &LidPnMappingEntry) -> Result<()>;
async fn put_lid_mappings(&self, entries: &[LidPnMappingEntry]) -> Result<()> {
for entry in entries {
self.put_lid_mapping(entry).await?;
}
Ok(())
}
async fn get_all_lid_mappings(&self) -> Result<Vec<LidPnMappingEntry>>;
async fn save_base_key(&self, address: &str, message_id: &str, base_key: &[u8]) -> Result<()>;
async fn has_same_base_key(
&self,
address: &str,
message_id: &str,
current_base_key: &[u8],
) -> Result<bool>;
async fn delete_base_key(&self, address: &str, message_id: &str) -> Result<()>;
async fn update_device_list(&self, record: DeviceListRecord) -> Result<()>;
async fn update_device_lists(&self, records: Vec<DeviceListRecord>) -> Result<()> {
for record in records {
self.update_device_list(record).await?;
}
Ok(())
}
async fn get_devices(&self, user: &str) -> Result<Option<DeviceListRecord>>;
async fn delete_devices(&self, user: &str) -> Result<()>;
async fn get_tc_token(&self, jid: &str) -> Result<Option<TcTokenEntry>>;
async fn put_tc_token(&self, jid: &str, entry: &TcTokenEntry) -> Result<()>;
async fn delete_tc_token(&self, jid: &str) -> Result<()>;
async fn get_all_tc_token_jids(&self) -> Result<Vec<String>>;
async fn delete_expired_tc_tokens(&self, cutoff_timestamp: i64) -> Result<u32>;
async fn store_sent_message(
&self,
chat_jid: &str,
message_id: &str,
payload: &[u8],
) -> Result<()>;
async fn take_sent_message(&self, chat_jid: &str, message_id: &str) -> Result<Option<Vec<u8>>>;
async fn delete_expired_sent_messages(&self, cutoff_timestamp: i64) -> Result<u32>;
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait DeviceStore: Send + Sync {
async fn save(&self, device: &crate::store::Device) -> Result<()>;
async fn load(&self) -> Result<Option<crate::store::Device>>;
async fn exists(&self) -> Result<bool>;
async fn create(&self) -> Result<i32>;
async fn snapshot_db(&self, _name: &str, _extra_content: Option<&[u8]>) -> Result<()> {
Ok(())
}
}
pub trait Backend: SignalStore + AppSyncStore + ProtocolStore + DeviceStore + Send + Sync {}
impl<T> Backend for T where T: SignalStore + AppSyncStore + ProtocolStore + DeviceStore + Send + Sync
{}