codama_nodes/type_nodes/
number_type_node.rs

1use codama_errors::{CodamaError, CodamaResult};
2use codama_nodes_derive::type_node;
3use serde::{Deserialize, Serialize};
4
5pub use NumberFormat::*;
6
7#[type_node]
8pub struct NumberTypeNode {
9    // Data.
10    pub format: NumberFormat,
11    pub endian: Endian,
12}
13
14impl From<NumberTypeNode> for crate::Node {
15    fn from(val: NumberTypeNode) -> Self {
16        crate::Node::Type(val.into())
17    }
18}
19
20impl NumberTypeNode {
21    pub fn new(format: NumberFormat, endian: Endian) -> Self {
22        Self { format, endian }
23    }
24
25    pub fn le(format: NumberFormat) -> Self {
26        Self::new(format, Endian::Little)
27    }
28
29    pub fn be(format: NumberFormat) -> Self {
30        Self::new(format, Endian::Big)
31    }
32}
33
34#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub enum NumberFormat {
37    U8,
38    U16,
39    U32,
40    U64,
41    U128,
42    I8,
43    I16,
44    I32,
45    I64,
46    I128,
47    F32,
48    F64,
49    ShortU16,
50}
51
52impl TryFrom<String> for NumberFormat {
53    type Error = CodamaError;
54
55    fn try_from(value: String) -> CodamaResult<Self> {
56        value.as_str().try_into()
57    }
58}
59
60impl TryFrom<&str> for NumberFormat {
61    type Error = CodamaError;
62
63    fn try_from(value: &str) -> CodamaResult<Self> {
64        match value {
65            "u8" => Ok(U8),
66            "u16" => Ok(U16),
67            "u32" => Ok(U32),
68            "u64" => Ok(U64),
69            "u128" => Ok(U128),
70            "i8" => Ok(I8),
71            "i16" => Ok(I16),
72            "i32" => Ok(I32),
73            "i64" => Ok(I64),
74            "i128" => Ok(I128),
75            "f32" => Ok(F32),
76            "f64" => Ok(F64),
77            "short_u16" => Ok(ShortU16),
78            _ => Err(CodamaError::InvalidNumberFormat(value.to_string())),
79        }
80    }
81}
82
83#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
84pub enum Endian {
85    #[serde(rename = "be")]
86    Big,
87    #[serde(rename = "le")]
88    Little,
89}
90
91impl TryFrom<String> for Endian {
92    type Error = CodamaError;
93
94    fn try_from(value: String) -> CodamaResult<Self> {
95        value.as_str().try_into()
96    }
97}
98
99impl TryFrom<&str> for Endian {
100    type Error = CodamaError;
101
102    fn try_from(value: &str) -> CodamaResult<Self> {
103        match value {
104            "be" | "big" => Ok(Endian::Big),
105            "le" | "little" => Ok(Endian::Little),
106            _ => Err(CodamaError::InvalidEndian(value.to_string())),
107        }
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn new() {
117        let node = NumberTypeNode::new(U8, Endian::Big);
118        assert_eq!(node.format, NumberFormat::U8);
119        assert_eq!(node.endian, Endian::Big);
120    }
121
122    #[test]
123    fn le() {
124        let node = NumberTypeNode::le(U32);
125        assert_eq!(node.format, NumberFormat::U32);
126        assert_eq!(node.endian, Endian::Little);
127    }
128
129    #[test]
130    fn be() {
131        let node = NumberTypeNode::be(U32);
132        assert_eq!(node.format, NumberFormat::U32);
133        assert_eq!(node.endian, Endian::Big);
134    }
135
136    #[test]
137    fn to_json() {
138        let node = NumberTypeNode::be(U8);
139        let json = serde_json::to_string(&node).unwrap();
140        assert_eq!(
141            json,
142            r#"{"kind":"numberTypeNode","format":"u8","endian":"be"}"#
143        );
144    }
145
146    #[test]
147    fn from_json() {
148        let json = r#"{"kind":"numberTypeNode","format":"u8","endian":"be"}"#;
149        let node: NumberTypeNode = serde_json::from_str(json).unwrap();
150        assert_eq!(node, NumberTypeNode::be(U8));
151    }
152}