codama_nodes/type_nodes/
size_prefix_type_node.rs

1use crate::{
2    NestedTypeNode, NestedTypeNodeTrait, NumberTypeNode, TypeNode, TypeNodeTrait,
3    TypeNodeUnionTrait,
4};
5use codama_errors::{CodamaError, CodamaResult};
6use codama_nodes_derive::nestable_type_node;
7
8#[nestable_type_node]
9pub struct SizePrefixTypeNode<T: TypeNodeUnionTrait> {
10    // Children.
11    #[serde(bound = "T: TypeNodeUnionTrait")]
12    pub r#type: Box<T>,
13    pub prefix: Box<NestedTypeNode<NumberTypeNode>>,
14}
15
16impl From<SizePrefixTypeNode<crate::TypeNode>> for crate::Node {
17    fn from(val: SizePrefixTypeNode<crate::TypeNode>) -> Self {
18        crate::Node::Type(val.into())
19    }
20}
21
22impl<T: TypeNodeTrait> From<SizePrefixTypeNode<NestedTypeNode<T>>>
23    for SizePrefixTypeNode<TypeNode>
24{
25    fn from(node: SizePrefixTypeNode<NestedTypeNode<T>>) -> Self {
26        SizePrefixTypeNode {
27            r#type: Box::new(TypeNode::from(*node.r#type)),
28            prefix: node.prefix,
29        }
30    }
31}
32
33impl<T: TypeNodeTrait> TryFrom<SizePrefixTypeNode<TypeNode>>
34    for SizePrefixTypeNode<NestedTypeNode<T>>
35{
36    type Error = CodamaError;
37    fn try_from(node: SizePrefixTypeNode<TypeNode>) -> CodamaResult<Self> {
38        Ok(SizePrefixTypeNode {
39            r#type: Box::new(NestedTypeNode::try_from(*node.r#type)?),
40            prefix: node.prefix,
41        })
42    }
43}
44
45impl<T: TypeNodeUnionTrait> SizePrefixTypeNode<T> {
46    pub fn new<U, V>(r#type: U, prefix: V) -> Self
47    where
48        U: Into<T>,
49        V: Into<NestedTypeNode<NumberTypeNode>>,
50    {
51        Self {
52            r#type: Box::new(r#type.into()),
53            prefix: Box::new(prefix.into()),
54        }
55    }
56}
57
58impl<T: TypeNodeTrait> NestedTypeNodeTrait<T> for SizePrefixTypeNode<NestedTypeNode<T>> {
59    type Mapped<U: TypeNodeTrait> = SizePrefixTypeNode<NestedTypeNode<U>>;
60
61    fn get_nested_type_node(&self) -> &T {
62        self.r#type.get_nested_type_node()
63    }
64
65    fn try_map_nested_type_node<U: TypeNodeTrait, F: FnOnce(T) -> CodamaResult<U>>(
66        self,
67        f: F,
68    ) -> CodamaResult<Self::Mapped<U>> {
69        Ok(SizePrefixTypeNode {
70            r#type: Box::new(self.r#type.try_map_nested_type_node(f)?),
71            prefix: self.prefix,
72        })
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use crate::{NestedTypeNode, StringTypeNode, TypeNode, U32};
79
80    use super::*;
81
82    #[test]
83    fn new_type_node() {
84        let node =
85            SizePrefixTypeNode::<TypeNode>::new(StringTypeNode::utf8(), NumberTypeNode::le(U32));
86        assert_eq!(*node.r#type, TypeNode::String(StringTypeNode::utf8()));
87        assert_eq!(*node.prefix, NestedTypeNode::Value(NumberTypeNode::le(U32)));
88    }
89
90    #[test]
91    fn new_nested_type_node() {
92        let node = SizePrefixTypeNode::<NestedTypeNode<StringTypeNode>>::new(
93            StringTypeNode::utf8(),
94            NumberTypeNode::le(U32),
95        );
96        assert_eq!(*node.r#type, NestedTypeNode::Value(StringTypeNode::utf8()));
97        assert_eq!(node.get_nested_type_node(), &StringTypeNode::utf8());
98        assert_eq!(*node.prefix, NestedTypeNode::Value(NumberTypeNode::le(U32)));
99    }
100
101    #[test]
102    fn to_json() {
103        let node =
104            SizePrefixTypeNode::<TypeNode>::new(StringTypeNode::utf8(), NumberTypeNode::le(U32));
105        let json = serde_json::to_string(&node).unwrap();
106        assert_eq!(
107            json,
108            r#"{"kind":"sizePrefixTypeNode","type":{"kind":"stringTypeNode","encoding":"utf8"},"prefix":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#
109        );
110    }
111
112    #[test]
113    fn from_json() {
114        let json = r#"{"kind":"sizePrefixTypeNode","type":{"kind":"stringTypeNode","encoding":"utf8"},"prefix":{"kind":"numberTypeNode","format":"u32","endian":"le"}}"#;
115        let node: SizePrefixTypeNode<TypeNode> = serde_json::from_str(json).unwrap();
116        assert_eq!(
117            node,
118            SizePrefixTypeNode::<TypeNode>::new(StringTypeNode::utf8(), NumberTypeNode::le(U32))
119        );
120    }
121}