thegraph_core/
allocation_id.rs

1use alloy::primitives::Address;
2
3/// A unique identifier for an allocation: the allocation's Ethereum address.
4///
5/// This is a "new-type" wrapper around [`Address`] to provide type safety.
6///
7/// ## Formatting
8///
9/// The `AllocationId` type implements the following formatting traits:
10///
11/// - Use [`std::fmt::Display`] for formatting the `AllocationId` as an [EIP-55] checksum string.
12/// - Use [`std::fmt::LowerHex`] (or [`std::fmt::UpperHex`]) for formatting   the `AllocationId` as
13///   a hexadecimal string.
14///
15/// See the [`Display`], [`LowerHex`], and [`UpperHex`] trait implementations for usage examples.
16///
17/// ## Generating test data
18///
19/// The `AllocationId` type implements the [`fake`] crate's [`fake::Dummy`] trait, allowing you to
20/// generate random `AllocationId` values for testing.
21///
22/// Note that the `fake` feature must be enabled to use this functionality.
23///
24/// See the [`Dummy`] trait impl for usage examples.
25///
26/// [EIP-55]: https://eips.ethereum.org/EIPS/eip-55
27/// [`Display`]: #impl-Display-for-AllocationId
28/// [`LowerHex`]: #impl-LowerHex-for-AllocationId
29/// [`UpperHex`]: #impl-UpperHex-for-AllocationId
30/// [`Dummy`]: #impl-Dummy<Faker>-for-AllocationId
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct AllocationId(Address);
33
34impl AllocationId {
35    /// Create a new [`AllocationId`].
36    pub const fn new(address: Address) -> Self {
37        AllocationId(address)
38    }
39
40    /// Return the internal representation.
41    pub fn into_inner(self) -> Address {
42        self.0
43    }
44}
45
46impl std::fmt::Display for AllocationId {
47    /// Formats the `AllocationId` using its [EIP-55](https://eips.ethereum.org/EIPS/eip-55)
48    /// checksum representation.
49    ///
50    /// See [`LowerHex`] (and [`UpperHex`]) for formatting the `AllocationId` as a hexadecimal
51    /// string.
52    ///
53    /// [`LowerHex`]: struct.AllocationId.html#impl-LowerHex-for-AllocationId
54    /// [`UpperHex`]: struct.AllocationId.html#impl-UpperHex-for-AllocationId
55    ///
56    /// ```rust
57    /// # use thegraph_core::{allocation_id, AllocationId};
58    /// const ID: AllocationId = allocation_id!("0002c67268fb8c8917f36f865a0cbdf5292fa68d");
59    ///
60    /// // Note the uppercase and lowercase hex characters in the checksum
61    /// assert_eq!(format!("{}", ID), "0x0002c67268FB8C8917F36F865a0CbdF5292FA68d");
62    /// ```
63    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
64        std::fmt::Display::fmt(&self.0, f)
65    }
66}
67
68impl std::fmt::Debug for AllocationId {
69    /// Formats the `AllocationId` using its raw lower-case hexadecimal representation.
70    ///
71    /// It is advised to use the [`LowerHex`] (and [`UpperHex`]) format trait implementation over
72    /// the [`Debug`](std::fmt::Debug) implementation to format the `AllocationId` as a lower-case
73    /// hexadecimal string.
74    ///
75    /// This implementation matches `alloy_primitives::Address`'s `Debug` implementation.
76    ///
77    /// [`LowerHex`]: struct.AllocationId.html#impl-LowerHex-for-AllocationId
78    /// [`UpperHex`]: struct.AllocationId.html#impl-UpperHex-for-AllocationId
79    ///
80    /// ```rust
81    /// # use thegraph_core::{allocation_id, AllocationId};
82    /// const ID: AllocationId = allocation_id!("0002c67268fb8c8917f36f865a0cbdf5292fa68d");
83    ///
84    /// assert_eq!(format!("{:?}", ID), "0x0002c67268fb8c8917f36f865a0cbdf5292fa68d");
85    /// ```
86    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
87        std::fmt::Debug::fmt(&self.0, f)
88    }
89}
90
91impl std::fmt::LowerHex for AllocationId {
92    /// Lowercase hex representation of the `AllocationId`.
93    ///
94    /// Note that the alternate flag, `#`, adds a `0x` in front of the output.
95    ///
96    /// ```rust
97    /// # use thegraph_core::{allocation_id, AllocationId};
98    /// const ID: AllocationId = allocation_id!("0002c67268fb8c8917f36f865a0cbdf5292fa68d");
99    ///
100    /// // Lower hex
101    /// assert_eq!(format!("{:x}", ID), "0002c67268fb8c8917f36f865a0cbdf5292fa68d");
102    ///
103    /// // Lower hex with alternate flag
104    /// assert_eq!(format!("{:#x}", ID), "0x0002c67268fb8c8917f36f865a0cbdf5292fa68d");
105    /// ```
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        std::fmt::LowerHex::fmt(&self.0, f)
108    }
109}
110
111impl std::fmt::UpperHex for AllocationId {
112    /// Uppercase hex representation of the `AllocationId`.
113    ///
114    /// Note that the alternate flag, `#`, adds a `0x` in front of the output.
115    ///
116    /// ```rust
117    /// # use thegraph_core::{allocation_id, AllocationId};
118    /// const ID: AllocationId = allocation_id!("0002c67268fb8c8917f36f865a0cbdf5292fa68d");
119    ///
120    /// // Upper hex
121    /// assert_eq!(format!("{:X}", ID), "0002C67268FB8C8917F36F865A0CBDF5292FA68D");
122    ///
123    /// // Upper hex with alternate flag
124    /// assert_eq!(format!("{:#X}", ID), "0x0002C67268FB8C8917F36F865A0CBDF5292FA68D");
125    /// ```
126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127        std::fmt::UpperHex::fmt(&self.0, f)
128    }
129}
130
131impl From<Address> for AllocationId {
132    fn from(address: Address) -> Self {
133        AllocationId(address)
134    }
135}
136
137impl std::str::FromStr for AllocationId {
138    type Err = <Address as std::str::FromStr>::Err;
139
140    fn from_str(s: &str) -> Result<Self, Self::Err> {
141        let address = std::str::FromStr::from_str(s)?;
142        Ok(AllocationId(address))
143    }
144}
145
146impl PartialEq<Address> for AllocationId {
147    fn eq(&self, other: &Address) -> bool {
148        self.0.eq(other)
149    }
150}
151
152impl AsRef<Address> for AllocationId {
153    fn as_ref(&self) -> &Address {
154        &self.0
155    }
156}
157
158impl std::ops::Deref for AllocationId {
159    type Target = Address;
160
161    fn deref(&self) -> &Self::Target {
162        &self.0
163    }
164}
165
166#[cfg(feature = "serde")]
167impl<'de> serde::Deserialize<'de> for AllocationId {
168    fn deserialize<D>(deserializer: D) -> Result<AllocationId, D::Error>
169    where
170        D: serde::Deserializer<'de>,
171    {
172        let address = Address::deserialize(deserializer)?;
173        Ok(AllocationId(address))
174    }
175}
176
177#[cfg(feature = "serde")]
178impl serde::Serialize for AllocationId {
179    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
180    where
181        S: serde::Serializer,
182    {
183        self.0.serialize(serializer)
184    }
185}
186
187#[cfg(feature = "fake")]
188/// To use the [`fake`] crate to generate random [`AllocationId`] values, **the `fake` feature must
189/// be enabled.**
190///
191/// ```rust
192/// # use thegraph_core::AllocationId;
193/// # use fake::Fake;
194/// let allocation_id = fake::Faker.fake::<AllocationId>();
195///
196/// println!("AllocationId: {:#x}", allocation_id);
197/// ```
198impl fake::Dummy<fake::Faker> for AllocationId {
199    fn dummy_with_rng<R: fake::Rng + ?Sized>(_: &fake::Faker, rng: &mut R) -> Self {
200        use crate::fake_impl::alloy::Alloy;
201        Self(Address::dummy_with_rng(&Alloy, rng))
202    }
203}
204
205/// Converts a sequence of string literals containing hex-encoded data into a new [`AllocationId`]
206/// at compile time.
207///
208/// To create an `AllocationId` from a string literal (no `0x` prefix) at compile time:
209///
210/// ```rust
211/// use thegraph_core::{allocation_id, AllocationId};
212///
213/// const ALLOCATION_ID: AllocationId = allocation_id!("0002c67268fb8c8917f36f865a0cbdf5292fa68d");
214/// ```
215///
216/// If no argument is provided, the macro will create an `AllocationId` with the zero address:
217///
218/// ```rust
219/// use thegraph_core::{
220///     alloy::primitives::Address,
221///     allocation_id, AllocationId
222/// };
223///
224/// const ALLOCATION_ID: AllocationId = allocation_id!();
225///
226/// assert_eq!(ALLOCATION_ID, Address::ZERO);
227/// ```
228#[macro_export]
229#[doc(hidden)]
230macro_rules! __allocation_id {
231    () => {
232        $crate::AllocationId::new($crate::alloy::primitives::Address::ZERO)
233    };
234    ($value:tt) => {
235        $crate::AllocationId::new($crate::alloy::primitives::address!($value))
236    };
237}