use std::fmt; use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; use crate::error::BoxedError; use crate::id::Id as BaseId; pub trait Provider { fn channels(&mut self) -> Channels; } impl<'c> Provider for Transaction<'c, Sqlite> { fn channels(&mut self) -> Channels { Channels(self) } } pub struct Channels<'t>(&'t mut SqliteConnection); #[derive(Debug)] pub struct Channel { pub id: Id, pub name: String, } impl<'c> Channels<'c> { /// Create a new channel. pub async fn create(&mut self, name: &str) -> Result { let id = Id::generate(); let channel = sqlx::query_scalar!( r#" insert into channel (id, name) values ($1, $2) returning id as "id: Id" "#, id, name, ) .fetch_one(&mut *self.0) .await?; Ok(channel) } pub async fn all(&mut self) -> Result, BoxedError> { let channels = sqlx::query_as!( Channel, r#" select channel.id as "id: Id", channel.name from channel order by channel.name "#, ) .fetch_all(&mut *self.0) .await?; Ok(channels) } } /// Stable identifier for a [Channel]. Prefixed with `C`. #[derive(Clone, Debug, Eq, Hash, PartialEq, sqlx::Type, serde::Deserialize, serde::Serialize)] #[sqlx(transparent)] #[serde(transparent)] pub struct Id(BaseId); impl From for Id { fn from(id: BaseId) -> Self { Self(id) } } impl Id { pub fn generate() -> Self { BaseId::generate("C") } } impl fmt::Display for Id { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } }