From be5900aa1121f3a9416ecdf08034fc0917a30ad1 Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Sun, 5 Jan 2025 05:33:26 -0800 Subject: [PATCH] Implement (de)serialization of `Option` --- README.md | 8 +++++--- examples/map_key_serialization.rs | 6 +++--- examples/serialization.rs | 6 ++++-- examples/transacted_serialization.rs | 4 ++-- src/decoder/serialization_serde.rs | 20 ++++++++++++++++---- src/encoder/serialization_serde.rs | 9 ++++++--- tests/serialization.rs | 27 ++++++++++++++++++++------- 7 files changed, 56 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index ef912cf..7c82f87 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Current features: * `u64` <=> `REG_QWORD` * Iteration through key names and through values * Transactions -* Transacted serialization of rust types into/from registry (only primitives, structures and maps for now) +* Transacted serialization of rust types into/from registry (only primitives, `Option`s, structures and maps for now) ## Usage @@ -204,7 +204,7 @@ struct Size { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Rectangle { - coords: Coords, + coords: Option, size: Size, } @@ -219,6 +219,7 @@ struct Test { t_struct: Rectangle, t_map: HashMap, t_string: String, + t_optional_string: Option, #[serde(rename = "")] // empty name becomes the (Default) value in the registry t_char: char, t_i8: i8, @@ -248,11 +249,12 @@ fn main() -> Result<(), Box> { t_u64: 123_456_789_101_112, t_usize: 1_234_567_891, t_struct: Rectangle { - coords: Coords { x: 55, y: 77 }, + coords: Some(Coords { x: 55, y: 77 }), size: Size { w: 500, h: 300 }, }, t_map: map, t_string: "test 123!".to_owned(), + t_optional_string: Some("test 456!".to_owned()), t_char: 'a', t_i8: -123, t_i16: -2049, diff --git a/examples/map_key_serialization.rs b/examples/map_key_serialization.rs index 729c662..44c9bc4 100644 --- a/examples/map_key_serialization.rs +++ b/examples/map_key_serialization.rs @@ -22,7 +22,7 @@ struct Size { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Rectangle { - coords: Coords, + coords: Option, size: Size, } @@ -33,14 +33,14 @@ fn main() -> Result<(), Box> { v1.insert( "first".to_owned(), Rectangle { - coords: Coords { x: 55, y: 77 }, + coords: Some(Coords { x: 55, y: 77 }), size: Size { w: 500, h: 300 }, }, ); v1.insert( "second".to_owned(), Rectangle { - coords: Coords { x: 11, y: 22 }, + coords: None, size: Size { w: 1000, h: 600 }, }, ); diff --git a/examples/serialization.rs b/examples/serialization.rs index c6df51e..3c31a4c 100644 --- a/examples/serialization.rs +++ b/examples/serialization.rs @@ -22,7 +22,7 @@ struct Size { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Rectangle { - coords: Coords, + coords: Option, size: Size, } @@ -37,6 +37,7 @@ struct Test { t_struct: Rectangle, t_map: HashMap, t_string: String, + t_optional_string: Option, #[serde(with = "serde_bytes")] t_bytes: Vec, #[serde(rename = "")] // empty name becomes the (Default) value in the registry @@ -68,11 +69,12 @@ fn main() -> Result<(), Box> { t_u64: 123_456_789_101_112, t_usize: 1_234_567_891, t_struct: Rectangle { - coords: Coords { x: 55, y: 77 }, + coords: Some(Coords { x: 55, y: 77 }), size: Size { w: 500, h: 300 }, }, t_map: map, t_string: "test 123!".to_owned(), + t_optional_string: Some("test 456!".to_owned()), t_bytes: vec![0xDE, 0xAD, 0xBE, 0xEF], t_char: 'a', t_i8: -123, diff --git a/examples/transacted_serialization.rs b/examples/transacted_serialization.rs index e586aae..8d7e95e 100644 --- a/examples/transacted_serialization.rs +++ b/examples/transacted_serialization.rs @@ -23,7 +23,7 @@ struct Size { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Rectangle { - coords: Coords, + coords: Option, size: Size, } @@ -70,7 +70,7 @@ fn main() -> Result<(), Box> { t_u64: 123_456_789_101_112, t_usize: 1_234_567_891, t_struct: Rectangle { - coords: Coords { x: 55, y: 77 }, + coords: Some(Coords { x: 55, y: 77 }), size: Size { w: 500, h: 300 }, }, t_map: map, diff --git a/src/decoder/serialization_serde.rs b/src/decoder/serialization_serde.rs index 9402f93..dc95f28 100644 --- a/src/decoder/serialization_serde.rs +++ b/src/decoder/serialization_serde.rs @@ -4,7 +4,7 @@ // may not be copied, modified, or distributed // except according to those terms. use super::{DecodeResult, Decoder, DecoderCursor, DecoderError, DECODER_SAM}; -use crate::types::FromRegValue; +use crate::{types::FromRegValue, RegValue}; use serde::de::*; use std::fmt; @@ -176,9 +176,21 @@ impl<'de, 'a> Deserializer<'de> for &'a mut Decoder { let v = { use super::DecoderCursor::*; match self.cursor { - FieldVal(_, ref name) => { - self.key.get_raw_value(name).map_err(DecoderError::IoError) - } + Start => return visitor.visit_some(&mut *self), + FieldVal(index, ref name) => self + .key + .get_raw_value(name) + .map_err(DecoderError::IoError) + .and_then(|v| match v { + RegValue { + vtype: crate::enums::RegType::REG_NONE, + .. + } => { + self.cursor = DecoderCursor::Field(index + 1); + Err(DecoderError::DeserializerError("Found REG_NONE".to_owned())) + } + val => Ok(val), + }), _ => Err(DecoderError::DeserializerError("Nothing found".to_owned())), } }; diff --git a/src/encoder/serialization_serde.rs b/src/encoder/serialization_serde.rs index 787db06..af4ddef 100644 --- a/src/encoder/serialization_serde.rs +++ b/src/encoder/serialization_serde.rs @@ -106,11 +106,14 @@ impl<'a, Tr: AsRef> Serializer for &'a mut Encoder { } fn serialize_none(self) -> EncodeResult { - no_impl!("serialize_none") + match mem::replace(&mut self.state, Start) { + NextKey(..) => Ok(()), + Start => Err(EncoderError::NoFieldName), + } } - fn serialize_some(self, _value: &T) -> EncodeResult { - no_impl!("serialize_some") + fn serialize_some(self, value: &T) -> EncodeResult { + value.serialize(self) } fn serialize_unit(self) -> EncodeResult { diff --git a/tests/serialization.rs b/tests/serialization.rs index 07e3bf6..a9d35c2 100644 --- a/tests/serialization.rs +++ b/tests/serialization.rs @@ -23,7 +23,7 @@ struct Size { #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Rectangle { - coords: Coords, + coords: Option, size: Size, } @@ -35,9 +35,14 @@ struct AllFields { t_u32: u32, t_u64: u64, t_usize: usize, - t_struct: Rectangle, + t_rect_no_coords: Rectangle, + t_rect_with_coords: Rectangle, t_string: String, t_map: HashMap>, + t_optional_u32_none: Option, + t_optional_u32_some: Option, + t_optional_map_none: Option>, + t_optional_map_some: Option>, t_i8: i8, t_i16: i16, t_i32: i32, @@ -63,7 +68,7 @@ impl AllFields { k2.insert("val3".to_owned(), 1024); let mut map = HashMap::new(); - map.insert("key1".to_owned(), k1); + map.insert("key1".to_owned(), k1.clone()); map.insert("key2".to_owned(), k2); AllFields { @@ -73,11 +78,19 @@ impl AllFields { t_u32: 123_456_789, t_u64: 123_456_789_101_112, t_usize: 1_234_567_891, - t_struct: Rectangle { - coords: Coords { x: 55, y: 77 }, + t_rect_no_coords: Rectangle { + coords: None, + size: Size { w: 320, h: 240 }, + }, + t_rect_with_coords: Rectangle { + coords: Some(Coords { x: 55, y: 77 }), size: Size { w: 500, h: 300 }, }, t_map: map, + t_optional_u32_none: None, + t_optional_u32_some: Some(1234), + t_optional_map_none: None, + t_optional_map_some: Some(k1), t_string: "Test123 \n$%^&|+-*/\\()".to_owned(), t_i8: -123, t_i16: -2049, @@ -95,7 +108,7 @@ impl AllFields { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct SomeFields { t_usize: usize, - t_struct: Rectangle, + t_rect_no_coords: Rectangle, t_string: String, t_u32: Option, t_none: Option, @@ -105,7 +118,7 @@ impl PartialEq for SomeFields { fn eq(&self, other: &AllFields) -> bool { *self.t_string == other.t_string && self.t_usize == other.t_usize - && self.t_struct == other.t_struct + && self.t_rect_no_coords == other.t_rect_no_coords && self.t_u32 == Some(other.t_u32) && self.t_none.is_none() }