diff --git a/blah-types/src/lib.rs b/blah-types/src/lib.rs index dc52f50..aa8e3f7 100644 --- a/blah-types/src/lib.rs +++ b/blah-types/src/lib.rs @@ -35,3 +35,6 @@ pub mod crypto; pub mod identity; pub mod msg; pub mod server; + +#[cfg(feature = "rusqlite")] +mod rusqlite_impl; diff --git a/blah-types/src/msg.rs b/blah-types/src/msg.rs index b811754..edbe8b8 100644 --- a/blah-types/src/msg.rs +++ b/blah-types/src/msg.rs @@ -463,78 +463,6 @@ impl_json_schema_as!(ServerPermission => i32); impl_json_schema_as!(MemberPermission => i32); impl_json_schema_as!(RoomAttrs => i32); -#[cfg(feature = "rusqlite")] -mod sql_impl { - use ed25519_dalek::{VerifyingKey, PUBLIC_KEY_LENGTH}; - use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef}; - use rusqlite::{Result, ToSql}; - - use super::*; - - impl ToSql for Id { - fn to_sql(&self) -> Result> { - self.0.to_sql() - } - } - - impl FromSql for Id { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { - i64::column_result(value).map(Self) - } - } - - impl ToSql for PubKey { - fn to_sql(&self) -> Result> { - // TODO: Extensive key format? - self.0.to_sql() - } - } - - impl FromSql for PubKey { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { - let rawkey = <[u8; PUBLIC_KEY_LENGTH]>::column_result(value)?; - let key = VerifyingKey::from_bytes(&rawkey) - .map_err(|err| FromSqlError::Other(format!("invalid pubkey: {err}").into()))?; - Ok(key.into()) - } - } - - impl ToSql for RichText { - fn to_sql(&self) -> Result> { - assert!(self.is_canonical()); - let json = serde_json::to_string(&self).expect("serialization cannot fail"); - Ok(json.into()) - } - } - - impl FromSql for RichText { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { - serde_json::from_str::(value.as_str()?) - .map_err(|err| FromSqlError::Other(format!("invalid rich text: {err}").into())) - } - } - - macro_rules! impl_flag_to_from_sql { - ($($name:ident),*) => { - $( - impl ToSql for $name { - fn to_sql(&self) -> Result> { - Ok(self.bits().into()) - } - } - - impl FromSql for $name { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { - i32::column_result(value).map($name::from_bits_retain) - } - } - )* - }; - } - - impl_flag_to_from_sql!(ServerPermission, MemberPermission, RoomAttrs); -} - #[cfg(test)] mod tests { use ed25519_dalek::{SigningKey, PUBLIC_KEY_LENGTH}; diff --git a/blah-types/src/rusqlite_impl.rs b/blah-types/src/rusqlite_impl.rs new file mode 100644 index 0000000..264f571 --- /dev/null +++ b/blah-types/src/rusqlite_impl.rs @@ -0,0 +1,69 @@ +use ed25519_dalek::{VerifyingKey, PUBLIC_KEY_LENGTH}; +use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef}; +use rusqlite::{Result, ToSql}; + +use crate::msg::{MemberPermission, RichText, RoomAttrs, ServerPermission}; +use crate::{Id, PubKey}; + +impl ToSql for Id { + fn to_sql(&self) -> Result> { + self.0.to_sql() + } +} + +impl FromSql for Id { + fn column_result(value: ValueRef<'_>) -> FromSqlResult { + i64::column_result(value).map(Self) + } +} + +impl ToSql for PubKey { + fn to_sql(&self) -> Result> { + // TODO: Extensive key format? + self.0.to_sql() + } +} + +impl FromSql for PubKey { + fn column_result(value: ValueRef<'_>) -> FromSqlResult { + let rawkey = <[u8; PUBLIC_KEY_LENGTH]>::column_result(value)?; + let key = VerifyingKey::from_bytes(&rawkey) + .map_err(|err| FromSqlError::Other(format!("invalid pubkey: {err}").into()))?; + Ok(key.into()) + } +} + +impl ToSql for RichText { + fn to_sql(&self) -> Result> { + assert!(self.is_canonical()); + let json = serde_json::to_string(&self).expect("serialization cannot fail"); + Ok(json.into()) + } +} + +impl FromSql for RichText { + fn column_result(value: ValueRef<'_>) -> FromSqlResult { + serde_json::from_str::(value.as_str()?) + .map_err(|err| FromSqlError::Other(format!("invalid rich text: {err}").into())) + } +} + +macro_rules! impl_flag_to_from_sql { + ($($name:ident),*) => { + $( + impl ToSql for $name { + fn to_sql(&self) -> Result> { + Ok(self.bits().into()) + } + } + + impl FromSql for $name { + fn column_result(value: ValueRef<'_>) -> FromSqlResult { + i32::column_result(value).map($name::from_bits_retain) + } + } + )* + }; +} + +impl_flag_to_from_sql!(ServerPermission, MemberPermission, RoomAttrs);