Created
January 4, 2026 00:56
-
-
Save charmoniumQ/a4980e06fca3ee3a8ad9ae92a48c3c98 to your computer and use it in GitHub Desktop.
Test serde deserialize with explicit discriminants
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*! | |
| * This module tests whether it would be possible to use serde to deserialize an enum with explicit discriminants, e.g., `enum Test { A = 20 }`. | |
| * I currently don't see a way to access the fact that 20 maps to `Test::A` from within Serde's datamodel. | |
| * | |
| * To test, start a new Rust project, `cargo add serde --features derive`, copy this file, and run `cargo test`. | |
| * | |
| * Also see <https://github.com/serde-rs/serde/issues/2763> | |
| * */ | |
| use serde::{Deserialize, de::IntoDeserializer}; | |
| /** | |
| * Test whether we can deserialize bytes into Test::A. | |
| * It works if you delete the explicit dscriminant assignment (` = 20`) and fails otherwise with stdout: | |
| * | |
| * Error: Error("invalid value: integer `20`, expected variant index 0 <= i < 1") | |
| * */ | |
| #[test] | |
| fn test_int_enum() -> Result<(), Box<dyn std::error::Error>> { | |
| #[derive(PartialEq, Eq, Debug, Clone, serde::Deserialize)] | |
| enum Test { | |
| A = 20, | |
| } | |
| let mut deserializer = MyDeserializer { | |
| bytes: vec![Test::A as u64], | |
| cursor: 0, | |
| }; | |
| let parsed_value = Test::deserialize(&mut deserializer)?; | |
| assert_eq!(parsed_value, Test::A); | |
| Ok(()) | |
| } | |
| /** | |
| * An example that deserializes structured data from a buffer of integers. | |
| * */ | |
| struct MyDeserializer { | |
| bytes: Vec<u64>, | |
| cursor: usize, | |
| } | |
| impl<'de> serde::Deserializer<'de> for &'de mut MyDeserializer { | |
| type Error = serde::de::value::Error; | |
| /** | |
| * For the sake of minimality, none of the methods other than deserialize_enum are actually implemented. | |
| * */ | |
| fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> | |
| where | |
| V: serde::de::Visitor<'de>, | |
| { | |
| unimplemented!("any"); | |
| } | |
| fn deserialize_enum<V>( | |
| self, | |
| _name: &'static str, | |
| _variants: &'static [&'static str], | |
| visitor: V, | |
| ) -> Result<V::Value, Self::Error> | |
| where | |
| V: serde::de::Visitor<'de>, | |
| { | |
| visitor.visit_enum(self) | |
| } | |
| serde::forward_to_deserialize_any! { | |
| bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string | |
| bytes byte_buf option unit unit_struct newtype_struct seq tuple | |
| tuple_struct map struct identifier ignored_any | |
| } | |
| } | |
| /** | |
| * Proper style may dictate using a new struct that implements EnumAccess. | |
| * But we can just reuse thes same MyDeserializer struct. | |
| * */ | |
| impl<'de> serde::de::EnumAccess<'de> for &'de mut MyDeserializer { | |
| type Error = serde::de::value::Error; | |
| type Variant = &'de mut MyDeserializer; | |
| fn variant_seed<V>( | |
| self, | |
| seed: V, | |
| ) -> Result<(<V as serde::de::DeserializeSeed<'de>>::Value, Self::Variant), Self::Error> | |
| where | |
| V: serde::de::DeserializeSeed<'de>, | |
| { | |
| let tag = self.bytes[self.cursor]; | |
| self.cursor += 1; | |
| Ok(( | |
| seed.deserialize(tag.into_deserializer())?, | |
| self, | |
| )) | |
| } | |
| } | |
| impl<'de> serde::de::VariantAccess<'de> for &'de mut MyDeserializer { | |
| type Error = serde::de::value::Error; | |
| fn unit_variant(self) -> Result<(), Self::Error> { | |
| Ok(()) | |
| } | |
| fn newtype_variant_seed<T>( | |
| self, | |
| _seed: T, | |
| ) -> Result<<T as serde::de::DeserializeSeed<'de>>::Value, Self::Error> | |
| where | |
| T: serde::de::DeserializeSeed<'de>, | |
| { | |
| unimplemented!("newtype_variant_seed"); | |
| } | |
| fn tuple_variant<V>( | |
| self, | |
| _len: usize, | |
| _visitor: V, | |
| ) -> Result<<V as serde::de::Visitor<'de>>::Value, Self::Error> | |
| where | |
| V: serde::de::Visitor<'de>, | |
| { | |
| unimplemented!("tuple_variant"); | |
| } | |
| fn struct_variant<V>( | |
| self, | |
| _fields: &'static [&'static str], | |
| _visitor: V, | |
| ) -> Result<<V as serde::de::Visitor<'de>>::Value, Self::Error> | |
| where | |
| V: serde::de::Visitor<'de>, | |
| { | |
| unimplemented!("struct_variant"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment