codama_nodes/type_nodes/
size_prefix_type_node.rs1use 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 #[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}