2017-10-06 7 views
1

J'ai besoin d'une fonction qui retourne le nom d'un type, j'ai cette fonction qui fonctionne en utilisant serde, mais maintenant j'ai besoin d'une version alternative qui ne nécessite pas le tapez pour être Deserialize afin que je puisse l'utiliser sur des structures qui ont des membres emprunteurs. Comment puis-je réécrire cette fonction pour qu'elle fonctionne lorsque le type est Serialize, mais pas Deserialize?Utilisation de serde pour obtenir le nom d'un type en tant que chaîne quand le type est seulement Serialize

#[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.

+0

On dirait que ce serait beaucoup plus facile d'écrire votre propre macro procédure et l'appliquer à vos types, tant que vous avez seulement besoin du nom de struct que vous contrôlez. – Shepmaster

Répondre

1

Voici une Serializer qui prend le nom d'une struct/unité struct/struct newtype/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))); 
} 
+0

Merci! Btw, pouvez-vous le faire fonctionner pour enums, aussi? :) –