Skip to content

Commit

Permalink
commit hacky way of bson serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
TroyKomodo committed Apr 19, 2024
1 parent cd78a77 commit 8c3ab14
Show file tree
Hide file tree
Showing 24 changed files with 62 additions and 101 deletions.
115 changes: 38 additions & 77 deletions shared/src/database/id.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

use chrono::TimeZone;
use mongodb::bson::oid::{ObjectId, Error as OidError};
use mongodb::bson::oid::{Error as OidError, ObjectId};
use mongodb::bson::uuid::Uuid as BsonUuid;
use mongodb::bson::Bson;

Expand Down Expand Up @@ -240,100 +240,61 @@ impl<S> std::fmt::Display for Id<S> {
}
}

/// Very Hacky way to check if the current serializer/deserializer is the
/// MongoDB BSON one This is used to determine if we should
/// serialize/deserialize the ID as a BSON UUID or a string This can be fixed
/// when we use specialization (nightly only)
///
/// #![feature(min_specialization)]
///
/// trait IsBsonSerializer {
/// const IS_BSON_SERIALIZER: bool;
/// }
///
/// impl IsBsonSerializer for mongodb::bson::ser::Serializer {
/// const IS_BSON_SERIALIZER: bool = true;
/// }
///
/// impl IsBsonSerializer for mongodb::bson::de::Deserializer {
/// const IS_BSON_SERIALIZER: bool = true;
/// }
///
/// impl<T> IsBsonSerializer for T {
/// default const IS_BSON_SERIALIZER: bool = false;
/// }
fn matches<U, T>() -> bool {
std::any::type_name::<U>().contains(std::any::type_name::<T>())
}

impl<S> serde::Serialize for Id<S> {
fn serialize<T: serde::Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error> {
self.to_string().serialize(serializer)
if matches::<T, mongodb::bson::ser::Serializer>() {
BsonUuid::from(*self).serialize(serializer)
} else {
self.to_string().serialize(serializer)
}
}
}

impl<'de, S> serde::Deserialize<'de> for Id<S> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
String::deserialize(deserializer)?.parse().map_err(serde::de::Error::custom)
}
}

pub mod bson {
use serde::{Deserialize, Serialize};

use super::*;

pub trait IdLike<S>: Sized {
fn encode<T: serde::Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error>;
fn decode<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>;
}

impl<S> IdLike<S> for Id<S> {
fn encode<T: serde::Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error> {
BsonUuid::from(*self).serialize(serializer)
}

fn decode<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
if matches::<D, mongodb::bson::de::Deserializer>() {
BsonUuid::deserialize(deserializer).map(Self::from)
} else {
String::deserialize(deserializer)?.parse().map_err(serde::de::Error::custom)
}
}

impl<S, T> IdLike<S> for Option<T>
where
T: IdLike<S>,
{
fn encode<U: serde::Serializer>(&self, serializer: U) -> Result<U::Ok, U::Error> {
match self {
Some(value) => value.encode(serializer),
None => serializer.serialize_none(),
}
}

fn decode<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor<T, S>(std::marker::PhantomData<(T, S)>);

impl<'de, T, S> serde::de::Visitor<'de> for Visitor<T, S>
where
T: IdLike<S>,
{
type Value = Option<T>;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "an optional value")
}

fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
Ok(None)
}

fn visit_some<D: serde::Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
T::decode(deserializer).map(Some)
}
}

deserializer.deserialize_option(Visitor(std::marker::PhantomData))
}
}

pub fn serialize<S, T, U>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: IdLike<U>,
{
value.encode(serializer)
}

pub fn deserialize<'de, T, D, U>(deserializer: D) -> Result<T, D::Error>
where
D: serde::Deserializer<'de>,
T: IdLike<U>,
{
T::decode(deserializer)
}
}

