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<(), BoxedError> { let id = Id::generate(); sqlx::query!( r#" insert into channel (id, name) values ($1, $2) "#, id, name, ) .execute(&mut *self.0) .await?; Ok(()) } 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(Debug, sqlx::Type, serde::Deserialize)] #[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) } }