rue_types/types/
atom.rs

1use std::{borrow::Cow, fmt};
2
3use clvmr::Allocator;
4use derive_more::Display;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display)]
7pub enum AtomSemantic {
8    #[display("Atom")]
9    Any,
10
11    #[display("Bytes")]
12    Bytes,
13
14    #[display("Int")]
15    Int,
16
17    #[display("PublicKey")]
18    PublicKey,
19
20    #[display("Bool")]
21    Bool,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub enum AtomRestriction {
26    Value(Cow<'static, [u8]>),
27    Length(usize),
28}
29
30#[derive(Debug, Clone)]
31pub struct Atom {
32    pub semantic: AtomSemantic,
33    pub restriction: Option<AtomRestriction>,
34}
35
36impl Atom {
37    pub const ANY: Self = Self::new(AtomSemantic::Any, None);
38    pub const NIL: Self = Self::new(
39        AtomSemantic::Bytes,
40        Some(AtomRestriction::Value(Cow::Borrowed(&[]))),
41    );
42    pub const FALSE: Self = Self::new(
43        AtomSemantic::Bool,
44        Some(AtomRestriction::Value(Cow::Borrowed(&[]))),
45    );
46    pub const TRUE: Self = Self::new(
47        AtomSemantic::Bool,
48        Some(AtomRestriction::Value(Cow::Borrowed(&[1]))),
49    );
50    pub const BYTES: Self = Self::new(AtomSemantic::Bytes, None);
51    pub const BYTES_32: Self = Self::new(AtomSemantic::Bytes, Some(AtomRestriction::Length(32)));
52    pub const PUBLIC_KEY: Self =
53        Self::new(AtomSemantic::PublicKey, Some(AtomRestriction::Length(48)));
54    pub const INT: Self = Self::new(AtomSemantic::Int, None);
55
56    pub const fn new(semantic: AtomSemantic, restriction: Option<AtomRestriction>) -> Self {
57        Self {
58            semantic,
59            restriction,
60        }
61    }
62}
63
64impl fmt::Display for Atom {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        let name = format!("{}", self.semantic);
67
68        let qualifier = match &self.restriction {
69            None => None,
70            Some(AtomRestriction::Length(length)) => {
71                if self.semantic == AtomSemantic::PublicKey && *length == 48 {
72                    None
73                } else {
74                    Some(format!("{length}"))
75                }
76            }
77            Some(AtomRestriction::Value(value)) => match self.semantic {
78                AtomSemantic::Any | AtomSemantic::Bytes | AtomSemantic::PublicKey => {
79                    if value.is_empty() {
80                        return write!(f, "nil");
81                    }
82
83                    return write!(f, "0x{}", hex::encode(value));
84                }
85                AtomSemantic::Int => {
86                    let mut allocator = Allocator::new();
87                    let ptr = allocator.new_atom(value).unwrap();
88                    return write!(f, "{}", allocator.number(ptr));
89                }
90                AtomSemantic::Bool => {
91                    if value.is_empty() {
92                        return write!(f, "false");
93                    } else if value.as_ref() == [1] {
94                        return write!(f, "true");
95                    }
96
97                    return write!(f, "0x{}", hex::encode(value));
98                }
99            },
100        };
101
102        if let Some(qualifier) = qualifier {
103            write!(f, "{name}{qualifier}")
104        } else {
105            write!(f, "{name}")
106        }
107    }
108}