aboutsummaryrefslogtreecommitdiffstats
path: root/filamento/src/roster.rs
diff options
context:
space:
mode:
Diffstat (limited to 'filamento/src/roster.rs')
-rw-r--r--filamento/src/roster.rs120
1 files changed, 76 insertions, 44 deletions
diff --git a/filamento/src/roster.rs b/filamento/src/roster.rs
index 43c32f5..0498278 100644
--- a/filamento/src/roster.rs
+++ b/filamento/src/roster.rs
@@ -1,85 +1,117 @@
-use std::collections::HashSet;
+use std::{collections::HashSet, fmt::Display};
-use jid::JID;
-use sqlx::Sqlite;
+use jid::BareJID;
+use rusqlite::{
+ ToSql,
+ types::{FromSql, ToSqlOutput, Value},
+};
pub struct ContactUpdate {
pub name: Option<String>,
pub groups: HashSet<String>,
}
-#[derive(Debug, sqlx::FromRow, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct Contact {
// jid is the id used to reference everything, but not the primary key
- pub user_jid: JID,
+ pub user_jid: BareJID,
pub subscription: Subscription,
/// client user defined name
pub name: Option<String>,
// TODO: avatar, nickname
/// nickname picked by contact
// nickname: Option<String>,
- #[sqlx(skip)]
+ #[cfg_attr(feature = "reactive_stores", store(key: String = |group| group.clone()))]
pub groups: HashSet<String>,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
+/// Contact subscription state.
pub enum Subscription {
+ /// No subscriptions.
None,
+ /// Pending outgoing subscription request.
PendingOut,
+ /// Pending incoming subscription request.
PendingIn,
+ /// Pending incoming & pending outgoing subscription requests.
PendingInPendingOut,
+ /// Subscribed to.
OnlyOut,
+ /// Subscription from.
OnlyIn,
+ /// Subscribed to & pending incoming subscription request.
OutPendingIn,
+ /// Subscription from & pending outgoing subscription request.
InPendingOut,
+ /// Buddy (subscriptions both ways).
Buddy,
// TODO: perhaps don't need, just emit event to remove contact
// Remove,
}
-impl sqlx::Type<Sqlite> for Subscription {
- fn type_info() -> <Sqlite as sqlx::Database>::TypeInfo {
- <&str as sqlx::Type<Sqlite>>::type_info()
+impl ToSql for Subscription {
+ fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
+ Ok(match self {
+ Subscription::None => ToSqlOutput::Owned(Value::Text("none".to_string())),
+ Subscription::PendingOut => ToSqlOutput::Owned(Value::Text("pending-out".to_string())),
+ Subscription::PendingIn => ToSqlOutput::Owned(Value::Text("pending-in".to_string())),
+ Subscription::PendingInPendingOut => {
+ ToSqlOutput::Owned(Value::Text("pending-in-pending-out".to_string()))
+ }
+ Subscription::OnlyOut => ToSqlOutput::Owned(Value::Text("only-out".to_string())),
+ Subscription::OnlyIn => ToSqlOutput::Owned(Value::Text("only-in".to_string())),
+ Subscription::OutPendingIn => {
+ ToSqlOutput::Owned(Value::Text("out-pending-in".to_string()))
+ }
+ Subscription::InPendingOut => {
+ ToSqlOutput::Owned(Value::Text("in-pending-out".to_string()))
+ }
+ Subscription::Buddy => ToSqlOutput::Owned(Value::Text("buddy".to_string())),
+ })
}
}
-impl sqlx::Decode<'_, Sqlite> for Subscription {
- fn decode(
- value: <Sqlite as sqlx::Database>::ValueRef<'_>,
- ) -> Result<Self, sqlx::error::BoxDynError> {
- let value = <&str as sqlx::Decode<Sqlite>>::decode(value)?;
- match value {
- "none" => Ok(Self::None),
- "pending-out" => Ok(Self::PendingOut),
- "pending-in" => Ok(Self::PendingIn),
- "pending-in-pending-out" => Ok(Self::PendingInPendingOut),
- "only-out" => Ok(Self::OnlyOut),
- "only-in" => Ok(Self::OnlyIn),
- "out-pending-in" => Ok(Self::OutPendingIn),
- "in-pending-out" => Ok(Self::InPendingOut),
- "buddy" => Ok(Self::Buddy),
- _ => panic!("unexpected subscription `{value}`"),
- }
+impl FromSql for Subscription {
+ fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
+ Ok(match value.as_str()? {
+ "none" => Self::None,
+ "pending-out" => Self::PendingOut,
+ "pending-in" => Self::PendingIn,
+ "pending-in-pending-out" => Self::PendingInPendingOut,
+ "only-out" => Self::OnlyOut,
+ "only-in" => Self::OnlyIn,
+ "out-pending-in" => Self::OutPendingIn,
+ "in-pending-out" => Self::InPendingOut,
+ "buddy" => Self::Buddy,
+ // TODO: don't have these lol
+ value => panic!("unexpected subscription `{value}`"),
+ })
}
}
-impl sqlx::Encode<'_, Sqlite> for Subscription {
- fn encode_by_ref(
- &self,
- buf: &mut <Sqlite as sqlx::Database>::ArgumentBuffer<'_>,
- ) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
- let value = match self {
- Subscription::None => "none",
- Subscription::PendingOut => "pending-out",
- Subscription::PendingIn => "pending-in",
- Subscription::PendingInPendingOut => "pending-in-pending-out",
- Subscription::OnlyOut => "only-out",
- Subscription::OnlyIn => "only-in",
- Subscription::OutPendingIn => "out-pending-in",
- Subscription::InPendingOut => "in-pending-out",
- Subscription::Buddy => "buddy",
- };
- <&str as sqlx::Encode<Sqlite>>::encode(value, buf)
+impl Display for Subscription {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Subscription::None => write!(f, "No Subscriptions"),
+ Subscription::PendingOut => write!(f, "Pending Outgoing Subscription Request"),
+ Subscription::PendingIn => write!(f, "Pending Incoming Subscription Request"),
+ Subscription::PendingInPendingOut => write!(
+ f,
+ "Pending Incoming & Pending Outgoing Subscription Requests"
+ ),
+ Subscription::OnlyOut => write!(f, "Subscribed To"),
+ Subscription::OnlyIn => write!(f, "Subscription From"),
+ Subscription::OutPendingIn => {
+ write!(f, "Subscribed To & Pending Incoming Subscription Request")
+ }
+ Subscription::InPendingOut => write!(
+ f,
+ "Subscription From & Pending Outgoing Subscription Request"
+ ),
+ Subscription::Buddy => write!(f, "Buddy (Subscriptions Both Ways)"),
+ }
}
}