chat: add Id<T> type

This commit is contained in:
sam 2024-01-20 23:09:19 +01:00
parent e57bff00c2
commit ce543e7ee1
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
8 changed files with 146 additions and 43 deletions

103
foxchat/src/id.rs Normal file
View file

@ -0,0 +1,103 @@
use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
use sqlx::{
database::{HasArguments, HasValueRef},
encode::IsNull,
error::BoxDynError,
postgres::PgTypeInfo,
Decode, Encode, Postgres, Type,
};
pub struct Id<T>(pub String, PhantomData<T>)
where
T: IdType;
impl<T: IdType> Id<T> {
pub fn new(value: String) -> Self {
Self(value, PhantomData)
}
pub fn from_str(value: &str) -> Self {
value.into()
}
}
impl<T: IdType> From<&str> for Id<T> {
fn from(value: &str) -> Self {
Self::new(value.to_string())
}
}
impl<T: IdType> From<String> for Id<T> {
fn from(value: String) -> Self {
Self::new(value)
}
}
impl<T: IdType> From<Id<T>> for String {
fn from(value: Id<T>) -> Self {
value.0
}
}
pub trait IdType: private::Sealed {}
pub struct GuildType;
pub struct ChannelType;
pub struct MessageType;
pub struct UserType;
impl IdType for GuildType {}
impl IdType for ChannelType {}
impl IdType for MessageType {}
impl IdType for UserType {}
mod private {
use super::*;
pub trait Sealed {}
impl Sealed for GuildType {}
impl Sealed for ChannelType {}
impl Sealed for MessageType {}
impl Sealed for UserType {}
}
impl<T: IdType> Type<Postgres> for Id<T> {
fn type_info() -> PgTypeInfo {
<&str as Type<Postgres>>::type_info()
}
}
impl<'r, T: IdType> Decode<'r, Postgres> for Id<T> {
fn decode(value: <Postgres as HasValueRef<'r>>::ValueRef) -> Result<Self, BoxDynError> {
let value = <&str as Decode<Postgres>>::decode(value)?;
Ok(Id::<T>::new(value.parse()?))
}
}
impl<'q, T: IdType> Encode<'q, Postgres> for Id<T> {
fn encode_by_ref(&self, buf: &mut <Postgres as HasArguments<'q>>::ArgumentBuffer) -> IsNull {
<&str as Encode<Postgres>>::encode(&self.0, buf)
}
}
impl<T: IdType> Serialize for Id<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.0)
}
}
impl<'de, T: IdType> Deserialize<'de> for Id<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self::new(String::deserialize(deserializer)?))
}
}

View file

@ -3,9 +3,11 @@ pub mod fed;
pub mod http;
pub mod model;
pub mod s2s;
pub mod id;
pub use error::FoxError;
pub use fed::signature;
pub use id::Id;
use chrono::{DateTime, Utc};
use ulid::Ulid;