From 7d2ea51d5df234110399b08d655e9390be83bf7e Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 5 May 2023 17:38:56 +0200 Subject: [PATCH] rust: test `serde` support A trivial example based on `serde`'s `example-format' [1]. It contains both a in-`kernel` data format later used by the kernel module, as well as a local data format in the module. The kernel module gives an output such as: [ 0.801425] rust_serde: Rust serde sample (init) [ 0.801634] rust_serde: original = S { a: (), b: false, c: true, d: () } [ 0.802079] rust_serde: serialized = [2, 0, 1, 0, 1, 1, 0, 3] [ 0.802506] rust_serde: deserialized = S { a: (), b: false, c: true, d: () } [ 0.802718] rust_serde: serialized (local) = [2, 0, 1, 42, 1, 43, 0, 3] [ 0.802895] rust_serde: deserialized (local) = S { a: (), b: false, c: true, d: () } [ 0.808954] rust_serde: Rust serde sample (exit) Note that this is just a quick draft/hack to check the previous commits work. It is not intended to be merged at all. Link: https://github.com/serde-rs/example-format [1] Signed-off-by: Miguel Ojeda --- rust/kernel/error.rs | 2 +- rust/kernel/lib.rs | 2 + rust/kernel/test_serde.rs | 26 ++ rust/kernel/test_serde/de.rs | 442 ++++++++++++++++++++++ rust/kernel/test_serde/error.rs | 73 ++++ rust/kernel/test_serde/ser.rs | 469 ++++++++++++++++++++++++ samples/rust/Kconfig | 10 + samples/rust/Makefile | 1 + samples/rust/local_data_format/de.rs | 422 +++++++++++++++++++++ samples/rust/local_data_format/error.rs | 73 ++++ samples/rust/local_data_format/ser.rs | 443 ++++++++++++++++++++++ samples/rust/rust_serde.rs | 73 ++++ 12 files changed, 2035 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/test_serde.rs create mode 100644 rust/kernel/test_serde/de.rs create mode 100644 rust/kernel/test_serde/error.rs create mode 100644 rust/kernel/test_serde/ser.rs create mode 100644 samples/rust/local_data_format/de.rs create mode 100644 samples/rust/local_data_format/error.rs create mode 100644 samples/rust/local_data_format/ser.rs create mode 100644 samples/rust/rust_serde.rs diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index 5f4114b30b94c7..01dd4d2f63d27a 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -177,7 +177,7 @@ impl From for Error { /// Note that even if a function does not return anything when it succeeds, /// it should still be modeled as returning a `Result` rather than /// just an [`Error`]. -pub type Result = core::result::Result; +pub type Result = core::result::Result; /// Converts an integer as returned by a C kernel function to an error if it's negative, and /// `Ok(())` otherwise. diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 676995d4e46038..8c929f776c4c1d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -101,3 +101,5 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! { // instead of `!`. See . loop {} } + +pub mod test_serde; diff --git a/rust/kernel/test_serde.rs b/rust/kernel/test_serde.rs new file mode 100644 index 00000000000000..012bf58213a81f --- /dev/null +++ b/rust/kernel/test_serde.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Test `serde`. +//! +//! It contains a data format used by the `rust_serde` sample, as well +//! as a quick check that `serde_derive` works in the `kernel` crate too. + +#![allow(missing_docs)] + +mod de; +mod error; +mod ser; + +pub use de::{from_bytes, Deserializer}; +pub use error::{Error, Result}; +pub use ser::{to_vec, Serializer}; + +use serde_derive::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct S { + a: (), + b: bool, + c: bool, + d: (), +} diff --git a/rust/kernel/test_serde/de.rs b/rust/kernel/test_serde/de.rs new file mode 100644 index 00000000000000..84c98d1c1c6650 --- /dev/null +++ b/rust/kernel/test_serde/de.rs @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::error::{Error, Result}; +use serde::de::{self, Deserialize, DeserializeSeed, SeqAccess, Visitor}; + +pub struct Deserializer<'de> { + // This string starts with the input data and characters are truncated off + // the beginning as data is parsed. + input: &'de [u8], +} + +impl<'de> Deserializer<'de> { + // By convention, `Deserializer` constructors are named like `from_xyz`. + // That way basic use cases are satisfied by something like + // `serde_json::from_str(...)` while advanced use cases that require a + // deserializer can make one with `serde_json::Deserializer::from_str(...)`. + #[allow(clippy::should_implement_trait)] + pub fn from_bytes(input: &'de [u8]) -> Self { + Deserializer { input } + } +} + +// By convention, the public API of a Serde deserializer is one or more +// `from_xyz` methods such as `from_str`, `from_bytes`, or `from_reader` +// depending on what Rust types the deserializer is able to consume as input. +// +// This basic deserializer supports only `from_str`. +pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_bytes(s); + let t = T::deserialize(&mut deserializer)?; + if deserializer.input.is_empty() { + Ok(t) + } else { + Err(Error::TrailingCharacters) + } +} + +// SERDE IS NOT A PARSING LIBRARY. This impl block defines a few basic parsing +// functions from scratch. More complicated formats may wish to use a dedicated +// parsing library to help implement their Serde deserializer. +impl<'de> Deserializer<'de> { + // Look at the first character in the input without consuming it. + fn peek_byte(&mut self) -> Result { + self.input.iter().next().ok_or(Error::Eof).map(|v| *v) + } + + // Consume the first character in the input. + fn next_byte(&mut self) -> Result { + let ch = self.peek_byte()?; + self.input = &self.input[1..]; + Ok(ch) + } + + // Parse the JSON identifier `true` or `false`. + fn parse_bool(&mut self) -> Result { + if self.input.starts_with(&[1]) { + self.input = &self.input[1..]; + match self.next_byte()? { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(Error::InvalidBooleanValue), + } + } else { + Err(Error::ExpectedBoolean) + } + } + + // Parse a group of decimal digits as an unsigned integer of type T. + // + // This implementation is a bit too lenient, for example `001` is not + // allowed in JSON. Also the various arithmetic operations can overflow and + // panic or return bogus data. But it is good enough for example code! + fn parse_unsigned(&mut self) -> Result { + unimplemented!() + } + + // Parse a possible minus sign followed by a group of decimal digits as a + // signed integer of type T. + fn parse_signed(&mut self) -> Result { + // Optional minus sign, delegate to `parse_unsigned`, negate if negative. + unimplemented!() + } +} + +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + // Look at the input data to decide what Serde data model type to + // deserialize as. Not all data formats are able to support this operation. + // Formats that support `deserialize_any` are known as self-describing. + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek_byte()? { + 0 => self.deserialize_unit(visitor), + 1 => self.deserialize_bool(visitor), + 2 => self.deserialize_map(visitor), + _ => Err(Error::Syntax), + } + } + + // Uses the `parse_bool` parsing function defined above to read the JSON + // identifier `true` or `false` from the input. + // + // Parsing refers to looking at the input and deciding that it contains the + // JSON value `true` or `false`. + // + // Deserialization refers to mapping that JSON value into Serde's data + // model by invoking one of the `Visitor` methods. In the case of JSON and + // bool that mapping is straightforward so the distinction may seem silly, + // but in other cases Deserializers sometimes perform non-obvious mappings. + // For example the TOML format has a Datetime type and Serde's data model + // does not. In the `toml` crate, a Datetime in the input is deserialized by + // mapping it to a Serde data model "struct" type with a special name and a + // single field containing the Datetime represented as a string. + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_bool(self.parse_bool()?) + } + + // The `parse_signed` function is generic over the integer type `T` so here + // it is invoked with `T=i8`. The next 8 methods are similar. + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i8(self.parse_signed()?) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i16(self.parse_signed()?) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i32(self.parse_signed()?) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i64(self.parse_signed()?) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u8(self.parse_unsigned()?) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u16(self.parse_unsigned()?) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u32(self.parse_unsigned()?) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u64(self.parse_unsigned()?) + } + + // The `Serializer` implementation on the previous page serialized chars as + // single-character strings so handle that representation here. + fn deserialize_char(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // Refer to the "Understanding deserializer lifetimes" page for information + // about the three deserialization flavors of strings in Serde. + fn deserialize_str(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + fn deserialize_string(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // The `Serializer` implementation on the previous page serialized byte + // arrays as JSON arrays of bytes. Handle that representation here. + fn deserialize_bytes(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + fn deserialize_byte_buf(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // An absent optional is represented as the JSON `null` and a present + // optional is represented as just the contained value. + // + // As commented in `Serializer` implementation, this is a lossy + // representation. For example the values `Some(())` and `None` both + // serialize as just `null`. Unfortunately this is typically what people + // expect when working with JSON. Other formats are encouraged to behave + // more intelligently if possible. + fn deserialize_option(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // In Serde, unit means an anonymous value containing no data. + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + if self.input.starts_with(&[0]) { + self.input = &self.input[1..]; + visitor.visit_unit() + } else { + Err(Error::ExpectedNull) + } + } + + // Unit struct means a named value containing no data. + fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + // As is done here, serializers are encouraged to treat newtype structs as + // insignificant wrappers around the data they contain. That means not + // parsing anything other than the contained value. + fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + // Deserialization of compound types like sequences and maps happens by + // passing the visitor an "Access" object that gives it the ability to + // iterate through the data contained in the sequence. + fn deserialize_seq(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // Tuples look just like sequences in JSON. Some formats may be able to + // represent tuples more efficiently. + // + // As indicated by the length parameter, the `Deserialize` implementation + // for a tuple in the Serde data model is required to know the length of the + // tuple before even looking at the input data. + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + // Tuple structs look just like sequences in JSON. + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + // Much like `deserialize_seq` but calls the visitors `visit_map` method + // with a `MapAccess` implementation, rather than the visitor's `visit_seq` + // method with a `SeqAccess` implementation. + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // Parse the opening brace of the map. + if self.next_byte()? == 2 { + // Give the visitor access to each entry of the map. + let value = visitor.visit_seq(StructFieldsVisitor::new(self))?; + // Parse the closing brace of the map. + if self.next_byte()? == 3 { + Ok(value) + } else { + Err(Error::ExpectedMapEnd) + } + } else { + Err(Error::ExpectedMap) + } + } + + // Structs look just like maps in JSON. + // + // Notice the `fields` parameter - a "struct" in the Serde data model means + // that the `Deserialize` implementation is required to know what the fields + // are before even looking at the input data. Any key-value pairing in which + // the fields cannot be known ahead of time is probably a map. + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // An identifier in Serde is the type that identifies a field of a struct or + // the variant of an enum. In JSON, struct fields and enum variants are + // represented as strings. In other formats they may be represented as + // numeric indices. + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + // Like `deserialize_any` but indicates to the `Deserializer` that it makes + // no difference which `Visitor` method is called because the data is + // ignored. + // + // Some deserializers are able to implement this more efficiently than + // `deserialize_any`, for example by rapidly skipping over matched + // delimiters without paying close attention to the data in between. + // + // Some formats are not able to implement this at all. Formats that can + // implement `deserialize_any` and `deserialize_ignored_any` are known as + // self-describing. + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } +} + +struct StructFieldsVisitor<'a, 'de> { + de: &'a mut Deserializer<'de>, +} + +impl<'a, 'de> StructFieldsVisitor<'a, 'de> { + fn new(de: &'a mut Deserializer<'de>) -> Self { + StructFieldsVisitor { de } + } +} + +impl<'de, 'a> SeqAccess<'de> for StructFieldsVisitor<'a, 'de> { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: DeserializeSeed<'de>, + { + // Check if there are no more elements. + if self.de.peek_byte()? == 3 { + return Ok(None); + } + // Deserialize an array element. + seed.deserialize(&mut *self.de).map(Some) + } +} + +//////////////////////////////////////////////////////////////////////////////// + +#[test] +fn test_struct() { + use serde_derive::Deserialize; + + #[derive(Deserialize, PartialEq, Debug)] + struct Test { + a: (), + b: bool, + } + + let j = &[2, 0, 1, 0, 3]; + let expected = Test { + a: (), + b: false, + }; + assert_eq!(expected, from_bytes(j).unwrap()); +} \ No newline at end of file diff --git a/rust/kernel/test_serde/error.rs b/rust/kernel/test_serde/error.rs new file mode 100644 index 00000000000000..a1eb3720ce67bc --- /dev/null +++ b/rust/kernel/test_serde/error.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::fmt::{self, Display}; +use serde::{de, ser}; + +pub type Result = crate::error::Result; + +// This is a bare-bones implementation. A real library would provide additional +// information in its error type, for example the line and column at which the +// error occurred, the byte offset into the input, or the current key being +// processed. +#[derive(Debug)] +pub enum Error { + // One or more variants that can be created by data structures through the + // `ser::Error` and `de::Error` traits. For example the Serialize impl for + // Mutex might return an error because the mutex is poisoned, or the + // Deserialize impl for a struct may return an error because a required + // field is missing. + Message, + + // Zero or more variants that can be created directly by the Serializer and + // Deserializer without going through `ser::Error` and `de::Error`. These + // are specific to the format, in this case JSON. + Eof, + Syntax, + ExpectedBoolean, + InvalidBooleanValue, + ExpectedInteger, + ExpectedString, + ExpectedNull, + ExpectedArray, + ExpectedArrayComma, + ExpectedArrayEnd, + ExpectedMap, + ExpectedMapColon, + ExpectedMapComma, + ExpectedMapEnd, + ExpectedEnum, + TrailingCharacters, +} + +impl ser::Error for Error { + fn custom(_msg: T) -> Self { + Error::Message + } +} + +impl de::Error for Error { + fn custom(_msg: T) -> Self { + Error::Message + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Message => write!(f, "message"), + Error::Eof => f.write_str("unexpected end of input"), + /* and so forth */ + _ => unimplemented!(), + } + } +} + +//impl core::error::Error for Error {} diff --git a/rust/kernel/test_serde/ser.rs b/rust/kernel/test_serde/ser.rs new file mode 100644 index 00000000000000..56abe7095a5f26 --- /dev/null +++ b/rust/kernel/test_serde/ser.rs @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::error::{Error, Result}; +use alloc::vec::Vec; +use serde::ser::{self, Serialize}; + +pub struct Serializer { + // This string starts empty and JSON is appended as values are serialized. + output: Vec, +} + +// By convention, the public API of a Serde serializer is one or more `to_abc` +// functions such as `to_string`, `to_bytes`, or `to_writer` depending on what +// Rust types the serializer is able to produce as output. +// +// This basic serializer supports only `to_string`. +pub fn to_vec(value: &T) -> Result> +where + T: Serialize, +{ + let mut serializer = Serializer { output: Vec::new() }; + value.serialize(&mut serializer)?; + Ok(serializer.output) +} + +impl<'a> ser::Serializer for &'a mut Serializer { + // The output type produced by this `Serializer` during successful + // serialization. Most serializers that produce text or binary output should + // set `Ok = ()` and serialize into an `io::Write` or buffer contained + // within the `Serializer` instance, as happens here. Serializers that build + // in-memory data structures may be simplified by using `Ok` to propagate + // the data structure around. + type Ok = (); + + // The error type when some error occurs during serialization. + type Error = Error; + + // Associated types for keeping track of additional state while serializing + // compound data structures like sequences and maps. In this case no + // additional state is required beyond what is already stored in the + // Serializer struct. + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + // Here we go with the simple methods. The following 12 methods receive one + // of the primitive types of the data model and map it to JSON by appending + // into the output string. + fn serialize_bool(self, v: bool) -> Result<()> { + self.output.try_push(1).unwrap(); + self.output.try_push(if v { 1 } else { 0 }).unwrap(); + Ok(()) + } + + // JSON does not distinguish between different sizes of integers, so all + // signed integers will be serialized the same and all unsigned integers + // will be serialized the same. Other formats, especially compact binary + // formats, may need independent logic for the different sizes. + fn serialize_i8(self, v: i8) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i16(self, v: i16) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i32(self, v: i32) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + // Not particularly efficient but this is example code anyway. A more + // performant approach would be to use the `itoa` crate. + fn serialize_i64(self, _v: i64) -> Result<()> { + unimplemented!(); + } + + fn serialize_u8(self, v: u8) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u16(self, v: u16) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u32(self, v: u32) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u64(self, _v: u64) -> Result<()> { + unimplemented!(); + } + + // Serialize a char as a single-character string. Other formats may + // represent this differently. + fn serialize_char(self, _v: char) -> Result<()> { + unimplemented!(); + } + + // This only works for strings that don't require escape sequences but you + // get the idea. For example it would emit invalid JSON if the input string + // contains a '"' character. + fn serialize_str(self, _v: &str) -> Result<()> { + unimplemented!(); + } + + // Serialize a byte array as an array of bytes. Could also use a base64 + // string here. Binary formats will typically represent byte arrays more + // compactly. + fn serialize_bytes(self, v: &[u8]) -> Result<()> { + use serde::ser::SerializeSeq; + let mut seq = self.serialize_seq(Some(v.len()))?; + for byte in v { + seq.serialize_element(byte)?; + } + seq.end() + } + + // An absent optional is represented as the JSON `null`. + fn serialize_none(self) -> Result<()> { + self.serialize_unit() + } + + // A present optional is represented as just the contained value. Note that + // this is a lossy representation. For example the values `Some(())` and + // `None` both serialize as just `null`. Unfortunately this is typically + // what people expect when working with JSON. Other formats are encouraged + // to behave more intelligently if possible. + fn serialize_some(self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + // In Serde, unit means an anonymous value containing no data. Map this to + // JSON as `null`. + fn serialize_unit(self) -> Result<()> { + self.output.try_push(0).unwrap(); + Ok(()) + } + + // Unit struct means a named value containing no data. Again, since there is + // no data, map this to JSON as `null`. There is no need to serialize the + // name in most formats. + fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { + self.serialize_unit() + } + + // When serializing a unit variant (or any other kind of variant), formats + // can choose whether to keep track of it by index or by name. Binary + // formats typically use the index of the variant and human-readable formats + // typically use the name. + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<()> { + self.serialize_str(variant) + } + + // As is done here, serializers are encouraged to treat newtype structs as + // insignificant wrappers around the data they contain. + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + // Note that newtype variant (and all of the other variant serialization + // methods) refer exclusively to the "externally tagged" enum + // representation. + // + // Serialize this to JSON in externally tagged form as `{ NAME: VALUE }`. + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + // Now we get to the serialization of compound types. + // + // The start of the sequence, each value, and the end are three separate + // method calls. This one is responsible only for serializing the start, + // which in JSON is `[`. + // + // The length of the sequence may or may not be known ahead of time. This + // doesn't make a difference in JSON because the length is not represented + // explicitly in the serialized form. Some serializers may only be able to + // support sequences for which the length is known up front. + fn serialize_seq(self, _len: Option) -> Result { + unimplemented!(); + } + + // Tuples look just like sequences in JSON. Some formats may be able to + // represent tuples more efficiently by omitting the length, since tuple + // means that the corresponding `Deserialize implementation will know the + // length without needing to look at the serialized data. + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + // Tuple structs look just like sequences in JSON. + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + // Tuple variants are represented in JSON as `{ NAME: [DATA...] }`. Again + // this method is only responsible for the externally tagged representation. + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + unimplemented!(); + } + + // Maps are represented in JSON as `{ K: V, K: V, ... }`. + fn serialize_map(self, _len: Option) -> Result { + self.output.try_push(2).unwrap(); + Ok(self) + } + + // Structs look just like maps in JSON. In particular, JSON requires that we + // serialize the field names of the struct. Other formats may be able to + // omit the field names when serializing structs because the corresponding + // Deserialize implementation is required to know what the keys are without + // looking at the serialized data. + fn serialize_struct(self, _name: &'static str, len: usize) -> Result { + self.serialize_map(Some(len)) + } + + // Struct variants are represented in JSON as `{ NAME: { K: V, ... } }`. + // This is the externally tagged representation. + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + unimplemented!(); + } + + fn collect_str(self, _: &T) -> Result<()> + where + T: core::fmt::Display, + { + unimplemented!() + } +} + +// The following 7 impls deal with the serialization of compound types like +// sequences and maps. Serialization of such types is begun by a Serializer +// method and followed by zero or more calls to serialize individual elements of +// the compound type and one call to end the compound type. +// +// This impl is SerializeSeq so these methods are called after `serialize_seq` +// is called on the Serializer. +impl<'a> ser::SerializeSeq for &'a mut Serializer { + // Must match the `Ok` type of the serializer. + type Ok = (); + // Must match the `Error` type of the serializer. + type Error = Error; + + // Serialize a single element of the sequence. + fn serialize_element(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + // Close the sequence. + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Same thing but for tuples. +impl<'a> ser::SerializeTuple for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Same thing but for tuple structs. +impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Tuple variants are a little different. Refer back to the +// `serialize_tuple_variant` method above: +// +// self.output += "{"; +// variant.serialize(&mut *self)?; +// self.output += ":["; +// +// So the `end` method in this impl is responsible for closing both the `]` and +// the `}`. +impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Some `Serialize` types are not able to hold a key and value in memory at the +// same time so `SerializeMap` implementations are required to support +// `serialize_key` and `serialize_value` individually. +// +// There is a third optional method on the `SerializeMap` trait. The +// `serialize_entry` method allows serializers to optimize for the case where +// key and value are both available simultaneously. In JSON it doesn't make a +// difference so the default behavior for `serialize_entry` is fine. +impl<'a> ser::SerializeMap for &'a mut Serializer { + type Ok = (); + type Error = Error; + + // The Serde data model allows map keys to be any serializable type. JSON + // only allows string keys so the implementation below will produce invalid + // JSON if the key serializes as something other than a string. + // + // A real JSON serializer would need to validate that map keys are strings. + // This can be done by using a different Serializer to serialize the key + // (instead of `&mut **self`) and having that other serializer only + // implement `serialize_str` and return an error on any other data type. + fn serialize_key(&mut self, _key: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!() + } + + // It doesn't make a difference whether the colon is printed at the end of + // `serialize_key` or at the beginning of `serialize_value`. In this case + // the code is a bit simpler having it here. + fn serialize_value(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!() + } + + fn end(self) -> Result<()> { + self.output.try_push(3).unwrap(); + Ok(()) + } +} + +// Structs are like maps in which the keys are constrained to be compile-time +// constant strings. +impl<'a> ser::SerializeStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + self.output.try_push(3).unwrap(); + Ok(()) + } +} + +// Similar to `SerializeTupleVariant`, here the `end` method is responsible for +// closing both of the curly braces opened by `serialize_struct_variant`. +impl<'a> ser::SerializeStructVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +#[test] +fn test_struct() { + use serde_derive::Serialize; + + #[derive(Serialize)] + struct Test { + a: (), + b: bool, + } + + let test = Test { + a: (), + b: false, + }; + + let mut expected = Vec::new(); + expected.try_push(2).unwrap(); + expected.try_push(0).unwrap(); + expected.try_push(1).unwrap(); + expected.try_push(0).unwrap(); + expected.try_push(3).unwrap(); + assert_eq!(to_vec(&test).unwrap(), expected); +} diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index b0f74a81c8f9ad..9151045ebbfe6a 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -30,6 +30,16 @@ config SAMPLE_RUST_PRINT If unsure, say N. +config SAMPLE_RUST_SERDE + tristate "Serde" + help + This option builds the Rust `serde` sample. + + To compile this as a module, choose M here: + the module will be called rust_serde. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 03086dabbea44f..11fc58df91f197 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o +obj-$(CONFIG_SAMPLE_RUST_SERDE) += rust_serde.o subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs diff --git a/samples/rust/local_data_format/de.rs b/samples/rust/local_data_format/de.rs new file mode 100644 index 00000000000000..32cfc53f98b3f8 --- /dev/null +++ b/samples/rust/local_data_format/de.rs @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::error::{Error, Result}; +use serde::de::{self, Deserialize, DeserializeSeed, SeqAccess, Visitor}; + +pub struct Deserializer<'de> { + // This string starts with the input data and characters are truncated off + // the beginning as data is parsed. + input: &'de [u8], +} + +impl<'de> Deserializer<'de> { + // By convention, `Deserializer` constructors are named like `from_xyz`. + // That way basic use cases are satisfied by something like + // `serde_json::from_str(...)` while advanced use cases that require a + // deserializer can make one with `serde_json::Deserializer::from_str(...)`. + #[allow(clippy::should_implement_trait)] + pub fn from_bytes(input: &'de [u8]) -> Self { + Deserializer { input } + } +} + +// By convention, the public API of a Serde deserializer is one or more +// `from_xyz` methods such as `from_str`, `from_bytes`, or `from_reader` +// depending on what Rust types the deserializer is able to consume as input. +// +// This basic deserializer supports only `from_str`. +pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_bytes(s); + let t = T::deserialize(&mut deserializer)?; + if deserializer.input.is_empty() { + Ok(t) + } else { + Err(Error::TrailingCharacters) + } +} + +// SERDE IS NOT A PARSING LIBRARY. This impl block defines a few basic parsing +// functions from scratch. More complicated formats may wish to use a dedicated +// parsing library to help implement their Serde deserializer. +impl<'de> Deserializer<'de> { + // Look at the first character in the input without consuming it. + fn peek_byte(&mut self) -> Result { + self.input.iter().next().ok_or(Error::Eof).map(|v| *v) + } + + // Consume the first character in the input. + fn next_byte(&mut self) -> Result { + let ch = self.peek_byte()?; + self.input = &self.input[1..]; + Ok(ch) + } + + // Parse the JSON identifier `true` or `false`. + fn parse_bool(&mut self) -> Result { + if self.input.starts_with(&[1]) { + self.input = &self.input[1..]; + match self.next_byte()? { + 42 => Ok(false), + 43 => Ok(true), + _ => Err(Error::InvalidBooleanValue), + } + } else { + Err(Error::ExpectedBoolean) + } + } + + // Parse a group of decimal digits as an unsigned integer of type T. + // + // This implementation is a bit too lenient, for example `001` is not + // allowed in JSON. Also the various arithmetic operations can overflow and + // panic or return bogus data. But it is good enough for example code! + fn parse_unsigned(&mut self) -> Result { + unimplemented!() + } + + // Parse a possible minus sign followed by a group of decimal digits as a + // signed integer of type T. + fn parse_signed(&mut self) -> Result { + // Optional minus sign, delegate to `parse_unsigned`, negate if negative. + unimplemented!() + } +} + +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + // Look at the input data to decide what Serde data model type to + // deserialize as. Not all data formats are able to support this operation. + // Formats that support `deserialize_any` are known as self-describing. + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek_byte()? { + 0 => self.deserialize_unit(visitor), + 1 => self.deserialize_bool(visitor), + 2 => self.deserialize_map(visitor), + _ => Err(Error::Syntax), + } + } + + // Uses the `parse_bool` parsing function defined above to read the JSON + // identifier `true` or `false` from the input. + // + // Parsing refers to looking at the input and deciding that it contains the + // JSON value `true` or `false`. + // + // Deserialization refers to mapping that JSON value into Serde's data + // model by invoking one of the `Visitor` methods. In the case of JSON and + // bool that mapping is straightforward so the distinction may seem silly, + // but in other cases Deserializers sometimes perform non-obvious mappings. + // For example the TOML format has a Datetime type and Serde's data model + // does not. In the `toml` crate, a Datetime in the input is deserialized by + // mapping it to a Serde data model "struct" type with a special name and a + // single field containing the Datetime represented as a string. + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_bool(self.parse_bool()?) + } + + // The `parse_signed` function is generic over the integer type `T` so here + // it is invoked with `T=i8`. The next 8 methods are similar. + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i8(self.parse_signed()?) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i16(self.parse_signed()?) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i32(self.parse_signed()?) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_i64(self.parse_signed()?) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u8(self.parse_unsigned()?) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u16(self.parse_unsigned()?) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u32(self.parse_unsigned()?) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_u64(self.parse_unsigned()?) + } + + // The `Serializer` implementation on the previous page serialized chars as + // single-character strings so handle that representation here. + fn deserialize_char(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // Refer to the "Understanding deserializer lifetimes" page for information + // about the three deserialization flavors of strings in Serde. + fn deserialize_str(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + fn deserialize_string(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // The `Serializer` implementation on the previous page serialized byte + // arrays as JSON arrays of bytes. Handle that representation here. + fn deserialize_bytes(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + fn deserialize_byte_buf(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // An absent optional is represented as the JSON `null` and a present + // optional is represented as just the contained value. + // + // As commented in `Serializer` implementation, this is a lossy + // representation. For example the values `Some(())` and `None` both + // serialize as just `null`. Unfortunately this is typically what people + // expect when working with JSON. Other formats are encouraged to behave + // more intelligently if possible. + fn deserialize_option(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // In Serde, unit means an anonymous value containing no data. + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + if self.input.starts_with(&[0]) { + self.input = &self.input[1..]; + visitor.visit_unit() + } else { + Err(Error::ExpectedNull) + } + } + + // Unit struct means a named value containing no data. + fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + // As is done here, serializers are encouraged to treat newtype structs as + // insignificant wrappers around the data they contain. That means not + // parsing anything other than the contained value. + fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + // Deserialization of compound types like sequences and maps happens by + // passing the visitor an "Access" object that gives it the ability to + // iterate through the data contained in the sequence. + fn deserialize_seq(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // Tuples look just like sequences in JSON. Some formats may be able to + // represent tuples more efficiently. + // + // As indicated by the length parameter, the `Deserialize` implementation + // for a tuple in the Serde data model is required to know the length of the + // tuple before even looking at the input data. + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + // Tuple structs look just like sequences in JSON. + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + // Much like `deserialize_seq` but calls the visitors `visit_map` method + // with a `MapAccess` implementation, rather than the visitor's `visit_seq` + // method with a `SeqAccess` implementation. + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // Parse the opening brace of the map. + if self.next_byte()? == 2 { + // Give the visitor access to each entry of the map. + let value = visitor.visit_seq(StructFieldsVisitor::new(self))?; + // Parse the closing brace of the map. + if self.next_byte()? == 3 { + Ok(value) + } else { + Err(Error::ExpectedMapEnd) + } + } else { + Err(Error::ExpectedMap) + } + } + + // Structs look just like maps in JSON. + // + // Notice the `fields` parameter - a "struct" in the Serde data model means + // that the `Deserialize` implementation is required to know what the fields + // are before even looking at the input data. Any key-value pairing in which + // the fields cannot be known ahead of time is probably a map. + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + unimplemented!() + } + + // An identifier in Serde is the type that identifies a field of a struct or + // the variant of an enum. In JSON, struct fields and enum variants are + // represented as strings. In other formats they may be represented as + // numeric indices. + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + // Like `deserialize_any` but indicates to the `Deserializer` that it makes + // no difference which `Visitor` method is called because the data is + // ignored. + // + // Some deserializers are able to implement this more efficiently than + // `deserialize_any`, for example by rapidly skipping over matched + // delimiters without paying close attention to the data in between. + // + // Some formats are not able to implement this at all. Formats that can + // implement `deserialize_any` and `deserialize_ignored_any` are known as + // self-describing. + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } +} + +struct StructFieldsVisitor<'a, 'de> { + de: &'a mut Deserializer<'de>, +} + +impl<'a, 'de> StructFieldsVisitor<'a, 'de> { + fn new(de: &'a mut Deserializer<'de>) -> Self { + StructFieldsVisitor { de } + } +} + +impl<'de, 'a> SeqAccess<'de> for StructFieldsVisitor<'a, 'de> { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: DeserializeSeed<'de>, + { + // Check if there are no more elements. + if self.de.peek_byte()? == 3 { + return Ok(None); + } + // Deserialize an array element. + seed.deserialize(&mut *self.de).map(Some) + } +} diff --git a/samples/rust/local_data_format/error.rs b/samples/rust/local_data_format/error.rs new file mode 100644 index 00000000000000..8d913580f71363 --- /dev/null +++ b/samples/rust/local_data_format/error.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::fmt::{self, Display}; +use serde::{de, ser}; + +pub type Result = kernel::error::Result; + +// This is a bare-bones implementation. A real library would provide additional +// information in its error type, for example the line and column at which the +// error occurred, the byte offset into the input, or the current key being +// processed. +#[derive(Debug)] +pub enum Error { + // One or more variants that can be created by data structures through the + // `ser::Error` and `de::Error` traits. For example the Serialize impl for + // Mutex might return an error because the mutex is poisoned, or the + // Deserialize impl for a struct may return an error because a required + // field is missing. + Message, + + // Zero or more variants that can be created directly by the Serializer and + // Deserializer without going through `ser::Error` and `de::Error`. These + // are specific to the format, in this case JSON. + Eof, + Syntax, + ExpectedBoolean, + InvalidBooleanValue, + ExpectedInteger, + ExpectedString, + ExpectedNull, + ExpectedArray, + ExpectedArrayComma, + ExpectedArrayEnd, + ExpectedMap, + ExpectedMapColon, + ExpectedMapComma, + ExpectedMapEnd, + ExpectedEnum, + TrailingCharacters, +} + +impl ser::Error for Error { + fn custom(_msg: T) -> Self { + Error::Message + } +} + +impl de::Error for Error { + fn custom(_msg: T) -> Self { + Error::Message + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Message => write!(f, "message"), + Error::Eof => f.write_str("unexpected end of input"), + /* and so forth */ + _ => unimplemented!(), + } + } +} + +//impl core::error::Error for Error {} diff --git a/samples/rust/local_data_format/ser.rs b/samples/rust/local_data_format/ser.rs new file mode 100644 index 00000000000000..f4f17eb6da66e6 --- /dev/null +++ b/samples/rust/local_data_format/ser.rs @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// Copyright 2018 Serde Developers +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::error::{Error, Result}; +use alloc::vec::Vec; +use serde::ser::{self, Serialize}; + +pub struct Serializer { + // This string starts empty and JSON is appended as values are serialized. + output: Vec, +} + +// By convention, the public API of a Serde serializer is one or more `to_abc` +// functions such as `to_string`, `to_bytes`, or `to_writer` depending on what +// Rust types the serializer is able to produce as output. +// +// This basic serializer supports only `to_string`. +pub fn to_vec(value: &T) -> Result> +where + T: Serialize, +{ + let mut serializer = Serializer { output: Vec::new() }; + value.serialize(&mut serializer)?; + Ok(serializer.output) +} + +impl<'a> ser::Serializer for &'a mut Serializer { + // The output type produced by this `Serializer` during successful + // serialization. Most serializers that produce text or binary output should + // set `Ok = ()` and serialize into an `io::Write` or buffer contained + // within the `Serializer` instance, as happens here. Serializers that build + // in-memory data structures may be simplified by using `Ok` to propagate + // the data structure around. + type Ok = (); + + // The error type when some error occurs during serialization. + type Error = Error; + + // Associated types for keeping track of additional state while serializing + // compound data structures like sequences and maps. In this case no + // additional state is required beyond what is already stored in the + // Serializer struct. + type SerializeSeq = Self; + type SerializeTuple = Self; + type SerializeTupleStruct = Self; + type SerializeTupleVariant = Self; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + // Here we go with the simple methods. The following 12 methods receive one + // of the primitive types of the data model and map it to JSON by appending + // into the output string. + fn serialize_bool(self, v: bool) -> Result<()> { + self.output.try_push(1).unwrap(); + self.output.try_push(if v { 43 } else { 42 }).unwrap(); + Ok(()) + } + + // JSON does not distinguish between different sizes of integers, so all + // signed integers will be serialized the same and all unsigned integers + // will be serialized the same. Other formats, especially compact binary + // formats, may need independent logic for the different sizes. + fn serialize_i8(self, v: i8) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i16(self, v: i16) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + fn serialize_i32(self, v: i32) -> Result<()> { + self.serialize_i64(i64::from(v)) + } + + // Not particularly efficient but this is example code anyway. A more + // performant approach would be to use the `itoa` crate. + fn serialize_i64(self, _v: i64) -> Result<()> { + unimplemented!(); + } + + fn serialize_u8(self, v: u8) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u16(self, v: u16) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u32(self, v: u32) -> Result<()> { + self.serialize_u64(u64::from(v)) + } + + fn serialize_u64(self, _v: u64) -> Result<()> { + unimplemented!(); + } + + // Serialize a char as a single-character string. Other formats may + // represent this differently. + fn serialize_char(self, _v: char) -> Result<()> { + unimplemented!(); + } + + // This only works for strings that don't require escape sequences but you + // get the idea. For example it would emit invalid JSON if the input string + // contains a '"' character. + fn serialize_str(self, _v: &str) -> Result<()> { + unimplemented!(); + } + + // Serialize a byte array as an array of bytes. Could also use a base64 + // string here. Binary formats will typically represent byte arrays more + // compactly. + fn serialize_bytes(self, v: &[u8]) -> Result<()> { + use serde::ser::SerializeSeq; + let mut seq = self.serialize_seq(Some(v.len()))?; + for byte in v { + seq.serialize_element(byte)?; + } + seq.end() + } + + // An absent optional is represented as the JSON `null`. + fn serialize_none(self) -> Result<()> { + self.serialize_unit() + } + + // A present optional is represented as just the contained value. Note that + // this is a lossy representation. For example the values `Some(())` and + // `None` both serialize as just `null`. Unfortunately this is typically + // what people expect when working with JSON. Other formats are encouraged + // to behave more intelligently if possible. + fn serialize_some(self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + // In Serde, unit means an anonymous value containing no data. Map this to + // JSON as `null`. + fn serialize_unit(self) -> Result<()> { + self.output.try_push(0).unwrap(); + Ok(()) + } + + // Unit struct means a named value containing no data. Again, since there is + // no data, map this to JSON as `null`. There is no need to serialize the + // name in most formats. + fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { + self.serialize_unit() + } + + // When serializing a unit variant (or any other kind of variant), formats + // can choose whether to keep track of it by index or by name. Binary + // formats typically use the index of the variant and human-readable formats + // typically use the name. + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<()> { + self.serialize_str(variant) + } + + // As is done here, serializers are encouraged to treat newtype structs as + // insignificant wrappers around the data they contain. + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + // Note that newtype variant (and all of the other variant serialization + // methods) refer exclusively to the "externally tagged" enum + // representation. + // + // Serialize this to JSON in externally tagged form as `{ NAME: VALUE }`. + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + // Now we get to the serialization of compound types. + // + // The start of the sequence, each value, and the end are three separate + // method calls. This one is responsible only for serializing the start, + // which in JSON is `[`. + // + // The length of the sequence may or may not be known ahead of time. This + // doesn't make a difference in JSON because the length is not represented + // explicitly in the serialized form. Some serializers may only be able to + // support sequences for which the length is known up front. + fn serialize_seq(self, _len: Option) -> Result { + unimplemented!(); + } + + // Tuples look just like sequences in JSON. Some formats may be able to + // represent tuples more efficiently by omitting the length, since tuple + // means that the corresponding `Deserialize implementation will know the + // length without needing to look at the serialized data. + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + // Tuple structs look just like sequences in JSON. + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + // Tuple variants are represented in JSON as `{ NAME: [DATA...] }`. Again + // this method is only responsible for the externally tagged representation. + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + unimplemented!(); + } + + // Maps are represented in JSON as `{ K: V, K: V, ... }`. + fn serialize_map(self, _len: Option) -> Result { + self.output.try_push(2).unwrap(); + Ok(self) + } + + // Structs look just like maps in JSON. In particular, JSON requires that we + // serialize the field names of the struct. Other formats may be able to + // omit the field names when serializing structs because the corresponding + // Deserialize implementation is required to know what the keys are without + // looking at the serialized data. + fn serialize_struct(self, _name: &'static str, len: usize) -> Result { + self.serialize_map(Some(len)) + } + + // Struct variants are represented in JSON as `{ NAME: { K: V, ... } }`. + // This is the externally tagged representation. + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + unimplemented!(); + } + + fn collect_str(self, _: &T) -> Result<()> + where + T: core::fmt::Display, + { + unimplemented!() + } +} + +// The following 7 impls deal with the serialization of compound types like +// sequences and maps. Serialization of such types is begun by a Serializer +// method and followed by zero or more calls to serialize individual elements of +// the compound type and one call to end the compound type. +// +// This impl is SerializeSeq so these methods are called after `serialize_seq` +// is called on the Serializer. +impl<'a> ser::SerializeSeq for &'a mut Serializer { + // Must match the `Ok` type of the serializer. + type Ok = (); + // Must match the `Error` type of the serializer. + type Error = Error; + + // Serialize a single element of the sequence. + fn serialize_element(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + // Close the sequence. + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Same thing but for tuples. +impl<'a> ser::SerializeTuple for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Same thing but for tuple structs. +impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Tuple variants are a little different. Refer back to the +// `serialize_tuple_variant` method above: +// +// self.output += "{"; +// variant.serialize(&mut *self)?; +// self.output += ":["; +// +// So the `end` method in this impl is responsible for closing both the `]` and +// the `}`. +impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} + +// Some `Serialize` types are not able to hold a key and value in memory at the +// same time so `SerializeMap` implementations are required to support +// `serialize_key` and `serialize_value` individually. +// +// There is a third optional method on the `SerializeMap` trait. The +// `serialize_entry` method allows serializers to optimize for the case where +// key and value are both available simultaneously. In JSON it doesn't make a +// difference so the default behavior for `serialize_entry` is fine. +impl<'a> ser::SerializeMap for &'a mut Serializer { + type Ok = (); + type Error = Error; + + // The Serde data model allows map keys to be any serializable type. JSON + // only allows string keys so the implementation below will produce invalid + // JSON if the key serializes as something other than a string. + // + // A real JSON serializer would need to validate that map keys are strings. + // This can be done by using a different Serializer to serialize the key + // (instead of `&mut **self`) and having that other serializer only + // implement `serialize_str` and return an error on any other data type. + fn serialize_key(&mut self, _key: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!() + } + + // It doesn't make a difference whether the colon is printed at the end of + // `serialize_key` or at the beginning of `serialize_value`. In this case + // the code is a bit simpler having it here. + fn serialize_value(&mut self, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!() + } + + fn end(self) -> Result<()> { + self.output.try_push(3).unwrap(); + Ok(()) + } +} + +// Structs are like maps in which the keys are constrained to be compile-time +// constant strings. +impl<'a> ser::SerializeStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + value.serialize(&mut **self) + } + + fn end(self) -> Result<()> { + self.output.try_push(3).unwrap(); + Ok(()) + } +} + +// Similar to `SerializeTupleVariant`, here the `end` method is responsible for +// closing both of the curly braces opened by `serialize_struct_variant`. +impl<'a> ser::SerializeStructVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + unimplemented!(); + } + + fn end(self) -> Result<()> { + unimplemented!(); + } +} diff --git a/samples/rust/rust_serde.rs b/samples/rust/rust_serde.rs new file mode 100644 index 00000000000000..3d4957dd082209 --- /dev/null +++ b/samples/rust/rust_serde.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust `serde` sample. +//! +//! It uses a data format from the `kernel` crate, as well as defining +//! one here ("local"). Then it uses both on a type that uses `serve_derive`. + +use kernel::prelude::*; +use serde_derive::{Deserialize, Serialize}; + +module! { + type: RustSerde, + name: "rust_serde", + author: "Rust for Linux Contributors", + description: "Rust `serde` sample", + license: "GPL", +} + +struct RustSerde; + +pub mod local_data_format { + #![allow(missing_docs)] + + mod de; + mod error; + mod ser; + + pub use de::{from_bytes, Deserializer}; + pub use error::{Error, Result}; + pub use ser::{to_vec, Serializer}; +} + +#[derive(Serialize, Deserialize, Debug)] +struct S { + a: (), + b: bool, + c: bool, + d: (), +} + +impl kernel::Module for RustSerde { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("Rust serde sample (init)\n"); + + let original = S { + a: (), + b: false, + c: true, + d: (), + }; + crate::pr_info!(" original = {:?}", original); + + let serialized = kernel::test_serde::to_vec(&original).unwrap(); + crate::pr_info!(" serialized = {:?}", serialized); + + let deserialized: S = kernel::test_serde::from_bytes(&serialized).unwrap(); + crate::pr_info!(" deserialized = {:?}", deserialized); + + let serialized = local_data_format::to_vec(&deserialized).unwrap(); + crate::pr_info!(" serialized (local) = {:?}", serialized); + + let deserialized: S = local_data_format::from_bytes(&serialized).unwrap(); + crate::pr_info!("deserialized (local) = {:?}", deserialized); + + Ok(RustSerde) + } +} + +impl Drop for RustSerde { + fn drop(&mut self) { + pr_info!("Rust serde sample (exit)\n"); + } +}