#[cfg(test)]
mod tests {
use super::*;
use mongodb::bson;

use super::*;

#[derive(serde::Serialize, serde::Deserialize)]
struct TestBson {
#[serde(with = "super::bson", rename = "_id")]
#[serde(rename = "_id")]
id: Id,
}

Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/automod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type AutomodRuleId = Id<AutomodRule>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct AutomodRule {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: AutomodRuleId,
pub name: String,
pub description: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/badge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub type BadgeId = Id<Badge>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Badge {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: BadgeId,
pub name: String,
pub description: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/emote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub type EmoteId = Id<Emote>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Emote {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: EmoteId,
pub owner_id: Option<UserId>,
pub default_name: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/emote_set/emote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub type EmoteSetEmoteId = Id<EmoteSetEmote>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct EmoteSetEmote {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: EmoteSetEmoteId,
pub emote_set_id: EmoteSetId,
pub emote_id: EmoteId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/emote_set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub type EmoteSetId = Id<EmoteSet>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct EmoteSet {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: EmoteSetId,
pub owner_id: Option<UserId>,
pub name: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type FileSetId = Id<FileSet>;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct FileSet {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: FileSetId,
pub kind: FileSetKind,
pub authenticated: bool,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type GlobalConfigId = Id<GlobalConfig>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct GlobalConfig {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: GlobalConfigId,
pub alerts: GlobalConfigAlerts,
pub emote_set_ids: Vec<EmoteSetId>,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type PageId = Id<Page>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Page {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: PageId,
pub kind: PageKind,
pub title: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/paint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub type PaintId = Id<Paint>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Paint {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: PaintId,
pub name: String,
pub description: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/product/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type ProductCodeId = Id<ProductCode>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct ProductCode {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: ProductCodeId,
pub owner_id: Option<UserId>,
pub purchase_id: Option<ProductPurchaseId>,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/product/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub type ProductId = Id<Product>;
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Product {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: ProductId,
pub name: String,
pub description: String,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/product/purchase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type ProductPurchaseId = Id<ProductPurchase>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct ProductPurchase {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: ProductPurchaseId,
pub product_id: ProductId,
pub user_id: Option<UserId>,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/role/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub type RoleId = Id<Role>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Role {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: RoleId,
pub badge_ids: Vec<BadgeId>,
pub paint_ids: Vec<PaintId>,
Expand Down
4 changes: 2 additions & 2 deletions shared/src/database/types/ticket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub type TicketId = Id<Ticket>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Ticket {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: TicketId,
pub kind: TicketKind,
pub status: TicketStatus,
Expand All @@ -62,7 +62,7 @@ pub type TicketMemberId = Id<TicketMember>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct TicketMember {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: TicketMemberId,
pub ticket_id: TicketId,
pub user_id: UserId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/ban.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserBanId = Id<UserBan>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserBan {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserBanId,
pub user_id: UserId,
pub created_by_id: Option<UserId>,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub type UserConnectionId = Id<UserConnection>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserConnection {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserConnectionId,
pub user_id: UserId,
pub main_connection: bool,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub type UserEditorId = Id<UserEditor>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserEditor {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserEditorId,
pub user_id: UserId,
pub editor_id: UserId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/gift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserGiftId = Id<UserGift>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserGift {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserGiftId,
pub sender_id: Option<UserId>,
pub recipient_id: UserId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub type UserId = Id<User>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct User {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserId,
pub email: Option<String>,
pub email_verified: bool,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/presence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserPresenceId = Id<UserPresence>;
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserPresence {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserPresenceId,
pub user_id: UserId,
pub platform: Platform,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/product.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserProductId = Id<UserProduct>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserProduct {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserProductId,
pub user_id: UserId,
pub product_id: ProductId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserRelationId = Id<UserRelation>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserRelation {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserRelationId,
pub user_id: UserId,
pub other_user_id: UserId,
Expand Down
2 changes: 1 addition & 1 deletion shared/src/database/types/user/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub type UserSessionId = Id<UserSession>;
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct UserSession {
#[serde(rename = "_id", with = "crate::database::id::bson")]
#[serde(rename = "_id")]
pub id: UserSessionId,
pub user_id: UserId,
pub expires_at: chrono::DateTime<chrono::Utc>,
Expand Down

0 comments on commit 8c3ab14

Please sign in to comment.