2016-10-26 10 views
4

Я реализую Serde Serializer trait, который имеет много методов. Многие из них выглядят очень похожими (например, для целых типов просто копируют байты в некоторый буфер), поэтому было бы неплохо их сгенерировать. Могу ли я написать некоторую общую функцию или макрос, чтобы реализовать многие из них одним методом (макросом)?Как реализовать много похожих методов для определения?

У меня есть что-то вроде этого:

use serde::Serializer; 
use byteorder::{WriteBytesExt, LittleEndian}; 

struct MySerializer { 
    ... 
} 

impl Serializer for MySerializer { 
    fn serialize_i32(&mut self, v:i32) -> Result<(), Error> { 
     try!(self.buffer.write_i32::<LittleEndian>(v)); 
    } 
    fn serialize_u8(&mut self, v:u8) -> Result<(), Error> { 
     try!(self.buffer.write_u8::<LittleEndian>(v)); 
    } 
    // many similar looking functions here 
} 
+0

Rust _does_ поддержка общего программирования: https://doc.rust-lang.org/book/generics.html – gbe

+1

@gbe Конечно, я знаю, что это так. Однако мне не нужны только дженерики, мне нужно генерировать новые функции с новыми идентификаторами (именами). Мое настоящее понимание заключается в том, что теперь это, к сожалению, невозможно, потому что правила макроса ржавчины не позволяют генерировать новые идентификаторы. –

ответ

0

я нашел и пример в serde/bench проекта:

macro_rules! impl_nums { 
    ($ty:ty, $dser_method:ident, $visitor_method:ident, $reader_method:ident) => { 
     #[inline] 
     fn $dser_method<V>(&mut self, mut visitor: V) -> Result<V::Value> 
      where V: Visitor 
     { 
      let value = try!(self.reader.$reader_method::<NativeEndian>()); 
      visitor.$visitor_method(value) 
     } 
    }; 
} 

impl_nums!(u16, deserialize_u16, visit_u16, read_u16); 
impl_nums!(u32, deserialize_u32, visit_u32, read_u32); 
.... 

Похоже, сейчас это самый лучший способ сделать это - concat_idents! макросъемки нестабилен и не очень полезен по сравнению с this github issue.