af_core/util/
uuid.rs

1// Copyright © 2020 Alexandra Frydl
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use crate::prelude::*;
8use ::uuid::{Builder, Uuid as Inner, Variant, Version};
9
10/// A universally-unique identifier.
11#[derive(
12  Clone, Copy, Default, Deserialize, Eq, From, FromStr, Hash, Ord, PartialEq, PartialOrd, Serialize,
13)]
14#[serde(transparent)]
15pub struct Uuid(Inner);
16
17impl Uuid {
18  /// Returns a "nil" UUID.
19  pub const fn nil() -> Self {
20    Self(Inner::nil())
21  }
22
23  /// Returns `true` if the UUID is the "nil" value.
24  pub fn is_nil(&self) -> bool {
25    self.0.is_nil()
26  }
27
28  /// Returns a new, random UUID.
29  pub fn new() -> Self {
30    random()
31  }
32
33  /// Returns a slice containing the bytes of the UUID.
34  pub fn as_bytes(&self) -> &[u8] {
35    self.0.as_bytes()
36  }
37
38  /// Converts the UUID to a `u128`.
39  pub fn to_u128(&self) -> u128 {
40    self.0.as_u128()
41  }
42}
43
44// Implement random generation.
45
46impl Random for Uuid {
47  fn random_with(rng: &mut random::Rng) -> Self {
48    let mut bytes = [0u8; 16];
49
50    rng.fill_bytes(&mut bytes);
51
52    let uuid =
53      Builder::from_bytes(bytes).set_variant(Variant::RFC4122).set_version(Version::Random).build();
54
55    Self(uuid)
56  }
57}
58
59// Implement formatting.
60
61macro_rules! impl_fmt {
62  ($ty:ident) => {
63    impl fmt::$ty for Uuid {
64      fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        fmt::$ty::fmt(&self.0, f)
66      }
67    }
68  };
69}
70
71impl_fmt!(Debug);
72impl_fmt!(Display);
73impl_fmt!(LowerHex);
74impl_fmt!(UpperHex);
75
76// Implement conversion to and from postgres.
77
78cfg_if! {
79  if #[cfg(feature = "postgres")] {
80    use postgres_types as pg;
81
82    impl<'a> pg::FromSql<'a> for Uuid {
83      fn from_sql(ty: &pg::Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>{
84        Ok(Self(pg::FromSql::from_sql(ty, raw)?))
85      }
86
87      fn accepts(ty: &pg::Type) -> bool {
88        <Inner as pg::FromSql>::accepts(ty)
89      }
90    }
91
92    impl pg::ToSql for Uuid {
93      fn to_sql(&self, ty: &pg::Type, out: &mut bytes::BytesMut) -> Result<pg::IsNull, Box<dyn Error + Sync + Send>>
94      where
95        Self: Sized,
96      {
97        self.0.to_sql(ty, out)
98      }
99
100      fn accepts(ty: &pg::Type) -> bool
101      where
102        Self: Sized,
103      {
104        <Inner as pg::ToSql>::accepts(ty)
105      }
106
107      fn to_sql_checked(&self, ty: &pg::Type, out: &mut bytes::BytesMut) -> Result<pg::IsNull, Box<dyn Error + Sync + Send>> {
108        self.0.to_sql_checked(ty, out)
109      }
110    }
111  }
112}