1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#![deny(missing_docs, missing_crate_level_docs)]

//! This crate exports a single macro to create your own newtyped Uuids more conveniently.
//! It is not the most fully featured macro, and it comes baked in with a lot of assumptions,
//! such as Serde and using Uuid v4. These assumptions derive from my own workflow,
//! where I find this macro very convenient.
//!
//! ## When would you want to use a macro such as this?
//!
//! Whenver you are dealing with multiple types of Ids on a single object, having a variety
//! of Uuids can effectively make you feel like you're working in a dynamic language. This
//! can happen especially in game development, or any development which has lots of asset management.
//! Imagine you have Entities which use Uuids as some unique id (perhaps of their save files),
//! and you have Assets, which are also using Uuids. You also have Prefabs, which are a kind of entity,
//! which you address like as Asset, which also have their own Uuid. As you might imagine,
//! this is a lot of Uuids to keep around and make sure to not mess up.
//!
//! This newtype wrapper greatly simplifies, but only by adding the small compiler error to warn
//! you against accidentally confusing your Uuids. Simply access the newtype directly with `.0`,
//! and you are back in full control over the raw Uuid data. Having our newtypes be an opaque
//! wrapper is a non-goal of this project
/// Make your own Uuid.
///
/// We might use this to differentiate between two different identifiers:
/// ```
/// # #[macro_use] extern crate mouuid;
/// # fn main() {
/// // we have an entity id...
/// my_own_uuid!(EntityId);
///
/// // and we have an asset id...
/// my_own_uuid!(AssetId);
///
/// // an example struct...
/// struct Entity {
///     id: EntityId,
///     sprite: AssetId,
/// }
///
/// let my_new_entity = Entity {
///     id: EntityId::new(),
///     sprite: AssetId::new()
/// };
///
/// // you'd get this from some sort of database in real code.
/// let my_other_asset = AssetId::new();
///
/// // this line won't compile because of the newtype wrapper!
/// // if my_new_entity.id == my_other_asset {
///
/// // but this line WILL compile!
/// if my_new_entity.sprite == my_other_asset {
///     // explode, we had a Uuid collision, contact the UN, the impossible happened.
///     // but actually you probably got this from a database, rather than
///     // constructed them inline.
/// }
/// # }
/// ```
/// Important note here: you can document your own Uuid like so:
///
/// ```
/// # #[macro_use] extern crate mouuid;
/// # fn main() {
/// my_own_uuid!(
///     /// An EntityId is a very good id. It's honestly
///     /// my *favorite* id. Don't tell the other ids.
///     EntityId
/// );
/// # }
/// ```
/// The above will show up in docs and in most IDEs when you hover over an EntityId!
#[macro_export]
macro_rules! my_own_uuid {
    ($(#[$meta:meta])* $this_val:ident) => {
        #[derive(
            PartialEq, Eq, Hash, Copy, Clone, Default, Debug, PartialOrd, Ord,
        )]
        #[derive(serde::Serialize, serde::Deserialize)]
        $(#[$meta])*
        pub struct $this_val(pub uuid::Uuid);

        impl $this_val {
            /// Creates a new Id using `Uuid::new_v4` which is randomly generated.
            #[inline]
            #[allow(dead_code)]
            pub fn new() -> Self {
                Self(uuid::Uuid::new_v4())
            }

            /// Creates a new Id with the provided Uuid.
            #[inline]
            #[allow(dead_code)]
            pub fn with_id(id: uuid::Uuid) -> Self {
                Self(id)
            }

            /// Creates a new Id with the provided String, attempting to parse it into a Uuid.
            #[inline]
            #[allow(dead_code)]
            pub fn with_string(input: &str) -> Result<Self, uuid::Error> {
                Ok(Self(uuid::Uuid::parse_str(input)?))
            }
        }

        impl std::fmt::Display for $this_val {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}({})", stringify!($this_val), self.0)
            }
        }
    };
}