Skip to main content

twilight_model/id/
mod.rs

1//! ID with type-safe markers for each resource.
2//!
3//! When IDs are simple 64-bit integers then it may be easy to accidentally use
4//! the ID of a role in place of where one means to use the ID of a user. This
5//! is a programmatic error; it's on the programmer to notice. By using IDs with
6//! typed markers, it can be ensured that only an ID with a guild marker is used
7//! where an ID with a guild marker is requested.
8//!
9//! # Parsing
10//!
11//! IDs may be initialized or parsed in a variety of manners depending on the
12//! context:
13//!
14//! - `serde` deserialization
15//! - [`std::str::FromStr`]
16//! - [`std::convert::TryFrom`]\<i64>
17//! - [`std::convert::TryFrom`]\<u64>
18//! - [`Id::new`]
19//! - [`Id::new_checked`]
20//! - [`Id::new_unchecked`]
21//! - [`std::convert::From`]<[`std::num::NonZeroU64`]>
22//!
23//! # Casting between resource types
24//!
25//! Discord may have constraints where IDs are the same across resources. For
26//! example, the `@everyone` role of a guild has the same ID as the guild
27//! itself. In this case, all one needs to do is use the guild's ID in place of
28//! a role in order to operate on the `@everyone` role of the guild. IDs can be
29//! easily casted in order to fulfill this:
30//!
31//! ```
32//! use twilight_model::id::{
33//!     Id,
34//!     marker::{GuildMarker, RoleMarker},
35//! };
36//!
37//! // Often Rust's type inference will be able to infer the type of ID.
38//! let guild_id = Id::<GuildMarker>::new(123);
39//! let role_id = guild_id.cast::<RoleMarker>();
40//!
41//! assert_eq!(guild_id.get(), role_id.get());
42//! ```
43
44pub mod marker;
45
46mod anonymizable;
47
48pub use anonymizable::AnonymizableId;
49
50use serde::{
51    de::{Deserialize, Deserializer, Error as DeError, Unexpected, Visitor},
52    ser::{Serialize, Serializer},
53};
54use std::{
55    any,
56    cmp::Ordering,
57    fmt::{Debug, Display, Formatter, Result as FmtResult},
58    hash::{Hash, Hasher},
59    marker::PhantomData,
60    num::{NonZero, ParseIntError, TryFromIntError},
61    str::FromStr,
62};
63
64/// ID of a resource, such as the ID of a [channel] or [user].
65///
66/// Markers themselves perform no logical action, and are only used to ensure
67/// that IDs of incorrect types aren't used. Read the [marker documentation] for
68/// additional information.
69///
70/// # serde
71///
72/// This ID deserializes from both integers and strings and serializes into a
73/// string.
74///
75/// [channel]: marker::ChannelMarker
76/// [marker documentation]: marker
77/// [user]: marker::UserMarker
78#[repr(transparent)]
79pub struct Id<T> {
80    phantom: PhantomData<fn(T) -> T>,
81    value: NonZero<u64>,
82}
83
84impl<T> Id<T> {
85    const fn from_nonzero(value: NonZero<u64>) -> Self {
86        Self {
87            phantom: PhantomData,
88            value,
89        }
90    }
91    /// Create a new ID, panicking if the value is zero.
92    ///
93    /// This is primarily useful in const contexts where you are passing a
94    /// hardcoded value.
95    ///
96    /// Refer to [`new_checked`] for a checked alternative to this method.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use twilight_model::id::{Id, marker::GenericMarker};
102    ///
103    /// const ID: Id<GenericMarker> = Id::new(123);
104    ///
105    /// println!("id: {ID}");
106    /// ```
107    ///
108    /// # Panics
109    ///
110    /// Panics if the value is 0.
111    ///
112    /// [`new_checked`]: Self::new_checked
113    #[track_caller]
114    pub const fn new(n: u64) -> Self {
115        if let Some(id) = Self::new_checked(n) {
116            id
117        } else {
118            panic!("value is zero");
119        }
120    }
121
122    /// Create an ID without checking if the value is non-zero.
123    ///
124    /// Equivalent to [`NonZeroU64::new_unchecked`].
125    ///
126    /// # Safety
127    ///
128    /// The value must not be zero.
129    #[allow(unsafe_code)]
130    pub const unsafe fn new_unchecked(n: u64) -> Self {
131        Self::from_nonzero(unsafe { NonZero::new_unchecked(n) })
132    }
133
134    /// Create an ID if the provided value is not zero.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use twilight_model::id::{Id, marker::GenericMarker};
140    ///
141    /// assert!(Id::<GenericMarker>::new_checked(123).is_some());
142    /// assert!(Id::<GenericMarker>::new_checked(0).is_none());
143    /// ```
144    ///
145    /// Equivalent to [`NonZeroU64::new`].
146    pub const fn new_checked(n: u64) -> Option<Self> {
147        if let Some(n) = NonZero::new(n) {
148            Some(Self::from_nonzero(n))
149        } else {
150            None
151        }
152    }
153
154    /// Return the inner primitive value.
155    ///
156    /// Equivalent to [`NonZeroU64::get`].
157    ///
158    /// # Examples
159    ///
160    /// Create an ID with a value and then confirm its inner value:
161    ///
162    /// ```
163    /// use twilight_model::id::{Id, marker::ChannelMarker};
164    ///
165    /// let channel_id = Id::<ChannelMarker>::new(7);
166    ///
167    /// assert_eq!(7, channel_id.get());
168    /// ```
169    pub const fn get(self) -> u64 {
170        self.value.get()
171    }
172
173    /// Return the [`NonZeroU64`] representation of the ID.
174    ///
175    /// # Examples
176    ///
177    /// Create an ID with a value and then confirm its nonzero value:
178    ///
179    /// ```
180    /// use std::num::NonZeroU64;
181    /// use twilight_model::id::{Id, marker::ChannelMarker};
182    ///
183    /// let channel_id = Id::<ChannelMarker>::new(7);
184    ///
185    /// assert_eq!(NonZeroU64::new(7).unwrap(), channel_id.into_nonzero());
186    /// ```
187    pub const fn into_nonzero(self) -> NonZero<u64> {
188        self.value
189    }
190
191    /// Cast an ID from one type to another.
192    ///
193    /// # Examples
194    ///
195    /// Cast a role ID to a guild ID, useful for the `@everyone` role:
196    ///
197    /// ```
198    /// use twilight_model::id::{
199    ///     Id,
200    ///     marker::{GuildMarker, RoleMarker},
201    /// };
202    ///
203    /// let role_id: Id<RoleMarker> = Id::new(1);
204    ///
205    /// let guild_id: Id<GuildMarker> = role_id.cast();
206    /// assert_eq!(1, guild_id.get());
207    /// ```
208    pub const fn cast<New>(self) -> Id<New> {
209        Id::from_nonzero(self.value)
210    }
211}
212
213impl<T> Clone for Id<T> {
214    fn clone(&self) -> Self {
215        *self
216    }
217}
218
219impl<T> Copy for Id<T> {}
220
221impl<T> Debug for Id<T> {
222    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
223        f.write_str("Id")?;
224        let type_name = any::type_name::<T>();
225
226        // `any::type_name` will usually provide an FQN, so we'll do our best
227        // (and simplest) method here of removing it to only get the type name
228        // itself.
229        if let Some(position) = type_name.rfind("::")
230            && let Some(slice) = type_name.get(position + 2..)
231        {
232            f.write_str("<")?;
233            f.write_str(slice)?;
234            f.write_str(">")?;
235        }
236
237        f.write_str("(")?;
238        Debug::fmt(&self.value, f)?;
239
240        f.write_str(")")
241    }
242}
243
244impl<'de, T> Deserialize<'de> for Id<T> {
245    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
246        struct IdVisitor;
247
248        impl<'de> Visitor<'de> for IdVisitor {
249            type Value = NonZero<u64>;
250
251            fn expecting(&self, f: &mut Formatter<'_>) -> FmtResult {
252                f.write_str("a discord snowflake")
253            }
254
255            fn visit_u64<E: DeError>(self, value: u64) -> Result<Self::Value, E> {
256                let value = NonZero::new(value).ok_or_else(|| {
257                    DeError::invalid_value(Unexpected::Unsigned(value), &"non zero u64")
258                })?;
259
260                Ok(value)
261            }
262
263            fn visit_i64<E: DeError>(self, value: i64) -> Result<Self::Value, E> {
264                let unsigned = u64::try_from(value).map_err(|_| {
265                    DeError::invalid_value(Unexpected::Signed(value), &"non zero u64")
266                })?;
267
268                self.visit_u64(unsigned)
269            }
270
271            fn visit_newtype_struct<D: Deserializer<'de>>(
272                self,
273                deserializer: D,
274            ) -> Result<Self::Value, D::Error> {
275                deserializer.deserialize_any(IdVisitor)
276            }
277
278            fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
279                let value = v.parse().map_err(|_| {
280                    let unexpected = Unexpected::Str(v);
281
282                    DeError::invalid_value(unexpected, &"non zero u64 string")
283                })?;
284
285                self.visit_u64(value)
286            }
287        }
288
289        Ok(deserializer.deserialize_any(IdVisitor)?.into())
290    }
291}
292
293impl<T> Display for Id<T> {
294    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
295        Display::fmt(&self.value.get(), f)
296    }
297}
298
299impl<T> From<Id<T>> for u64 {
300    fn from(id: Id<T>) -> Self {
301        id.get()
302    }
303}
304
305impl<T> From<NonZero<u64>> for Id<T> {
306    fn from(id: NonZero<u64>) -> Self {
307        Self::from_nonzero(id)
308    }
309}
310
311impl<T> From<Id<T>> for NonZero<u64> {
312    fn from(id: Id<T>) -> Self {
313        id.into_nonzero()
314    }
315}
316
317impl<T> FromStr for Id<T> {
318    type Err = ParseIntError;
319
320    fn from_str(s: &str) -> Result<Self, Self::Err> {
321        NonZero::from_str(s).map(Self::from_nonzero)
322    }
323}
324
325impl<T> Eq for Id<T> {}
326
327impl<T> Hash for Id<T> {
328    fn hash<U: Hasher>(&self, state: &mut U) {
329        state.write_u64(self.value.get());
330    }
331}
332
333impl<T> Ord for Id<T> {
334    fn cmp(&self, other: &Self) -> Ordering {
335        self.value.cmp(&other.value)
336    }
337}
338
339impl<T> PartialEq for Id<T> {
340    fn eq(&self, other: &Self) -> bool {
341        self.value == other.value
342    }
343}
344
345impl<T> PartialEq<i64> for Id<T> {
346    fn eq(&self, other: &i64) -> bool {
347        u64::try_from(*other).is_ok_and(|v| v == self.value.get())
348    }
349}
350
351impl<T> PartialEq<Id<T>> for i64 {
352    fn eq(&self, other: &Id<T>) -> bool {
353        u64::try_from(*self).is_ok_and(|v| v == other.value.get())
354    }
355}
356
357impl<T> PartialEq<u64> for Id<T> {
358    fn eq(&self, other: &u64) -> bool {
359        self.value.get() == *other
360    }
361}
362
363impl<T> PartialEq<Id<T>> for u64 {
364    fn eq(&self, other: &Id<T>) -> bool {
365        other.value.get() == *self
366    }
367}
368
369impl<T> PartialOrd for Id<T> {
370    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
371        Some(self.cmp(other))
372    }
373}
374
375impl<T> Serialize for Id<T> {
376    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
377        serializer.serialize_newtype_struct("Id", &self.to_string())
378    }
379}
380
381impl<T> TryFrom<i64> for Id<T> {
382    type Error = TryFromIntError;
383
384    fn try_from(value: i64) -> Result<Self, Self::Error> {
385        let signed_nonzero = NonZero::try_from(value)?;
386        let unsigned_nonzero = NonZero::try_from(signed_nonzero)?;
387
388        Ok(Self::from_nonzero(unsigned_nonzero))
389    }
390}
391
392impl<T> TryFrom<u64> for Id<T> {
393    type Error = TryFromIntError;
394
395    fn try_from(value: u64) -> Result<Self, Self::Error> {
396        let nonzero = NonZero::try_from(value)?;
397
398        Ok(Self::from_nonzero(nonzero))
399    }
400}
401
402#[cfg(test)]
403mod tests {
404    use super::{
405        Id,
406        marker::{
407            ApplicationMarker, AttachmentMarker, AuditLogEntryMarker, ChannelMarker, CommandMarker,
408            CommandVersionMarker, EmojiMarker, EntitlementMarker, GenericMarker, GuildMarker,
409            IntegrationMarker, InteractionMarker, MessageMarker, RoleMarker,
410            RoleSubscriptionSkuMarker, SkuMarker, StageMarker, UserMarker, WebhookMarker,
411        },
412    };
413    use serde::{Deserialize, Serialize};
414    use serde_test::Token;
415    use static_assertions::assert_impl_all;
416    use std::{
417        collections::hash_map::DefaultHasher,
418        error::Error,
419        fmt::{Debug, Display},
420        hash::{Hash, Hasher},
421        num::NonZeroU64,
422        str::FromStr,
423    };
424
425    assert_impl_all!(ApplicationMarker: Debug, Send, Sync);
426    assert_impl_all!(AttachmentMarker: Debug, Send, Sync);
427    assert_impl_all!(AuditLogEntryMarker: Debug, Send, Sync);
428    assert_impl_all!(ChannelMarker: Debug, Send, Sync);
429    assert_impl_all!(CommandMarker: Debug, Send, Sync);
430    assert_impl_all!(CommandVersionMarker: Debug, Send, Sync);
431    assert_impl_all!(EmojiMarker: Debug, Send, Sync);
432    assert_impl_all!(EntitlementMarker: Debug, Send, Sync);
433    assert_impl_all!(SkuMarker: Debug, Send, Sync);
434    assert_impl_all!(GenericMarker: Debug, Send, Sync);
435    assert_impl_all!(GuildMarker: Debug, Send, Sync);
436    assert_impl_all!(IntegrationMarker: Debug, Send, Sync);
437    assert_impl_all!(InteractionMarker: Debug, Send, Sync);
438    assert_impl_all!(MessageMarker: Debug, Send, Sync);
439    assert_impl_all!(RoleMarker: Debug, Send, Sync);
440    assert_impl_all!(RoleSubscriptionSkuMarker: Debug, Send, Sync);
441    assert_impl_all!(StageMarker: Debug, Send, Sync);
442    assert_impl_all!(UserMarker: Debug, Send, Sync);
443    assert_impl_all!(WebhookMarker: Debug, Send, Sync);
444    assert_impl_all!(Id<GenericMarker>:
445        Clone, Copy, Debug, Deserialize<'static>, Display, Eq, From<NonZeroU64>,
446        FromStr, Hash, Into<NonZeroU64>, Into<u64>, Ord, PartialEq, PartialEq<i64>, PartialEq<u64>, PartialOrd, Send, Serialize, Sync,
447        TryFrom<i64>, TryFrom<u64>
448    );
449    // assert invariant
450    assert_impl_all!(Id<*const ()>: Send, Sync);
451
452    /// Test that various methods of initializing IDs are correct, such as via
453    /// [`Id::new`] or [`Id`]'s [`TryFrom`] implementations.
454    #[test]
455    fn initializers() -> Result<(), Box<dyn Error>> {
456        // `Id::new_checked`
457        assert!(Id::<GenericMarker>::new_checked(0).is_none());
458        assert_eq!(Some(1), Id::<GenericMarker>::new_checked(1).map(Id::get));
459
460        // `Id::new`
461        assert_eq!(1, Id::<GenericMarker>::new(1).get());
462
463        // `From`
464        assert_eq!(
465            123_u64,
466            Id::<GenericMarker>::from(NonZeroU64::new(123).expect("non zero"))
467        );
468
469        // `FromStr`
470        assert_eq!(123_u64, Id::<GenericMarker>::from_str("123")?);
471        assert!(Id::<GenericMarker>::from_str("0").is_err());
472        assert!(Id::<GenericMarker>::from_str("123a").is_err());
473
474        // `TryFrom`
475        assert!(Id::<GenericMarker>::try_from(-123_i64).is_err());
476        assert!(Id::<GenericMarker>::try_from(0_i64).is_err());
477        assert_eq!(123_u64, Id::<GenericMarker>::try_from(123_i64)?);
478        assert!(Id::<GenericMarker>::try_from(0_u64).is_err());
479        assert_eq!(123_u64, Id::<GenericMarker>::try_from(123_u64)?);
480
481        Ok(())
482    }
483
484    /// Test that conversion methods are correct.
485    #[test]
486    fn conversions() {
487        // `Into`
488        assert_eq!(1, u64::from(Id::<GenericMarker>::new(1)));
489        assert_eq!(
490            NonZeroU64::new(1).expect("non zero"),
491            NonZeroU64::from(Id::<GenericMarker>::new(1))
492        );
493    }
494
495    /// Test that creating an ID via [`Id::new`] with a value of zero panics.
496    #[should_panic(expected = "value is zero")]
497    #[test]
498    const fn test_new_checked_zero() {
499        _ = Id::<GenericMarker>::new(0);
500    }
501
502    /// Test that casting IDs maintains the original value.
503    #[test]
504    fn cast() {
505        let id = Id::<GenericMarker>::new(123);
506        assert_eq!(123_u64, id.cast::<RoleMarker>());
507    }
508
509    /// Test that debugging IDs formats the generic and value as a newtype.
510    #[test]
511    fn debug() {
512        let id = Id::<RoleMarker>::new(114_941_315_417_899_012);
513
514        assert_eq!("Id<RoleMarker>(114941315417899012)", format!("{id:?}"));
515    }
516
517    /// Test that display formatting an ID formats the value.
518    #[test]
519    fn display() {
520        let id = Id::<GenericMarker>::new(114_941_315_417_899_012);
521
522        assert_eq!("114941315417899012", id.to_string());
523    }
524
525    /// Test that hashing an ID is equivalent to hashing only its inner value.
526    #[test]
527    fn hash() {
528        let id = Id::<GenericMarker>::new(123);
529
530        let mut id_hasher = DefaultHasher::new();
531        id.hash(&mut id_hasher);
532
533        let mut value_hasher = DefaultHasher::new();
534        123_u64.hash(&mut value_hasher);
535
536        assert_eq!(id_hasher.finish(), value_hasher.finish());
537    }
538
539    /// Test that IDs are ordered exactly like their inner values.
540    #[test]
541    fn ordering() {
542        let lesser = Id::<GenericMarker>::new(911_638_235_594_244_096);
543        let center = Id::<GenericMarker>::new(911_638_263_322_800_208);
544        let greater = Id::<GenericMarker>::new(911_638_287_939_166_208);
545
546        assert!(center.cmp(&greater).is_lt());
547        assert!(center.cmp(&center).is_eq());
548        assert!(center.cmp(&lesser).is_gt());
549    }
550
551    #[allow(clippy::too_many_lines)]
552    #[test]
553    fn serde() {
554        serde_test::assert_tokens(
555            &Id::<ApplicationMarker>::new(114_941_315_417_899_012),
556            &[
557                Token::NewtypeStruct { name: "Id" },
558                Token::Str("114941315417899012"),
559            ],
560        );
561        serde_test::assert_de_tokens(
562            &Id::<ApplicationMarker>::new(114_941_315_417_899_012),
563            &[
564                Token::NewtypeStruct { name: "Id" },
565                Token::U64(114_941_315_417_899_012),
566            ],
567        );
568        serde_test::assert_tokens(
569            &Id::<AttachmentMarker>::new(114_941_315_417_899_012),
570            &[
571                Token::NewtypeStruct { name: "Id" },
572                Token::Str("114941315417899012"),
573            ],
574        );
575        serde_test::assert_de_tokens(
576            &Id::<AttachmentMarker>::new(114_941_315_417_899_012),
577            &[
578                Token::NewtypeStruct { name: "Id" },
579                Token::U64(114_941_315_417_899_012),
580            ],
581        );
582        serde_test::assert_tokens(
583            &Id::<AuditLogEntryMarker>::new(114_941_315_417_899_012),
584            &[
585                Token::NewtypeStruct { name: "Id" },
586                Token::Str("114941315417899012"),
587            ],
588        );
589        serde_test::assert_de_tokens(
590            &Id::<AuditLogEntryMarker>::new(114_941_315_417_899_012),
591            &[
592                Token::NewtypeStruct { name: "Id" },
593                Token::U64(114_941_315_417_899_012),
594            ],
595        );
596        serde_test::assert_tokens(
597            &Id::<ChannelMarker>::new(114_941_315_417_899_012),
598            &[
599                Token::NewtypeStruct { name: "Id" },
600                Token::Str("114941315417899012"),
601            ],
602        );
603        serde_test::assert_de_tokens(
604            &Id::<ChannelMarker>::new(114_941_315_417_899_012),
605            &[
606                Token::NewtypeStruct { name: "Id" },
607                Token::U64(114_941_315_417_899_012),
608            ],
609        );
610        serde_test::assert_tokens(
611            &Id::<CommandMarker>::new(114_941_315_417_899_012),
612            &[
613                Token::NewtypeStruct { name: "Id" },
614                Token::Str("114941315417899012"),
615            ],
616        );
617        serde_test::assert_de_tokens(
618            &Id::<CommandMarker>::new(114_941_315_417_899_012),
619            &[
620                Token::NewtypeStruct { name: "Id" },
621                Token::U64(114_941_315_417_899_012),
622            ],
623        );
624        serde_test::assert_tokens(
625            &Id::<CommandVersionMarker>::new(114_941_315_417_899_012),
626            &[
627                Token::NewtypeStruct { name: "Id" },
628                Token::Str("114941315417899012"),
629            ],
630        );
631        serde_test::assert_de_tokens(
632            &Id::<CommandVersionMarker>::new(114_941_315_417_899_012),
633            &[
634                Token::NewtypeStruct { name: "Id" },
635                Token::U64(114_941_315_417_899_012),
636            ],
637        );
638        serde_test::assert_tokens(
639            &Id::<EmojiMarker>::new(114_941_315_417_899_012),
640            &[
641                Token::NewtypeStruct { name: "Id" },
642                Token::Str("114941315417899012"),
643            ],
644        );
645        serde_test::assert_de_tokens(
646            &Id::<EmojiMarker>::new(114_941_315_417_899_012),
647            &[
648                Token::NewtypeStruct { name: "Id" },
649                Token::U64(114_941_315_417_899_012),
650            ],
651        );
652        serde_test::assert_tokens(
653            &Id::<EntitlementMarker>::new(114_941_315_417_899_012),
654            &[
655                Token::NewtypeStruct { name: "Id" },
656                Token::Str("114941315417899012"),
657            ],
658        );
659        serde_test::assert_de_tokens(
660            &Id::<EntitlementMarker>::new(114_941_315_417_899_012),
661            &[
662                Token::NewtypeStruct { name: "Id" },
663                Token::Str("114941315417899012"),
664            ],
665        );
666        serde_test::assert_tokens(
667            &Id::<SkuMarker>::new(114_941_315_417_899_012),
668            &[
669                Token::NewtypeStruct { name: "Id" },
670                Token::Str("114941315417899012"),
671            ],
672        );
673        serde_test::assert_de_tokens(
674            &Id::<SkuMarker>::new(114_941_315_417_899_012),
675            &[
676                Token::NewtypeStruct { name: "Id" },
677                Token::Str("114941315417899012"),
678            ],
679        );
680        serde_test::assert_tokens(
681            &Id::<GenericMarker>::new(114_941_315_417_899_012),
682            &[
683                Token::NewtypeStruct { name: "Id" },
684                Token::Str("114941315417899012"),
685            ],
686        );
687        serde_test::assert_de_tokens(
688            &Id::<GenericMarker>::new(114_941_315_417_899_012),
689            &[
690                Token::NewtypeStruct { name: "Id" },
691                Token::U64(114_941_315_417_899_012),
692            ],
693        );
694        serde_test::assert_tokens(
695            &Id::<GuildMarker>::new(114_941_315_417_899_012),
696            &[
697                Token::NewtypeStruct { name: "Id" },
698                Token::Str("114941315417899012"),
699            ],
700        );
701        serde_test::assert_de_tokens(
702            &Id::<GuildMarker>::new(114_941_315_417_899_012),
703            &[
704                Token::NewtypeStruct { name: "Id" },
705                Token::U64(114_941_315_417_899_012),
706            ],
707        );
708        serde_test::assert_tokens(
709            &Id::<IntegrationMarker>::new(114_941_315_417_899_012),
710            &[
711                Token::NewtypeStruct { name: "Id" },
712                Token::Str("114941315417899012"),
713            ],
714        );
715        serde_test::assert_de_tokens(
716            &Id::<IntegrationMarker>::new(114_941_315_417_899_012),
717            &[
718                Token::NewtypeStruct { name: "Id" },
719                Token::U64(114_941_315_417_899_012),
720            ],
721        );
722        serde_test::assert_tokens(
723            &Id::<InteractionMarker>::new(114_941_315_417_899_012),
724            &[
725                Token::NewtypeStruct { name: "Id" },
726                Token::Str("114941315417899012"),
727            ],
728        );
729        serde_test::assert_de_tokens(
730            &Id::<InteractionMarker>::new(114_941_315_417_899_012),
731            &[
732                Token::NewtypeStruct { name: "Id" },
733                Token::U64(114_941_315_417_899_012),
734            ],
735        );
736        serde_test::assert_tokens(
737            &Id::<MessageMarker>::new(114_941_315_417_899_012),
738            &[
739                Token::NewtypeStruct { name: "Id" },
740                Token::Str("114941315417899012"),
741            ],
742        );
743        serde_test::assert_de_tokens(
744            &Id::<MessageMarker>::new(114_941_315_417_899_012),
745            &[
746                Token::NewtypeStruct { name: "Id" },
747                Token::U64(114_941_315_417_899_012),
748            ],
749        );
750        serde_test::assert_tokens(
751            &Id::<RoleMarker>::new(114_941_315_417_899_012),
752            &[
753                Token::NewtypeStruct { name: "Id" },
754                Token::Str("114941315417899012"),
755            ],
756        );
757        serde_test::assert_de_tokens(
758            &Id::<RoleMarker>::new(114_941_315_417_899_012),
759            &[
760                Token::NewtypeStruct { name: "Id" },
761                Token::U64(114_941_315_417_899_012),
762            ],
763        );
764        serde_test::assert_tokens(
765            &Id::<RoleSubscriptionSkuMarker>::new(114_941_315_417_899_012),
766            &[
767                Token::NewtypeStruct { name: "Id" },
768                Token::Str("114941315417899012"),
769            ],
770        );
771        serde_test::assert_tokens(
772            &Id::<StageMarker>::new(114_941_315_417_899_012),
773            &[
774                Token::NewtypeStruct { name: "Id" },
775                Token::Str("114941315417899012"),
776            ],
777        );
778        serde_test::assert_de_tokens(
779            &Id::<StageMarker>::new(114_941_315_417_899_012),
780            &[
781                Token::NewtypeStruct { name: "Id" },
782                Token::U64(114_941_315_417_899_012),
783            ],
784        );
785        serde_test::assert_tokens(
786            &Id::<UserMarker>::new(114_941_315_417_899_012),
787            &[
788                Token::NewtypeStruct { name: "Id" },
789                Token::Str("114941315417899012"),
790            ],
791        );
792        serde_test::assert_de_tokens(
793            &Id::<UserMarker>::new(114_941_315_417_899_012),
794            &[
795                Token::NewtypeStruct { name: "Id" },
796                Token::U64(114_941_315_417_899_012),
797            ],
798        );
799        serde_test::assert_tokens(
800            &Id::<WebhookMarker>::new(114_941_315_417_899_012),
801            &[
802                Token::NewtypeStruct { name: "Id" },
803                Token::Str("114941315417899012"),
804            ],
805        );
806        serde_test::assert_de_tokens(
807            &Id::<WebhookMarker>::new(114_941_315_417_899_012),
808            &[
809                Token::NewtypeStruct { name: "Id" },
810                Token::U64(114_941_315_417_899_012),
811            ],
812        );
813        serde_test::assert_de_tokens(
814            &Id::<WebhookMarker>::new(114_941_315_417_899_012),
815            &[
816                Token::NewtypeStruct { name: "Id" },
817                Token::I64(114_941_315_417_899_012),
818            ],
819        );
820    }
821}