Skip to main content

kmip_ttlv/
ser.rs

1//! High-level Serde based serialization of Rust data types to TTLV bytes.
2
3use std::{io::Write, str::FromStr};
4
5use serde::{
6    ser::{self, Impossible, SerializeTupleStruct},
7    Serialize,
8};
9use types::{TtlvBoolean, TtlvEnumeration, TtlvInteger, TtlvLength, TtlvLongInteger, TtlvTextString};
10
11use crate::{
12    error::{Error, ErrorLocation, MalformedTtlvError, Result, SerdeError},
13    types::{
14        self, ByteOffset, FieldType, SerializableTtlvType, TtlvByteString, TtlvDateTime, TtlvStateMachine,
15        TtlvStateMachineMode, TtlvTag, TtlvType,
16    },
17};
18
19// --- Public interface ------------------------------------------------------------------------------------------------
20
21/// Serialize and write bytes into a new Vector.
22pub fn to_vec<T: Serialize>(value: &T) -> Result<Vec<u8>> {
23    let mut ser = TtlvSerializer::new();
24    value.serialize(&mut ser)?;
25    ser.into_vec()
26}
27
28/// Serialize and write bytes to a Writer.
29pub fn to_writer<T, W>(value: &T, mut writer: W) -> Result<()>
30where
31    T: Serialize,
32    W: Write,
33{
34    let vec = to_vec(value)?;
35    writer
36        .write_all(&vec)
37        .map_err(|err| pinpoint!(err, ErrorLocation::unknown()))?;
38    Ok(())
39}
40
41impl serde::ser::Error for Error {
42    fn custom<T: std::fmt::Display>(msg: T) -> Self {
43        pinpoint!(SerdeError::Other(msg.to_string()), ErrorLocation::unknown())
44    }
45}
46
47// --- Private implementation details ----------------------------------------------------------------------------------
48
49impl From<&mut TtlvSerializer> for ErrorLocation {
50    fn from(ser: &mut TtlvSerializer) -> Self {
51        use std::convert::TryFrom;
52        match u64::try_from(ser.dst.len()) {
53            Ok(offset) => ErrorLocation::from(ByteOffset::from(offset)),
54            Err(_) => ErrorLocation::unknown(),
55        }
56    }
57}
58
59pub struct TtlvSerializer {
60    /// The destination buffer to serialize TTLV bytes into. If we want to write to something else in future we will need
61    /// a way to be able to write to an earlier position in the output so that we can rewrite an items length value once
62    /// we know how long it is (with padding rules per TTLV type taken into account). Currently this is done simply by
63    /// indexing directly into the output buffer. An alternate approach could be to require the Seek trait to be
64    /// implemented.
65    dst: Vec<u8>,
66
67    /// A push/pop stack of indexes into the `dst` buffer to the points at which TTLV value byte lengths must be returned
68    /// to and overwritten once the length of the value being written, and any padding to ignore, is known.
69    bookmarks: Vec<usize>,
70
71    state: TtlvStateMachine,
72}
73
74impl Default for TtlvSerializer {
75    fn default() -> Self {
76        Self {
77            dst: Default::default(),
78            bookmarks: Default::default(),
79            state: TtlvStateMachine::new(TtlvStateMachineMode::Serializing),
80        }
81    }
82}
83
84impl TtlvSerializer {
85    pub fn new() -> Self {
86        Self::default()
87    }
88
89    pub fn into_vec(mut self) -> Result<Vec<u8>> {
90        self.finalize()?;
91        Ok(self.dst)
92    }
93
94    /// Write the item tag (a "three-byte binary unsigned integer, transmitted big-endian"). The caller is
95    /// responsible for ensuring that the given tag value is big-endian encoded, i.e.
96    /// assert_eq!(0x42007B_u32.to_be_bytes(), [00, 0x42, 0x00, 0x7B]); This will advance the buffer write position
97    /// by 3 bytes.
98    fn write_tag(&mut self, item_tag: TtlvTag, set_ignore_next_tag: bool) -> Result<()> {
99        if self.advance_state_machine(FieldType::Tag)? {
100            if set_ignore_next_tag {
101                let loc = self.location();
102                self.state.ignore_next_tag().map_err(|err| pinpoint!(err, loc))?;
103            }
104            item_tag.write(&mut self.dst).map_err(|err| pinpoint!(err, self))?;
105        }
106        Ok(())
107    }
108
109    /// Write the TTLV item type ("a byte containing a coded value"). This will advance the buffer write position by
110    /// 1 byte.
111    fn write_type(&mut self, item_type: TtlvType) -> Result<()> {
112        if self.advance_state_machine(FieldType::Type)? {
113            item_type.write(&mut self.dst).map_err(|err| pinpoint!(err, self))?;
114        }
115        Ok(())
116    }
117
118    /// Push a dummy 0x000000 4-byte TTLV item length. After writing the value bytes we'll come back later and replace
119    /// the dummy bytes with the correct item length. Adds a bookmark at the current buffer write location so that
120    /// fn rewite_len() knows where to come back to.
121    fn write_zero_len(&mut self) -> Result<()> {
122        if self.advance_state_machine(FieldType::Length)? {
123            TtlvLength::new(0)
124                .write(&mut self.dst)
125                .map_err(|err| pinpoint!(err, self.location()))?;
126            self.bookmarks.push(self.dst.len());
127        }
128        Ok(())
129    }
130
131    /// Replace the most recent dummy 0x00000000 4-byte TTLV item length written by the last call to fn write_zero_len()
132    /// with the actual TTLV item length value. Assumes that the most recently bookmarked location in the write buffer
133    /// is the start of the 4 bytes to overwrite.
134    fn rewrite_len(&mut self) -> Result<()> {
135        if let Some(v_start_pos) = self.bookmarks.pop() {
136            // the bookmark is the position just after the L in TTLV, i.e. the start of the value V. Calculate the length of
137            // V by comparing the bookmarked position to our current position in the write buffer, then write that length
138            // into the bookmarked L position.
139            let len_to_write: u32 = (self.dst.len() - v_start_pos) as u32;
140            let bytes_to_overwrite = &mut self.dst.as_mut_slice()[v_start_pos - 4..v_start_pos];
141            bytes_to_overwrite.copy_from_slice(&len_to_write.to_be_bytes());
142        }
143        Ok(())
144    }
145
146    /// To be called at the end of serializing the stream of TTLV bytes. Makes sure that we didn't forget to rewrite the
147    /// last dummy TTLV length value and verifies afterwards that there are no bookmarks left.
148    fn finalize(&mut self) -> Result<()> {
149        if !self.bookmarks.is_empty() {
150            // This shouldn't happen.
151            Err(pinpoint!(MalformedTtlvError::UnknownStructureLength, self))
152        } else {
153            Ok(())
154        }
155    }
156
157    fn location(&self) -> ErrorLocation {
158        ErrorLocation::from(self.dst.len())
159    }
160
161    fn advance_state_machine(&mut self, next_state: FieldType) -> Result<bool> {
162        self.state.advance(next_state).map_err(|err| pinpoint!(err, self))
163    }
164}
165
166impl serde::ser::Serializer for &mut TtlvSerializer {
167    type Ok = ();
168    type Error = Error;
169
170    // =======================================================
171    // RUST TYPES FOR WHICH SERIALIZATION TO TTLV IS SUPPORTED
172    // =======================================================
173    type SerializeSeq = Self;
174    type SerializeStruct = Self;
175    type SerializeTupleStruct = Self;
176    type SerializeTupleVariant = Self;
177
178    /// This fn is called at the start of serializing a Rust tuple struct, e.g. struct SomeStruct(type, type, type). The
179    /// struct contents will be written out as a tree of TTLV structures (TTLV type 0x01) with each field in the Rust
180    /// structure being represented as a TTLV tag, type, len and value byte sequence. Inner structs or other supported
181    /// complex Rust types that can be serialized by this Serializer will be rendered as inner TTLV structure sequences
182    /// in the created TTLV byte sequence. The TTLV tag value to write is taken from the name argument passed to this fn.
183    /// When using #[derive(Serialize)] you should use #[serde(rename = "0xAABBCC")] to cause the name argument value
184    /// received here to be the TTLV tag value to use when serializing the structure to the write buffer.
185    fn serialize_tuple_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
186        let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
187        self.write_tag(item_tag, false)?;
188        self.write_type(TtlvType::Structure)?;
189        self.write_zero_len()?;
190        // SerializeTupleStruct will write out the tuple fields then call rewrite_len()
191        Ok(self)
192    }
193
194    /// Serialize a Rust bool value into the TTLV write buffer as TTLV type 0x06 (Boolean).
195    fn serialize_bool(self, v: bool) -> Result<()> {
196        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
197            TtlvBoolean(v)
198                .write(&mut self.dst)
199                .map_err(|err| pinpoint!(err, self))?;
200        }
201        Ok(())
202    }
203
204    /// Serialize a Rust integer value into the TTLV write buffer as TTLV type 0x02 (Integer).
205    fn serialize_i8(self, v: i8) -> Result<()> {
206        self.serialize_i32(v as i32)
207    }
208
209    /// Serialize a Rust integer value into the TTLV write buffer as TTLV type 0x02 (Integer).
210    fn serialize_i16(self, v: i16) -> Result<()> {
211        self.serialize_i32(v as i32)
212    }
213
214    /// Serialize a Rust integer value into the TTLV write buffer as TTLV type 0x02 (Integer).
215    fn serialize_i32(self, v: i32) -> Result<()> {
216        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
217            TtlvInteger(v)
218                .write(&mut self.dst)
219                .map_err(|err| pinpoint!(err, self))?;
220        }
221        Ok(())
222    }
223
224    /// Serialize a Rust unsigned 32-bit integer value into the TTLV write buffer as TTLV type 0x05 (Enumeration).
225    fn serialize_u32(self, v: u32) -> Result<()> {
226        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
227            TtlvEnumeration(v)
228                .write(&mut self.dst)
229                .map_err(|err| pinpoint!(err, self))?;
230        }
231        Ok(())
232    }
233
234    /// Serialize a Rust integer value into the TTLV write buffer as TTLV type 0x03 (Long Integer).
235    fn serialize_i64(self, v: i64) -> Result<()> {
236        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
237            TtlvLongInteger(v)
238                .write(&mut self.dst)
239                .map_err(|err| pinpoint!(err, self))?;
240        }
241        Ok(())
242    }
243
244    /// Serialize a Rust unsigned 64-bit integer value into the TTLV write buffer as TTLV type 0x09 (DateTime).
245    ///
246    /// TTLV DateTime values are serialized as a signed 64-bit value but as we need to ensure that we serialize the
247    /// correct TTLV type we can't handle these in serialize_i64 as that is already used for TTLV type 0x03
248    /// (Long Integer).
249    fn serialize_u64(self, v: u64) -> Result<()> {
250        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
251            TtlvDateTime(v as i64)
252                .write(&mut self.dst)
253                .map_err(|err| pinpoint!(err, self))?;
254        }
255        Ok(())
256    }
257
258    /// Serialize a Rust str value into the TTLV write buffer as TTLV type 0x07 (Text String).
259    fn serialize_str(self, v: &str) -> Result<()> {
260        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
261            TtlvTextString(v.to_string())
262                .write(&mut self.dst)
263                .map_err(|err| pinpoint!(err, self))?;
264        }
265        Ok(())
266    }
267
268    /// Use #[serde(with = "serde_bytes")] to direct Serde to this serializer function for type Vec<u8>.
269    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
270        if self.advance_state_machine(FieldType::TypeAndLengthAndValue)? {
271            TtlvByteString(v.to_vec())
272                .write(&mut self.dst)
273                .map_err(|err| pinpoint!(err, self))?;
274        }
275        Ok(())
276    }
277
278    /// Serialize a unit enum variant.
279    ///
280    /// We can't serialize based on the discriminant as Serde doesn't make that available to us. We also can't serialize
281    /// based on the variant index as most KMIP enumerations start at one rather than zero, and we can't work based on
282    /// that assumption either as some start at other numbers entirely (e.g. the KMIP spec 1.0 section 9.1.3.2.19 Link
283    /// Type Enumeration defines an enumeration that starts at 0x00000101). And we can't serialize based on the variant
284    /// name if that name is a string, e.g. "Query", as TTLV requires an enumeration to be serialized as a 32-bit
285    /// unsigned integer and we only have a string which might not be (correctly) convertable to an integer. And we also
286    /// can't serialize using serde_repr which would give us access to the discriminant, but would invoke our
287    /// `fn serialize_u32()` function with ONLY the discriminant, we wouldn't be able to write out the TTLV tag as we
288    /// wouldn't know what it was.
289    ///
290    /// Therefore we require the tag AND the discriminant to be communicated to us. The tag should be passed via the
291    /// enum name and the discriminant via the variant name. When using serde-derive both should be overridden using the
292    /// `#[serde(rename = "0xAABBCC")]` syntax, e.g.
293    ///
294    /// ```ignore
295    /// #[derive(Serialize)]
296    /// #[serde(rename = "0x42005C")]
297    /// enum MyEnum {
298    ///     #[serde(rename = "0x000000001")] // The discriminant has to be defined here.
299    ///     SomeVariant // = 1,                 Any discriminant value assigned here will be ignored
300    /// }
301    /// ```
302    fn serialize_unit_variant(self, name: &'static str, _variant_index: u32, variant: &'static str) -> Result<()> {
303        // Don't write the tag if we just wrote a tag. This can happen in situations like this:
304        //
305        //   Tag: Template-Attribute (0x420091), Type: Structure (0x01), Data:
306        //     Tag: Attribute (0x420008), Type: Structure (0x01), Data:
307        //       Tag: Attribute Name (0x42000A), Type: Text String (0x07), Data: Cryptographic Algorithm
308        //       Tag: Attribute Value (0x42000B), Type: Enumeration (0x05), Data: 0x00000003 (AES)
309        //
310        // Here we've just written out the tag 0x42000B and we're about to write the enum value 0x00000003. However, the
311        // input to Serde that we are processing looked like this:
312        //
313        //   #[derive(Clone, Copy, Debug, Deserialize, Serialize, Display, PartialEq, Eq)]
314        //   #[serde(rename = "0x420028")]
315        //   #[non_exhaustive]
316        //   #[allow(non_camel_case_types)]
317        //   pub enum CryptographicAlgorithm {
318        //       #[serde(rename = "0x00000001")]
319        //       ...
320        //
321        // This type has its own tag, 0x4200028, and we would normally write this out as a full TTLV. In the case of a
322        // KMIP Attribute Value however the tag is always the same, 0x420000B, and the type of the data is inferred by
323        // the deserializer by looking at the Data of the preceeding Attribute Name.
324        //
325        // So in this case we should skip writing out the tag and only write the type, length and value.
326
327        let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
328        self.write_tag(item_tag, false)?;
329
330        let variant = u32::from_str_radix(variant.trim_start_matches("0x"), 16)
331            .map_err(|_| pinpoint!(SerdeError::InvalidVariant(variant), self.location()))?;
332        variant.serialize(self)
333    }
334
335    /// Serialize a struct SomeEnumVariant(a, b, c) to the TTLV write buffer as a TTLV Structure with fields a, b and c.
336    fn serialize_tuple_variant(
337        self,
338        name: &'static str,
339        _variant_index: u32,
340        _variant: &'static str,
341        _len: usize,
342    ) -> Result<Self::SerializeTupleVariant> {
343        // The Override name prefix has no meaning in the case of a tuple variant, it only applies to a single inner
344        // tagged value whose tag should be overriden. See serialize_newtype_variant().
345        let name = name.strip_prefix("Override:").unwrap_or(name);
346        let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
347        self.write_tag(item_tag, false)?;
348        self.write_type(TtlvType::Structure)?;
349        self.write_zero_len()?;
350        // SerializeTupleVariant will write out the tuple fields then call rewrite_len()
351        Ok(self)
352    }
353
354    fn serialize_newtype_variant<T: ?Sized>(
355        self,
356        name: &'static str,
357        variant_index: u32,
358        variant: &'static str,
359        value: &T,
360    ) -> Result<()>
361    where
362        T: Serialize,
363    {
364        // If the Override name prefix is present use the tag of this enum when writing the next item instead of that
365        // items own tag.
366        let (name, set_ignore_next_tag) = if let Some(name) = name.strip_prefix("Override:") {
367            (name, true)
368        } else {
369            (name, false)
370        };
371
372        // If the variant name is "Transparent" serialize the inner value directly, don't wrap it in a TTLV Structure.
373        if variant == "Transparent" {
374            let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
375            self.write_tag(item_tag, set_ignore_next_tag)?;
376            value.serialize(self)
377        } else {
378            let mut ser = self.serialize_tuple_variant(name, variant_index, variant, 1)?;
379            ser.serialize_field(value)?;
380            ser.end()
381        }
382    }
383
384    /// Serialize a struct SomeStruct(type) to the TTLV write buffer as if it were the naked type without the enclosing
385    /// "newtype" SomeStruct wrapper.
386    ///
387    /// We don't use `#[serde(transparent)]` on the structs because then the serialization process would go straight to
388    /// functions such as `serialize_i32()` which serialize the V in TTLV but we also need to serialize the TTL part as
389    /// well.
390    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<()>
391    where
392        T: Serialize,
393    {
394        if let Some(name) = name.strip_prefix("Transparent:") {
395            let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
396            self.write_tag(item_tag, false)?;
397            value.serialize(self)
398        } else {
399            let mut ser = self.serialize_tuple_struct(name, 1)?;
400            ser.serialize_field(value)?;
401            ser.end()
402        }
403    }
404
405    /// Serializing Rust brace structs to TTLV.
406    ///
407    /// Use of newtype and tuple structs is preferred as it leads to less verbose (yet still well named) Rust
408    /// hierarchical data structures because the field names do not need to be expressed. Usually this would be less
409    /// readable but because wrapper types must be used around primitive types (in order to give them a Serde "name"
410    /// which will be used as the TTLV "tag") then the unnamed primitive value is still wrapped in a named wrapper type.
411    ///
412    /// One use case for brace structs however is to avoid having to define separately a tuple struct for a type sent in
413    /// a request and a brace struct for the same type when received in a response. For structs with many fields this
414    /// can lead to a lot of duplication. If instead a single brace struct is defined but helper functions on the struct
415    /// are used to streamline the request construction this can be a way to achieve the best of both worlds: simple
416    /// requests based on anonymous fields that are self-evident from their type names, and responses with helpfully
417    /// named member fields for cases where there is no need to explicitly name the field type in order to use it.
418    fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
419        let item_tag = TtlvTag::from_str(name).map_err(|err| pinpoint!(err, self.location()))?;
420        self.write_tag(item_tag, false)?;
421        self.write_type(TtlvType::Structure)?;
422        self.write_zero_len()?;
423        // SerializeStruct will write out the tuple fields then call rewrite_len()
424        Ok(self)
425    }
426
427    /// Dispatch serialization of a Rust sequence type such as Vec to the implementation of SerializeSeq that we
428    /// provide.
429    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
430        Ok(self)
431    }
432
433    /// Serialize a `Some(value)` as if it were plain `value`.
434    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<()>
435    where
436        T: Serialize,
437    {
438        value.serialize(self)
439    }
440
441    // ==============================================================
442    // RUST TYPES FOR WHICH SERIALIZATION TO TTLV IS _NOT_ SUPPORTED!
443    // ==============================================================
444
445    type SerializeMap = Impossible<(), Self::Error>;
446    type SerializeStructVariant = Impossible<(), Self::Error>;
447    type SerializeTuple = Impossible<(), Self::Error>;
448
449    fn serialize_u8(self, _v: u8) -> Result<()> {
450        Err(pinpoint!(SerdeError::UnsupportedRustType("u8"), self))
451    }
452
453    fn serialize_u16(self, _v: u16) -> Result<()> {
454        Err(pinpoint!(SerdeError::UnsupportedRustType("u16"), self))
455    }
456
457    fn serialize_f32(self, _v: f32) -> Result<()> {
458        Err(pinpoint!(SerdeError::UnsupportedRustType("f32"), self))
459    }
460
461    fn serialize_f64(self, _v: f64) -> Result<()> {
462        Err(pinpoint!(SerdeError::UnsupportedRustType("f64"), self))
463    }
464
465    fn serialize_char(self, _v: char) -> Result<()> {
466        Err(pinpoint!(SerdeError::UnsupportedRustType("char"), self))
467    }
468
469    /// Serializing `None` values, e.g. Option::<TypeName>::None, is not supported.
470    ///
471    /// TTLV doesn't support the notion of a serialized value that indicates the absence of a value.
472    ///
473    /// ### Using Serde to "skip" a missing value
474    ///
475    /// The correct way to omit None values is to not attempt to serialize them at all, e.g. using the
476    /// `#[serde(skip_serializing_if = "Option::is_none")]` Serde derive field attribute. Note that at the time of
477    /// writing it seems that Serde derive only handles this attribute correctly when used on Rust brace struct field
478    /// members (which we do not support), or on tuple struct fields (i.e. there must be more than one field). Also,
479    /// note that not serializing a None struct field value will still result in the struct itself being serialized as
480    /// a TTLV "Structure" unless you also mark the struct as "transparent" (using the rename attribute like so:
481    /// `[#serde(rename = "Transparent:0xAABBCC"))]`. Using the attribute on newtype structs still causes Serde derive
482    /// to invoke `serialize_none()` which will result in an unsupported error.
483    ///
484    /// ### Rationale
485    ///
486    /// As we have already serialized the item tag to the output by the time we process the `Option` value, serializing
487    /// nothing here would still result in something having been serialized. We could in theory remove the already
488    /// serialized bytes from the stream but is not necessarily safe, e.g. if the already serialized bytes were a TTLV
489    /// Structure "header" (i.e. 0xAABBCC 0x00000001 0x00000000) removing the header might be incorrect if there are
490    /// other structure items that will be serialized to the stream after this "none". Removing the Structure "header"
491    /// bytes would also break the current logic which at the end of a structure goes back to the start and replaces the
492    /// zero length value in the TTLV Structure "header" with the actual length as the bytes to replace would no longer
493    /// exist.
494    fn serialize_none(self) -> Result<()> {
495        Err(pinpoint!(SerdeError::UnsupportedRustType("None"), self))
496    }
497
498    fn serialize_unit(self) -> Result<()> {
499        Err(pinpoint!(SerdeError::UnsupportedRustType("unit"), self))
500    }
501
502    fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
503        Err(pinpoint!(SerdeError::UnsupportedRustType("unit struct"), self))
504    }
505
506    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
507        Err(pinpoint!(SerdeError::UnsupportedRustType("tuple"), self))
508    }
509
510    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
511        Err(pinpoint!(SerdeError::UnsupportedRustType("map"), self))
512    }
513
514    fn serialize_struct_variant(
515        self,
516        _name: &'static str,
517        _variant_index: u32,
518        _variant: &'static str,
519        _len: usize,
520    ) -> Result<Self::SerializeStructVariant> {
521        Err(pinpoint!(SerdeError::UnsupportedRustType("struct variant"), self))
522    }
523}
524
525// =======================================
526// SERIALIZATION OF RUST SEQUENCES TO TTLV
527// =======================================
528impl ser::SerializeSeq for &mut TtlvSerializer {
529    type Ok = ();
530    type Error = Error;
531
532    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<()>
533    where
534        T: Serialize,
535    {
536        value.serialize(&mut **self)
537    }
538
539    fn end(self) -> Result<()> {
540        Ok(())
541    }
542}
543
544// =====================================
545// SERIALIZATION OF RUST STRUCTS TO TTLV
546// =====================================
547impl ser::SerializeStruct for &mut TtlvSerializer {
548    type Ok = ();
549    type Error = Error;
550
551    fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> Result<()>
552    where
553        T: Serialize,
554    {
555        value.serialize(&mut **self)
556    }
557
558    fn end(self) -> Result<()> {
559        // This fn is called at the end of serializing a Struct.
560        self.rewrite_len()
561    }
562}
563
564// ===========================================
565// SERIALIZATION OF RUST TUPLE STRUCTS TO TTLV
566// ===========================================
567impl ser::SerializeTupleStruct for &mut TtlvSerializer {
568    type Ok = ();
569    type Error = Error;
570
571    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()>
572    where
573        T: Serialize,
574    {
575        value.serialize(&mut **self)
576    }
577
578    fn end(self) -> Result<()> {
579        // This fn is called at the end of serializing a Struct.
580        self.rewrite_len()
581    }
582}
583
584// ============================================
585// SERIALIZATION OF RUST TUPLE VARIANTS TO TTLV
586// ============================================
587impl ser::SerializeTupleVariant for &mut TtlvSerializer {
588    type Ok = ();
589    type Error = Error;
590
591    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()>
592    where
593        T: Serialize,
594    {
595        value.serialize(&mut **self)
596    }
597
598    fn end(self) -> Result<Self::Ok> {
599        // This fn is called at the end of serializing a tuple variant.
600        // TODO: go back to the length byte pos in the vec and write in our distance from that point
601        // Either we need to receive back from ... from where? we get no values passed to us, so instead we need to
602        // store the position to go back to in the vec, but we'll need to do that for each level of struct nesting, push
603        // them on and pop them off.
604        self.rewrite_len()
605    }
606}
607
608#[cfg(test)]
609mod test {
610    #[allow(unused_imports)]
611    use pretty_assertions::{assert_eq, assert_ne};
612
613    use serde_derive::Serialize;
614
615    use crate::ser::to_vec;
616
617    #[test]
618    fn test_kmip_10_create_destroy_use_case_create_request_serialization() {
619        // Define the types used by the test below. Note that these are structured so as to be easy to compose with minimal
620        // boilerplate overhead. For example tuple structs are heavily used rather than structs with named fields. If this
621        // were for deserialization instead of serialization these types should instead be verbose with named fields to make
622        // it easy to interact with the response objects.
623        #[derive(Serialize)]
624        #[serde(rename = "0x420078")]
625        struct RequestMessage(RequestHeader, Vec<BatchItem>);
626
627        #[derive(Serialize)]
628        #[serde(rename = "0x420077")]
629        struct RequestHeader(ProtocolVersion, BatchCount);
630
631        #[derive(Serialize)]
632        #[serde(rename = "Transparent:0x42006B")]
633        struct ProtocolVersionMinor(i32);
634
635        #[derive(Serialize)]
636        #[serde(rename = "Transparent:0x42006A")]
637        struct ProtocolVersionMajor(i32);
638
639        #[derive(Serialize)]
640        #[serde(rename = "0x420069")]
641        struct ProtocolVersion(ProtocolVersionMajor, ProtocolVersionMinor);
642
643        #[derive(Serialize)]
644        #[serde(rename = "Transparent:0x42000D")]
645        struct BatchCount(i32);
646
647        #[derive(Serialize)]
648        #[serde(rename = "0x42000F")]
649        struct BatchItem(Operation, RequestPayload);
650
651        #[derive(Serialize)]
652        #[serde(rename = "0x42005C")]
653        enum Operation {
654            #[serde(rename = "0x00000001")]
655            Create,
656        }
657
658        #[derive(Serialize)]
659        #[serde(rename = "0x420079")]
660        struct RequestPayload(ObjectType, TemplateAttribute);
661
662        #[derive(Serialize)]
663        #[serde(rename = "0x420057")]
664        enum ObjectType {
665            #[serde(rename = "0x00000002")]
666            SymmetricKey,
667        }
668
669        #[derive(Serialize)]
670        #[serde(rename = "0x420091")]
671        struct TemplateAttribute(Vec<Attribute>);
672
673        #[derive(Serialize)]
674        #[serde(rename = "0x420008")]
675        struct Attribute(AttributeName, AttributeValue);
676
677        #[derive(Serialize)]
678        #[serde(rename = "Transparent:0x42000A")]
679        struct AttributeName(&'static str);
680
681        #[derive(Serialize)]
682        #[serde(rename = "Override:0x42000B")]
683        enum AttributeValue {
684            #[serde(rename = "Transparent")]
685            CryptographicAlgorithm(CryptographicAlgorithm),
686
687            #[serde(rename = "Transparent")]
688            Integer(i32),
689        }
690
691        impl Attribute {
692            #[allow(non_snake_case)]
693            fn CryptographicAlgorithm(value: CryptographicAlgorithm) -> Self {
694                Attribute(
695                    AttributeName("Cryptographic Algorithm"),
696                    AttributeValue::CryptographicAlgorithm(value),
697                )
698            }
699
700            #[allow(non_snake_case)]
701            fn CryptographicLength(value: i32) -> Self {
702                Attribute(AttributeName("Cryptographic Length"), AttributeValue::Integer(value))
703            }
704
705            #[allow(non_snake_case)]
706            fn CryptographicUsageMask(value: i32) -> Self {
707                Attribute(
708                    AttributeName("Cryptographic Usage Mask"),
709                    AttributeValue::Integer(value),
710                )
711            }
712        }
713
714        #[derive(Serialize)]
715        #[serde(rename = "420028")]
716        enum CryptographicAlgorithm {
717            #[serde(rename = "0x00000003")]
718            AES,
719        }
720
721        // Attempt to generate correct binary TTLV for KMIP specification v1.0 use case 3.1.1 Create / Destroy as the\
722        // use case definition includes the input structure and the corresponding expected binary output.
723        // See: http://docs.oasis-open.org/kmip/usecases/v1.0/cs01/kmip-usecases-1.0-cs-01.html
724
725        let use_case_input = RequestMessage(
726            RequestHeader(
727                ProtocolVersion(ProtocolVersionMajor(1), ProtocolVersionMinor(0)),
728                BatchCount(1),
729            ),
730            vec![BatchItem(
731                Operation::Create,
732                RequestPayload(
733                    ObjectType::SymmetricKey,
734                    TemplateAttribute(vec![
735                        Attribute::CryptographicAlgorithm(CryptographicAlgorithm::AES),
736                        Attribute::CryptographicLength(128),
737                        Attribute::CryptographicUsageMask(0x0000_000C),
738                    ]),
739                ),
740            )],
741        );
742
743        let use_case_output = concat!(
744            "42007801000001204200770100000038420069010000002042006A0200000004000000010000000042006B0200000",
745            "004000000000000000042000D0200000004000000010000000042000F01000000D842005C05000000040000000100",
746            "00000042007901000000C04200570500000004000000020000000042009101000000A8420008010000003042000A0",
747            "70000001743727970746F6772617068696320416C676F726974686D0042000B050000000400000003000000004200",
748            "08010000003042000A070000001443727970746F67726170686963204C656E6774680000000042000B02000000040",
749            "000008000000000420008010000003042000A070000001843727970746F67726170686963205573616765204D6173",
750            "6B42000B02000000040000000C00000000"
751        );
752
753        assert_eq!(
754            use_case_output,
755            hex::encode_upper(to_vec(&use_case_input).unwrap()),
756            "expected hex (left) differs to the generated hex (right)"
757        );
758    }
759
760    // The rule for how Rust structs are by default mapped to TTLV is: a struct will be serialized as a Structure,
761    // UNLESS it has been marked as "transparent". To use a Rust struct as a container to hang a Serde attribute off
762    // without actually serializing it as a TTLV Structure one must mark the struct as "transparent". Option types
763    // are also transparent in the sense that either the entire value SHOULD NOT be serialized if it is None, or if
764    // Some then only its inner value will be serialized.
765
766    #[test]
767    fn test_structure_members_must_be_tagged() {
768        // The following cannot be serialized as valid TTLV because a Rust struct is serialized as a TTLV Structure and
769        // a TTLV Structure must contain complete TTLV items (i.e. a full Tag+Type+Length+Value). This doesn't work for
770        // primitive types as they are passed by Serde Derive to serializer functions that only take a value as an
771        // argument, e.g. `serialize_i32(self, value)`, and so the serializer has no name from which to create the tag
772        // (for the initial T in TTLV) for the item. We also cannot handle a None value inside a struct because a None
773        // value should not be serialized at all yet by the time serialize_none() is invoked, the outer struct TTL part
774        // has already been serialized to the byte stream and not serializing the V part doesn't remove the alraedy
775        // serialized TTL part.
776        #[derive(Serialize)]
777        #[serde(rename = "0xAABBCC")]
778        struct SomeStruct(i32);
779        let to_encode = SomeStruct(3);
780        assert!(to_vec(&to_encode).is_err()); // Error: attempt to serialize malformed TTLTLV.
781    }
782
783    #[test]
784    fn test_a_transparent_struct_can_be_used_to_tag_a_primitive_value() {
785        // If we instead mark the struct as transparent we can then serialize the inner value using the Serde "name" of
786        // the struct as the TTLV tag, instead of creating a containing TTLV Structure with that tag as happens
787        // otherwise.
788        #[derive(Serialize)]
789        #[serde(rename = "Transparent:0xAABBCC")]
790        struct SomeStruct(i32);
791        let to_encode = SomeStruct(3);
792        assert_eq!(
793            "AABBCC02000000040000000300000000",
794            hex::encode_upper(to_vec(&to_encode).unwrap()),
795            "expected hex (left) differs to the generated hex (right)"
796        );
797    }
798
799    #[test]
800    fn test_ttlv_has_no_concept_of_values_that_denote_absence() {
801        #[derive(Serialize)]
802        #[serde(rename = "0xAABBCC")]
803        struct SomeStruct(Option<i32>);
804        let to_encode = SomeStruct(None);
805        assert!(to_vec(&to_encode).is_err()); // Error: serializing None is not supported.
806    }
807
808    #[test]
809    fn test_optional_values_that_are_present_are_serialized_as_the_value_directly() {
810        #[derive(Serialize)]
811        #[serde(rename = "Transparent:0xAABBCC")]
812        struct SomeStruct(Option<i32>);
813        let to_encode = SomeStruct(Some(3));
814        assert_eq!(
815            "AABBCC02000000040000000300000000",
816            hex::encode_upper(to_vec(&to_encode).unwrap()),
817            "expected hex (left) differs to the generated hex (right)"
818        );
819    }
820
821    #[test]
822    fn test_serde_derive_doesnt_skip_an_inner_none_inside_a_newtype() {
823        // One would expect the following to work, but Serde Derive ignores the skip directive in this case and still
824        // attempts to serialize the None. What would it mean for a Structure expected to have a single field for that
825        // field to be missing anyway?
826        #[derive(Serialize)]
827        #[serde(rename = "Transparent:0xAABBCC")]
828        struct TransparentItemWithConditionallySerializedOptionalField(
829            #[serde(skip_serializing_if = "Option::is_none")] Option<i32>,
830        );
831        let transparent_conditional_with_none = TransparentItemWithConditionallySerializedOptionalField(None);
832        assert!(to_vec(&transparent_conditional_with_none).is_err()); // Error: serializing None is not supported.
833    }
834
835    #[test]
836    fn test_transparent_is_only_for_newtypes_not_for_tuples() {
837        // Serde Derive will correctly ignore the None field if it is not the only field, but then in this case
838        // "Transparent:0xNNNNNNN" isn't supported because it is intended only for the case of a single inner field.
839        #[derive(Serialize)]
840        #[serde(rename = "Transparent:0xAABBCC")]
841        struct TransparentTupleWithConditionallySerializedOptionalField(
842            i32,
843            #[serde(skip_serializing_if = "Option::is_none")] Option<i32>,
844        );
845        let transparent_tuple_conditional_with_none = TransparentTupleWithConditionallySerializedOptionalField(1, None);
846        assert!(to_vec(&transparent_tuple_conditional_with_none).is_err()); // Error: "Transparent" is not supported here.
847    }
848
849    #[test]
850    fn test_serde_derive_can_skip_optional_none_values_in_a_tuple() {
851        // We can use Serde Derive to skip serialization of a None value if it is not the only inner value in the type
852        // being serialized:
853        #[derive(Serialize)]
854        #[serde(rename = "Transparent:0x123456")]
855        struct SomeTaggedValue(i32);
856
857        #[derive(Serialize)]
858        #[serde(rename = "0xAABBCC")]
859        struct TupleWithConditionallySerializedOptionalField(
860            SomeTaggedValue,
861            #[serde(skip_serializing_if = "Option::is_none")] Option<SomeTaggedValue>,
862        );
863        let tuple_conditional_with_none = TupleWithConditionallySerializedOptionalField(SomeTaggedValue(3), None);
864        assert_eq!(
865            "AABBCC010000001012345602000000040000000300000000",
866            hex::encode_upper(to_vec(&tuple_conditional_with_none).unwrap()),
867            "expected hex (left) differs to the generated hex (right)"
868        );
869    }
870}