1use avro_rs::{from_avro_datum, to_avro_datum, Schema};
2use bytes::Bytes;
3use lazy_static::lazy_static;
4use serde::{Deserialize, Serialize};
5
6use crate::error::BundlrError;
7
8#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
9pub struct Tag {
10 pub name: String,
11 pub value: String,
12}
13
14impl Tag {
15 pub fn new(name: &str, value: &str) -> Self {
16 Tag {
17 name: name.to_string(),
18 value: value.to_string(),
19 }
20 }
21}
22
23const SCHEMA_STR: &str = r#"{
24 "type": "array",
25 "items": {
26 "type": "record",
27 "name": "Tag",
28 "fields": [
29 { "name": "name", "type": "string" },
30 { "name": "value", "type": "string" }
31 ]
32 }
33}"#;
34
35lazy_static! {
36 pub static ref TAGS_SCHEMA: Schema = Schema::parse_str(SCHEMA_STR).unwrap();
37}
38
39pub trait AvroEncode {
43 fn encode(&self) -> Result<Bytes, BundlrError>;
44}
45
46pub trait AvroDecode {
47 fn decode(&mut self) -> Result<Vec<Tag>, BundlrError>;
48}
49
50impl AvroEncode for Vec<Tag> {
51 fn encode(&self) -> Result<Bytes, BundlrError> {
52 let v = avro_rs::to_value(self)?;
53 to_avro_datum(&TAGS_SCHEMA, v)
54 .map(|v| v.into())
55 .map_err(|_| BundlrError::NoBytesLeft)
56 }
57}
58
59impl AvroDecode for &mut [u8] {
60 fn decode(&mut self) -> Result<Vec<Tag>, BundlrError> {
61 let x = self.to_vec();
62 let v = from_avro_datum(&TAGS_SCHEMA, &mut x.as_slice(), Some(&TAGS_SCHEMA))
63 .map_err(|_| BundlrError::InvalidTagEncoding)?;
64 avro_rs::from_value(&v).map_err(|_| BundlrError::InvalidTagEncoding)
65 }
66}
67
68impl From<avro_rs::DeError> for BundlrError {
69 fn from(_: avro_rs::DeError) -> Self {
70 BundlrError::InvalidTagEncoding
71 }
72}
73
74#[cfg(test)]
75mod tests {
76
77 use crate::tags::{AvroDecode, AvroEncode};
78
79 use super::Tag;
80
81 #[test]
82 fn test_bytes() {
83 let b = &[2u8, 8, 110, 97, 109, 101, 10, 118, 97, 108, 117, 101, 0];
84
85 let mut sli = &mut b.clone()[..];
86
87 dbg!((sli).decode()).unwrap();
88 }
89
90 #[test]
91 fn test_tags() {
92 let tags = vec![Tag {
93 name: "name".to_string(),
94 value: "value".to_string(),
95 }];
96
97 dbg!(tags.encode().unwrap().to_vec());
98 }
99}