Peter Foxworth
Peter Foxworth

Reputation: 83

Using serde to get a type's name as String when the type is only Serialize

I need a function that returns a type's name, I have this function which works using serde, but now I need an alternative version that doesn't require the type to be Deserialize so that I can use it on structs that have borrowing members.

How can I rewrite this function so that it works when the type is Serialize, but not Deserialize?

#[macro_use]
extern crate serde;

#[macro_use]
extern crate serde_derive;

use serde::de::{self, Deserialize, Deserializer, Visitor};
use std::fmt::{self, Display};

fn type_name<'de, D: Deserialize<'de>>() -> &'static str {
    #[derive(Debug)]
    struct NoError;
    impl std::error::Error for NoError {
        fn description(&self) -> &str {
            "no error"
        }
    }

    impl Display for NoError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "NoError")
        }
    }

    impl de::Error for NoError {
        fn custom<T: Display>(_msg: T) -> Self {
            NoError
        }
    }

    struct NameDeserializer(Option<&'static str>);
    impl<'a, 'de> Deserializer<'de> for &'a mut NameDeserializer {
        type Error = NoError;
        fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
            where V: Visitor<'de>
        {
            Err(NoError)
        }
        fn deserialize_unit_struct<V>(self, name: &'static str, _visitor: V) -> Result<V::Value, Self::Error>
            where V: Visitor<'de>
        {
            self.0 = Some(name);
            Err(NoError)
        }
        fn deserialize_newtype_struct<V>(self, name: &'static str, _visitor: V) -> Result<V::Value, Self::Error>
            where V: Visitor<'de>
        {
            self.0 = Some(name);
            Err(NoError)
        }
        fn deserialize_tuple_struct<V>(self, name: &'static str, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
            where V: Visitor<'de>
        {
            self.0 = Some(name);
            Err(NoError)
        }
        fn deserialize_struct<V>(self, name: &'static str, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value, Self::Error>
            where V: Visitor<'de>
        {
            self.0 = Some(name);
            Err(NoError)
        }
        forward_to_deserialize_any! {
            bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
            byte_buf option unit seq tuple map enum identifier ignored_any
        }
    }

    let mut deserializer = NameDeserializer(None);
    let _ = D::deserialize(&mut deserializer);
    deserializer.0.unwrap()
}

#[derive(Serialize, Deserialize)]
struct Vec2(f32, f32);

fn main() {
    println!("{}", type_name::<Vec2>());
}

Here is a playground link.

Upvotes: 6

Views: 2485

Answers (1)

dtolnay
dtolnay

Reputation: 11033

Here is a Serializer that picks out the name of any struct / unit struct / newtype struct / tuple struct.


extern crate serde;

#[macro_use]
extern crate serde_derive;

use serde::ser::{self, Serialize, Serializer, SerializeStruct, SerializeTupleStruct, Impossible};
use std::fmt::{self, Display};

fn type_name<T: Serialize>(t: &T) -> &'static str {
    #[derive(Debug)]
    struct NotStruct;
    type Result<T> = std::result::Result<T, NotStruct>;
    impl std::error::Error for NotStruct {
        fn description(&self) -> &str { "not struct" }
    }
    impl Display for NotStruct {
        fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result { unimplemented!() }
    }
    impl ser::Error for NotStruct {
        fn custom<T: Display>(_msg: T) -> Self { NotStruct }
    }

    struct TypeName;
    impl Serializer for TypeName {
        type Ok = &'static str;
        type Error = NotStruct;
        type SerializeSeq = Impossible<Self::Ok, Self::Error>;
        type SerializeTuple = Impossible<Self::Ok, Self::Error>;
        type SerializeTupleStruct = Struct;
        type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
        type SerializeMap = Impossible<Self::Ok, Self::Error>;
        type SerializeStruct = Struct;
        type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
        fn serialize_bool(self, _v: bool) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_i8(self, _v: i8) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_i16(self, _v: i16) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_i32(self, _v: i32) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_i64(self, _v: i64) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_u8(self, _v: u8) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_u16(self, _v: u16) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_u32(self, _v: u32) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_u64(self, _v: u64) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_f32(self, _v: f32) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_f64(self, _v: f64) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_char(self, _v: char) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_str(self, _v: &str) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_none(self) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_some<T: ?Sized + Serialize>(self, _value: &T) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_unit(self) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
            Ok(name)
        }
        fn serialize_unit_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_newtype_struct<T: ?Sized + Serialize>(self, name: &'static str, _value: &T) -> Result<Self::Ok> {
            Ok(name)
        }
        fn serialize_newtype_variant<T: ?Sized + Serialize>(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _value: &T) -> Result<Self::Ok> { Err(NotStruct) }
        fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> { Err(NotStruct) }
        fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> { Err(NotStruct) }
        fn serialize_tuple_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
            Ok(Struct(name))
        }
        fn serialize_tuple_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant> { Err(NotStruct) }
        fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> { Err(NotStruct) }
        fn serialize_struct(self, name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
            Ok(Struct(name))
        }
        fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant> { Err(NotStruct) }
    }

    struct Struct(&'static str);
    impl SerializeStruct for Struct {
        type Ok = &'static str;
        type Error = NotStruct;
        fn serialize_field<T: ?Sized + Serialize>(&mut self, _key: &'static str, _value: &T) -> Result<()> { Ok(()) }
        fn end(self) -> Result<Self::Ok> {
            Ok(self.0)
        }
    }
    impl SerializeTupleStruct for Struct {
        type Ok = &'static str;
        type Error = NotStruct;
        fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<()> { Ok(()) }
        fn end(self) -> Result<Self::Ok> {
            Ok(self.0)
        }
    }

    t.serialize(TypeName).unwrap()
}

#[derive(Serialize)]
struct Vec2(f32, f32);

fn main() {
    println!("{}", type_name(&Vec2(0.0, 0.0)));
}

Upvotes: 6

Related Questions