willow25/entry/
subspace_id.rs

1use core::fmt;
2
3#[cfg(feature = "dev")]
4use arbitrary::Arbitrary;
5
6use order_theory::{
7    GreatestElement, LeastElement, LowerSemilattice, PredecessorExceptForLeast,
8    SuccessorExceptForGreatest, TryPredecessor, TrySuccessor, UpperSemilattice,
9};
10
11use super::HexFormatter;
12
13/// The width of a [`SubspaceId`] in bytes: 32.
14///
15/// [Specification](https://macromania--macromania.deno.dev/specs/willow25/index.html#willow25_data_model)
16pub const SUBSPACE_ID_WIDTH: usize = 32;
17
18wrapper! {
19    /// The type of [SubspaceIds](https://willowprotocol.org/specs/data-model/index.html#SubspaceId) used by [Willow’25](https://macromania--macromania.deno.dev/specs/willow25/index.html#willow25_data_model).
20    ///
21    /// This is a thin wrapper around `[u8; SUBSPACE_ID_WIDTH]`.
22    ///
23    /// ```
24    /// use willow25::prelude::*;
25    ///
26    /// let subspace_id = SubspaceId::from([17; SUBSPACE_ID_WIDTH]);
27    /// assert_eq!(subspace_id.as_bytes(), &[17; 32]);
28    /// ```
29    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
30    #[cfg_attr(feature = "dev", derive(Arbitrary))]
31    SubspaceId; [u8; SUBSPACE_ID_WIDTH]
32}
33
34impl fmt::Debug for SubspaceId {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        f.debug_tuple("SubspaceId")
37            .field(&HexFormatter(self.0))
38            .finish()
39    }
40}
41
42impl SubspaceId {
43    /// Returns the raw bytes that make up this subspace id.
44    ///
45    /// This type deliberately does not provide implementations of [`AsRef`], [`Deref`](core::ops::Deref) or [`Borrow`](core::borrow::Borrow), to make it more difficult to leak information accidentally. Apologies if this is inconvenient.
46    pub fn as_bytes(&self) -> &[u8; SUBSPACE_ID_WIDTH] {
47        &self.0
48    }
49}
50
51impl LeastElement for SubspaceId {
52    fn least() -> Self {
53        <[u8; SUBSPACE_ID_WIDTH]>::least().into()
54    }
55}
56
57impl GreatestElement for SubspaceId {
58    fn greatest() -> Self {
59        <[u8; SUBSPACE_ID_WIDTH]>::greatest().into()
60    }
61}
62
63impl LowerSemilattice for SubspaceId {
64    fn greatest_lower_bound(&self, other: &Self) -> Self {
65        self.0.greatest_lower_bound(other.as_bytes()).into()
66    }
67}
68
69impl UpperSemilattice for SubspaceId {
70    fn least_upper_bound(&self, other: &Self) -> Self {
71        self.0.least_upper_bound(other.as_bytes()).into()
72    }
73}
74
75impl TryPredecessor for SubspaceId {
76    fn try_predecessor(&self) -> Option<Self> {
77        self.0.try_predecessor().map(Self)
78    }
79}
80
81impl TrySuccessor for SubspaceId {
82    fn try_successor(&self) -> Option<Self> {
83        self.0.try_successor().map(Self)
84    }
85}
86
87impl PredecessorExceptForLeast for SubspaceId {}
88
89impl SuccessorExceptForGreatest for SubspaceId {}