1use crate::enums::AnnotationKind;
2use crate::error::TypeError;
3use crate::fields::{
4 decode_bytes_value, decode_field_header, decode_varint_value, encode_bytes_field,
5 encode_varint_field, skip_field,
6};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct AnnotationBlock {
32 pub target_block_id: u32,
33 pub kind: AnnotationKind,
34 pub value: Vec<u8>,
35}
36
37impl AnnotationBlock {
38 pub fn encode_body(&self) -> Vec<u8> {
40 let mut buf = Vec::new();
41 encode_varint_field(&mut buf, 1, u64::from(self.target_block_id));
42 encode_varint_field(&mut buf, 2, u64::from(self.kind.to_wire_byte()));
43 encode_bytes_field(&mut buf, 3, &self.value);
44 buf
45 }
46
47 pub fn decode_body(mut buf: &[u8]) -> Result<Self, TypeError> {
49 let mut target_block_id: Option<u32> = None;
50 let mut kind: Option<AnnotationKind> = None;
51 let mut value: Option<Vec<u8>> = None;
52
53 while !buf.is_empty() {
54 let (header, n) = decode_field_header(buf)?;
55 buf = &buf[n..];
56
57 match header.field_id {
58 1 => {
59 let (v, n) = decode_varint_value(buf)?;
60 buf = &buf[n..];
61 target_block_id = Some(v as u32);
62 }
63 2 => {
64 let (v, n) = decode_varint_value(buf)?;
65 buf = &buf[n..];
66 kind = Some(AnnotationKind::from_wire_byte(v as u8)?);
67 }
68 3 => {
69 let (data, n) = decode_bytes_value(buf)?;
70 buf = &buf[n..];
71 value = Some(data.to_vec());
72 }
73 _ => {
74 let n = skip_field(buf, header.wire_type)?;
75 buf = &buf[n..];
76 }
77 }
78 }
79
80 Ok(Self {
81 target_block_id: target_block_id.ok_or(TypeError::MissingRequiredField {
82 field: "target_block_id",
83 })?,
84 kind: kind.ok_or(TypeError::MissingRequiredField { field: "kind" })?,
85 value: value.ok_or(TypeError::MissingRequiredField { field: "value" })?,
86 })
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn roundtrip_priority_annotation() {
96 let block = AnnotationBlock {
97 target_block_id: 0,
98 kind: AnnotationKind::Priority,
99 value: vec![0x01], };
101 let body = block.encode_body();
102 let decoded = AnnotationBlock::decode_body(&body).unwrap();
103 assert_eq!(decoded, block);
104 }
105
106 #[test]
107 fn roundtrip_tag_annotation() {
108 let block = AnnotationBlock {
109 target_block_id: 5,
110 kind: AnnotationKind::Tag,
111 value: b"security-critical".to_vec(),
112 };
113 let body = block.encode_body();
114 let decoded = AnnotationBlock::decode_body(&body).unwrap();
115 assert_eq!(decoded, block);
116 }
117
118 #[test]
119 fn roundtrip_summary_annotation() {
120 let block = AnnotationBlock {
121 target_block_id: 2,
122 kind: AnnotationKind::Summary,
123 value: b"Authentication middleware for JWT tokens".to_vec(),
124 };
125 let body = block.encode_body();
126 let decoded = AnnotationBlock::decode_body(&body).unwrap();
127 assert_eq!(decoded, block);
128 }
129}