1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use {Error, Parcel, Settings}; use hint; use std::io::prelude::*; use std::fmt; /// A high level abstraction over a lower-level `Parcel`. /// /// Automatically marshals values to and from the high level /// and low level types for serialization. /// /// # Example /// /// ``` /// #[macro_use] extern crate protocol_derive; /// extern crate protocol; /// /// use protocol::Parcel; /// /// #[derive(Protocol)] /// pub struct RawPacket { /// opcode: u8, /// magic_number: u8, /// payload: Vec<u8>, /// version: (u8, u8), /// } /// /// #[derive(Debug, Clone)] /// pub enum Login { /// Success { /// message: String, /// }, /// Failure { /// code: FailureCode, /// response: String, /// }, /// } /// /// impl protocol::HighLevel for Login { /// type LowLevel = RawPacket; /// /// fn into_low_level(self) -> RawPacket { /// match self { /// Login::Success { message } => { /// RawPacket { /// opcode: 0, /// magic_number: 0xaa, /// payload: message.into_bytes(), /// version: (11, 0), /// } /// }, /// Login::Failure { .. } => unimplemented!(), /// } /// } /// /// fn from_low_level(low_level: RawPacket, /// _: &mut std::io::Read, /// _: &protocol::Settings, /// _: &mut protocol::hint::Hints) /// -> Result<Self, protocol::Error> { /// match low_level.opcode { /// 0 => Ok(Login::Success { message: String::from_utf8(low_level.payload).unwrap() }), /// 1 => Ok(Login::Failure { /// code: FailureCode::MyDogAteMyHomework, /// response: String::from_utf8(low_level.payload[1..].to_owned()).unwrap() }), /// _ => unreachable!(), /// } /// } /// } /// /// #[derive(Debug, Clone)] /// pub enum FailureCode { /// MyDogAteMyHomework, /// } /// /// let high_level = Login::Success { message: "Hi!".to_owned() }; /// assert_eq!(11, high_level.raw_bytes(&protocol::Settings::default()).unwrap().len()); /// ``` pub trait HighLevel : Clone + fmt::Debug { /// The lower-level representation of this type. type LowLevel: Parcel; /// Converts this high level type into its lower-level representation. fn into_low_level(self) -> Self::LowLevel; /// Creates a high-level abstraction over a lower-level value. /// /// The method has access to the reader post-parsing of the low level type. /// It is not necessary to use this if not needed. fn from_low_level(value: Self::LowLevel, subsequent_reader: &mut Read, settings: &Settings, hints: &mut hint::Hints) -> Result<Self, Error>; } impl<H> Parcel for H where H: HighLevel { const TYPE_NAME: &'static str = "HighLevel"; fn read_field(read: &mut Read, settings: &Settings, hints: &mut hint::Hints) -> Result<Self, Error> { let low_level = H::LowLevel::read_field(read, settings, hints)?; H::from_low_level(low_level, read, settings, hints) } fn write_field(&self, write: &mut Write, settings: &Settings, hints: &mut hint::Hints) -> Result<(), Error> { let low_level = self.clone().into_low_level(); low_level.write_field(write, settings, hints) } }