zvt_builder/
lib.rs

1use encoding::Encoding;
2use log::debug;
3use thiserror::Error;
4
5pub mod encoding;
6pub mod length;
7
8#[derive(Debug, PartialEq, Error)]
9pub enum ZVTError {
10    #[error("Incomplete data")]
11    IncompleteData,
12
13    #[error("The following tags are required, but were missing: {0:?}")]
14    MissingRequiredTags(Vec<Tag>),
15
16    #[error("Not implemented")]
17    NonImplemented,
18
19    #[error("Unexpected tag: {0:?}")]
20    WrongTag(Tag),
21
22    #[error("Duplicate tag: {0:?}")]
23    DuplicateTag(Tag),
24
25    #[error("Received an abort {0}")]
26    Aborted(u8),
27}
28
29pub type ZVTResult<T> = ::std::result::Result<T, ZVTError>;
30
31/// The tag of a field.
32///
33/// The tag is equivalent to the bmp-number in the Zvt documentation.
34#[derive(Debug, PartialEq, Clone)]
35pub struct Tag(pub u16);
36
37/// Trait for commands.
38///
39/// The trait encodes the control fields of an Adpu package.
40pub trait ZvtCommand {
41    const CLASS: u8;
42    const INSTR: u8;
43}
44
45pub trait NotZvtCommand {}
46
47/// The implementation for serializing/deserializing a Zvt struct.
48///
49/// Trait implements the basic logic of the Zvt protocol. Every package consists
50/// of up to three fields:
51///
52/// `<BMP-NUMBER>` `<LENGTH>` `<DATA>`.
53///
54/// The BMP-NUMBER and LENGTH are optional; The DATA may be encoded in different
55/// ways.
56///
57/// # Parameters:
58///
59///  * `L`: The trait [length::Length] encodes/decodes the `<LENGTH>` field.
60///         Use [length::Empty] to omit the length.
61///  * `E`: The trait [encoding::Encoding] encodes/decodes the given data an
62///         generates the DATA field. In order to use this trait with custom
63///         types, you have to implement the [encoding::Encoding] trait for your type.
64///  * `TE`: The trait [encoding::Encoding] which encodes/decodes the [Tag]
65///         the `<BMP-NUMBER>` field.
66pub trait ZvtSerializerImpl<
67    L: length::Length = length::Empty,
68    E: encoding::Encoding<Self> = encoding::Default,
69    TE: encoding::Encoding<Tag> = encoding::Default,
70> where
71    Self: Sized,
72{
73    fn serialize_tagged(&self, tag: Option<Tag>) -> Vec<u8> {
74        let mut output = Vec::new();
75        if let Some(tag) = tag {
76            output = TE::encode(&tag);
77        }
78        let mut payload = E::encode(self);
79        let mut length = L::serialize(payload.len());
80        output.append(&mut length);
81        output.append(&mut payload);
82        output
83    }
84
85    fn deserialize_tagged(mut bytes: &[u8], tag: Option<Tag>) -> ZVTResult<(Self, &[u8])> {
86        if let Some(desired_tag) = tag {
87            let actual_tag;
88            (actual_tag, bytes) = TE::decode(bytes)?;
89            if actual_tag != desired_tag {
90                return Err(ZVTError::WrongTag(actual_tag));
91            }
92            debug!(
93                "found tag: 0x{:x}, remaining bytes after tag: {:x?}",
94                actual_tag.0, bytes
95            );
96        }
97        let (length, payload) = L::deserialize(bytes)?;
98        if length > payload.len() {
99            return Err(ZVTError::IncompleteData);
100        }
101        let (data, remainder) = E::decode(&payload[..length])?;
102
103        Ok((data, &payload[length - remainder.len()..]))
104    }
105}
106
107/// The implementation for serializing/deserializing a optional Zvt fields.
108///
109/// Optional fields don't generate anything if the data field is [None]. They
110/// generate the same output if the data field is provided.
111///
112/// When deserializing optional fields behave differently depending if a [Tag]
113/// is provided or not. If the [Tag] is [None] the deserialization always
114/// succeeds returning [None] as the result. If the [Tag] is provided, then the
115/// serialization error is propagated.
116impl<T, L: length::Length, E: encoding::Encoding<T>, TE: encoding::Encoding<Tag>>
117    ZvtSerializerImpl<L, E, TE> for Option<T>
118where
119    T: ZvtSerializerImpl<L, E, TE>,
120{
121    fn serialize_tagged(&self, tag: Option<Tag>) -> Vec<u8> {
122        // If the data is missing, the tag is also missing.
123        match self {
124            None => Vec::new(),
125            Some(ref data) => <T as ZvtSerializerImpl<L, E, TE>>::serialize_tagged(data, tag),
126        }
127    }
128
129    fn deserialize_tagged(bytes: &[u8], tag: Option<Tag>) -> ZVTResult<(Self, &[u8])> {
130        // If we're deserializing and the tag is a match but the data is still
131        // missing, this is an error.
132        match &tag {
133            Some(_) => match <T as ZvtSerializerImpl<L, E, TE>>::deserialize_tagged(bytes, tag) {
134                Err(err) => Err(err),
135                Ok(data) => Ok((Some(data.0), data.1)),
136            },
137            None => match <T as ZvtSerializerImpl<L, E, TE>>::deserialize_tagged(bytes, None) {
138                Err(_) => Ok((None, bytes)),
139                Ok(data) => Ok((Some(data.0), data.1)),
140            },
141        }
142    }
143}
144
145/// The implementation for serializing/deserializing [Vec]
146///
147/// The Zvt protocol does not define a consistent handling of vectors. However,
148/// in most cases it assumes that every element is tagged and not the vector
149/// itself. Therefore we provide a default serialization/deserialization which
150/// does exactly this.
151///
152/// The serialization will return an empty vector for an empty input. Otherwise
153/// it will tag every element independently and collect the results.
154///
155/// The deserialization will deserialize the input until a failure occurs -
156/// this indicates that there are no more elements in the vector - and return
157/// the results. This means that all elements in the vector must be placed
158/// consecutively to each other.
159impl<T, L: length::Length, E: encoding::Encoding<T>, TE: encoding::Encoding<Tag>>
160    ZvtSerializerImpl<L, E, TE> for Vec<T>
161where
162    T: ZvtSerializerImpl<L, E, TE>,
163{
164    fn serialize_tagged(&self, tag: Option<Tag>) -> Vec<u8> {
165        self.iter()
166            .flat_map(|item| {
167                <T as ZvtSerializerImpl<L, E, TE>>::serialize_tagged(item, tag.clone())
168            })
169            .collect()
170    }
171
172    fn deserialize_tagged(mut bytes: &[u8], tag: Option<Tag>) -> ZVTResult<(Self, &[u8])> {
173        let mut items = Vec::new();
174
175        while let Ok((item, remainder)) =
176            <T as ZvtSerializerImpl<L, E, TE>>::deserialize_tagged(bytes, tag.clone())
177        {
178            items.push(item);
179            bytes = remainder;
180        }
181
182        Ok((items, bytes))
183    }
184}
185
186/// Serializes/Deserializes an Zvt packet.
187///
188/// The trait wraps the ZvtSerializerImpl and allows a simple serialization/
189/// deserialization.
190pub trait ZvtSerializer: ZvtSerializerImpl
191where
192    Self: Sized,
193    encoding::Default: encoding::Encoding<Self>,
194{
195    fn zvt_serialize(&self) -> Vec<u8> {
196        <Self as ZvtSerializerImpl>::serialize_tagged(self, None)
197    }
198
199    fn zvt_deserialize(bytes: &[u8]) -> ZVTResult<(Self, &[u8])> {
200        <Self as ZvtSerializerImpl>::deserialize_tagged(bytes, None)
201    }
202}
203
204/// Serializes/Deserializes an Adpu packet.
205impl<T> ZvtSerializer for T
206where
207    Self: ZvtCommand
208        + ZvtSerializerImpl<length::Adpu, encoding::Default, encoding::BigEndian>
209        + ZvtSerializerImpl,
210    encoding::Default: encoding::Encoding<Self>,
211{
212    fn zvt_serialize(&self) -> Vec<u8> {
213        // Find a more elegant way to express this.
214        let tag: Tag = encoding::BigEndian::decode(&[Self::CLASS, Self::INSTR])
215            .unwrap()
216            .0;
217        <Self as ZvtSerializerImpl<length::Adpu, encoding::Default, encoding::BigEndian>>::serialize_tagged(self, Some(tag))
218    }
219
220    fn zvt_deserialize(bytes: &[u8]) -> ZVTResult<(Self, &[u8])> {
221        let tag: Tag = encoding::BigEndian::decode(&[Self::CLASS, Self::INSTR])
222            .unwrap()
223            .0;
224        <Self as ZvtSerializerImpl<length::Adpu, encoding::Default, encoding::BigEndian>>::deserialize_tagged(bytes, Some(tag))
225    }
226}
227
228pub trait ZvtParser
229where
230    Self: Sized,
231{
232    fn zvt_parse(bytes: &[u8]) -> ZVTResult<Self>;
233}