Skip to main content

kellnr_db/
id.rs

1//! Typed primary keys, so the key of one table cannot be passed where the key
2//! of another one is expected. They are stored and serialized as plain numbers.
3
4use std::fmt;
5
6use sea_orm::DeriveValueType;
7use serde::{Deserialize, Serialize};
8use utoipa::ToSchema;
9
10macro_rules! id_type {
11    ($(#[$doc:meta])* $name:ident) => {
12        $(#[$doc])*
13        #[derive(
14            Default,
15            Debug,
16            Clone,
17            Copy,
18            PartialEq,
19            Eq,
20            PartialOrd,
21            Ord,
22            Hash,
23            Serialize,
24            Deserialize,
25            ToSchema,
26            DeriveValueType,
27        )]
28        #[serde(transparent)]
29        pub struct $name(i64);
30
31        impl $name {
32            pub const fn new(id: i64) -> Self {
33                Self(id)
34            }
35
36            pub const fn get(self) -> i64 {
37                self.0
38            }
39        }
40
41        impl fmt::Display for $name {
42            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43                self.0.fmt(f)
44            }
45        }
46    };
47}
48
49id_type!(
50    /// Primary key of a user.
51    UserId
52);
53id_type!(
54    /// Primary key of a group.
55    GroupId
56);
57id_type!(
58    /// Primary key of a crate hosted by Kellnr.
59    CrateId
60);
61id_type!(
62    /// Primary key of an auth token.
63    AuthTokenId
64);
65
66#[cfg(test)]
67mod tests {
68    use sea_orm::Value;
69
70    use super::*;
71
72    #[test]
73    fn ids_are_numbers_in_json() {
74        assert_eq!("42", serde_json::to_string(&UserId::new(42)).unwrap());
75        assert_eq!("7", serde_json::to_string(&AuthTokenId::new(7)).unwrap());
76        assert_eq!(
77            CrateId::new(3_000_000_000),
78            serde_json::from_str("3000000000").unwrap()
79        );
80        assert!(serde_json::from_str::<GroupId>(r#""1""#).is_err());
81    }
82
83    #[test]
84    fn ids_are_big_ints_in_the_database() {
85        assert_eq!(Value::BigInt(Some(5)), Value::from(GroupId::new(5)));
86    }
87}