Skip to main content

r402_core/wire/
u64_string.rs

1//! Stringified `u64` for JSON-safe integer transport.
2
3use std::fmt::{self, Display, Formatter};
4use std::str::FromStr;
5
6use serde_with::{DisplayFromStr, serde_as};
7
8/// A `u64` that serializes as a JSON string.
9///
10/// JSON integer parsing in the browser (JavaScript `Number`) is limited
11/// to 2⁵³ bits. x402 wraps `u64`-sized fields in strings to guarantee
12/// exact precision across runtimes.
13///
14/// # Examples
15///
16/// ```
17/// use r402_core::wire::U64String;
18///
19/// let value = U64String::from(42_u64);
20/// assert_eq!(value.inner(), 42);
21/// assert_eq!(serde_json::to_string(&value).unwrap(), r#""42""#);
22/// let parsed: U64String = serde_json::from_str(r#""42""#).unwrap();
23/// assert_eq!(parsed.inner(), 42);
24/// ```
25#[serde_as]
26#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
27#[repr(transparent)]
28pub struct U64String(#[serde_as(as = "DisplayFromStr")] u64);
29
30impl U64String {
31    /// Returns the wrapped `u64`.
32    #[must_use]
33    pub const fn inner(self) -> u64 {
34        self.0
35    }
36}
37
38impl Display for U64String {
39    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40        Display::fmt(&self.0, f)
41    }
42}
43
44impl FromStr for U64String {
45    type Err = <u64 as FromStr>::Err;
46    fn from_str(s: &str) -> Result<Self, Self::Err> {
47        s.parse::<u64>().map(Self)
48    }
49}
50
51impl From<u64> for U64String {
52    fn from(value: u64) -> Self {
53        Self(value)
54    }
55}
56
57impl From<U64String> for u64 {
58    fn from(value: U64String) -> Self {
59        value.0
60    }
61}