codama_nodes/value_nodes/
number_value_node.rs1use 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 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}