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}