codama_nodes/value_nodes/
number_value_node.rs

1use codama_nodes_derive::node;
2use derive_more::derive::From;
3use serde::{Deserialize, Serialize};
4use serde_json::Number as JsonNumber;
5
6#[node]
7pub struct NumberValueNode {
8    // Data.
9    pub number: Number,
10}
11
12impl From<NumberValueNode> for crate::Node {
13    fn from(val: NumberValueNode) -> Self {
14        crate::Node::Value(val.into())
15    }
16}
17
18impl NumberValueNode {
19    pub fn new<T>(number: T) -> Self
20    where
21        T: Into<Number>,
22    {
23        Self {
24            number: number.into(),
25        }
26    }
27}
28
29#[derive(From, Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
30#[serde(from = "JsonNumber", into = "JsonNumber")]
31pub enum Number {
32    UnsignedInteger(u64),
33    SignedInteger(i64),
34    Float(f64),
35}
36
37impl From<u8> for Number {
38    fn from(number: u8) -> Self {
39        Number::UnsignedInteger(number as u64)
40    }
41}
42
43impl From<u16> for Number {
44    fn from(number: u16) -> Self {
45        Number::UnsignedInteger(number as u64)
46    }
47}
48
49impl From<u32> for Number {
50    fn from(number: u32) -> Self {
51        Number::UnsignedInteger(number as u64)
52    }
53}
54
55impl From<i8> for Number {
56    fn from(number: i8) -> Self {
57        Number::SignedInteger(number as i64)
58    }
59}
60
61impl From<i16> for Number {
62    fn from(number: i16) -> Self {
63        Number::SignedInteger(number as i64)
64    }
65}
66
67impl From<i32> for Number {
68    fn from(number: i32) -> Self {
69        Number::SignedInteger(number as i64)
70    }
71}
72
73impl From<f32> for Number {
74    fn from(number: f32) -> Self {
75        Number::Float(number as f64)
76    }
77}
78
79impl From<JsonNumber> for Number {
80    fn from(number: JsonNumber) -> Self {
81        if number.is_u64() {
82            Number::UnsignedInteger(number.as_u64().unwrap())
83        } else if number.is_i64() {
84            Number::SignedInteger(number.as_i64().unwrap())
85        } else {
86            Number::Float(number.as_f64().unwrap())
87        }
88    }
89}
90
91impl From<Number> for JsonNumber {
92    fn from(val: Number) -> Self {
93        match val {
94            Number::UnsignedInteger(number) => JsonNumber::from(number),
95            Number::SignedInteger(number) => JsonNumber::from(number),
96            Number::Float(number) => JsonNumber::from_f64(number).unwrap(),
97        }
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    fn new() {
107        assert_eq!(NumberValueNode::new(42).number, Number::SignedInteger(42));
108        assert_eq!(
109            NumberValueNode::new(42u8).number,
110            Number::UnsignedInteger(42)
111        );
112        assert_eq!(
113            NumberValueNode::new(42u16).number,
114            Number::UnsignedInteger(42)
115        );
116        assert_eq!(
117            NumberValueNode::new(42u32).number,
118            Number::UnsignedInteger(42)
119        );
120        assert_eq!(
121            NumberValueNode::new(42u64).number,
122            Number::UnsignedInteger(42)
123        );
124        assert_eq!(
125            NumberValueNode::new(-42i8).number,
126            Number::SignedInteger(-42)
127        );
128        assert_eq!(
129            NumberValueNode::new(-42i16).number,
130            Number::SignedInteger(-42)
131        );
132        assert_eq!(
133            NumberValueNode::new(-42i32).number,
134            Number::SignedInteger(-42)
135        );
136        assert_eq!(
137            NumberValueNode::new(-42i64).number,
138            Number::SignedInteger(-42)
139        );
140        assert_eq!(NumberValueNode::new(1.5).number, Number::Float(1.5));
141        assert_eq!(NumberValueNode::new(1.5f32).number, Number::Float(1.5));
142        assert_eq!(NumberValueNode::new(1.5f64).number, Number::Float(1.5));
143    }
144
145    #[test]
146    fn to_json() {
147        let node = NumberValueNode::new(42u16);
148        let json = serde_json::to_string(&node).unwrap();
149        assert_eq!(json, r#"{"kind":"numberValueNode","number":42}"#);
150    }
151
152    #[test]
153    fn from_json() {
154        let node: NumberValueNode =
155            serde_json::from_str(r#"{"kind":"numberValueNode","number":42}"#).unwrap();
156        assert_eq!(node.number, Number::UnsignedInteger(42));
157    }
158}