p2panda_store/groups/
sqlite.rs1use p2panda_auth::group::GroupCrdtState;
4use p2panda_auth::traits::{Conditions, Operation as AuthOperation};
5use p2panda_core::cbor::{decode_cbor, encode_cbor};
6use p2panda_core::{Hash, VerifyingKey};
7use serde::{Deserialize, Serialize};
8use sqlx::query;
9use sqlx::query_as;
10
11use crate::groups::traits::GroupsStore;
12use crate::{SqliteError, SqliteStore};
13
14impl<M, C> GroupsStore<M, C> for SqliteStore
15where
16 C: Conditions + Serialize + for<'a> Deserialize<'a>,
17 M: AuthOperation<VerifyingKey, Hash, C> + Serialize + for<'a> Deserialize<'a>,
18{
19 type Error = SqliteError;
20
21 async fn set_groups_state_tx(
22 &self,
23 id: Hash,
24 state: &GroupCrdtState<VerifyingKey, Hash, M, C>,
25 ) -> Result<(), SqliteError> {
26 self.tx(async |tx| {
27 query(
28 "
29 INSERT OR REPLACE
30 INTO
31 groups_v1 (
32 id,
33 state
34 )
35 VALUES
36 (?, ?)
37 ",
38 )
39 .bind(id.to_hex())
40 .bind(encode_cbor(&state).map_err(|err| SqliteError::Encode("state".to_string(), err))?)
41 .execute(&mut **tx)
42 .await
43 .map_err(SqliteError::Sqlite)
44 })
45 .await?;
46
47 Ok(())
48 }
49
50 async fn get_groups_state_tx(
51 &self,
52 id: Hash,
53 ) -> Result<Option<GroupCrdtState<VerifyingKey, Hash, M, C>>, SqliteError> {
54 let row = self
55 .tx(async |tx| {
56 query_as::<_, (Vec<u8>,)>(
57 "
58 SELECT
59 state
60 FROM
61 groups_v1
62 WHERE
63 id = ?
64 ",
65 )
66 .bind(id.to_hex())
67 .fetch_optional(&mut **tx)
68 .await
69 .map_err(SqliteError::Sqlite)
70 })
71 .await?;
72
73 let Some((state_bytes,)) = row else {
74 return Ok(None);
75 };
76
77 let state = decode_cbor(&state_bytes[..])
78 .map_err(|err| SqliteError::Decode("state".into(), err.into()))?;
79
80 Ok(Some(state))
81 }
82}