From 7bb290f0ef0e0465822cd47ecbf7f07f609d89ad Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Sun, 14 Jun 2020 20:45:38 +0000 Subject: [PATCH] Introduce ProtoEncodeError and use it in ProtoEncoder. Tests are not fixed yet. --- src/proto/base_codec.rs | 128 ++++++++++++++++++++++------------- src/proto/codec.rs | 19 +++--- src/proto/mod.rs | 3 +- src/proto/peer/message.rs | 6 +- src/proto/server/request.rs | 26 +++---- src/proto/server/response.rs | 66 +++++++++--------- src/proto/user.rs | 4 +- 7 files changed, 148 insertions(+), 104 deletions(-) diff --git a/src/proto/base_codec.rs b/src/proto/base_codec.rs index b9bcc55..3763e44 100644 --- a/src/proto/base_codec.rs +++ b/src/proto/base_codec.rs @@ -299,96 +299,130 @@ impl ProtoDecode for Vec { } } +#[derive(Debug, Error, PartialEq)] +pub enum ProtoEncodeError { + #[error("encoded string length {length} is too large: {string:?}")] + StringTooLong { + /// The string that is too long to encode. + string: String, + + /// The length of `string` in the Windows-1252 encoding. + /// Always larger than `u32::max_value()`. + length: usize, + }, +} + +impl From for io::Error { + fn from(error: ProtoEncodeError) -> Self { + io::Error::new(io::ErrorKind::InvalidData, format!("{}", error)) + } +} + /// A type for encoding various types of values into protocol messages. pub struct ProtoEncoder<'a> { - inner: &'a mut BytesMut, + /// The buffer to which the encoder appends encoded bytes. + buffer: &'a mut Vec, } /// This trait is implemented by types that can be encoded into messages using /// a `ProtoEncoder`. pub trait ProtoEncode { + // TODO: Rename to encode_to(). /// Attempts to encode `self` with the given encoder. - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()>; + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError>; } impl<'a> ProtoEncoder<'a> { /// Wraps the given buffer for encoding values into. /// - /// The buffer is grown as required. - pub fn new(inner: &'a mut BytesMut) -> Self { - ProtoEncoder { inner: inner } + /// Encoded bytes are appended. The buffer is not pre-cleared. + pub fn new(buffer: &'a mut Vec) -> Self { + ProtoEncoder { buffer: buffer } } - /// Attempts to encode the given u32 value. - pub fn encode_u32(&mut self, val: u32) -> io::Result<()> { - self.inner.reserve(U32_BYTE_LEN); - self.inner.put_u32_le(val); + /// Encodes the given u32 value into the underlying buffer. + pub fn encode_u32(&mut self, val: u32) -> Result<(), ProtoEncodeError> { + self.buffer.extend_from_slice(&val.to_le_bytes()); Ok(()) } - /// Attempts to encode the given boolean value. - pub fn encode_bool(&mut self, val: bool) -> io::Result<()> { - self.inner.reserve(1); - self.inner.put_u8(val as u8); - Ok(()) + /// Encodes the given u16 value into the underlying buffer. + pub fn encode_u16(&mut self, val: u16) -> Result<(), ProtoEncodeError> { + self.encode_u32(val as u32) } - /// Attempts to encode the given IPv4 address. - pub fn encode_ipv4_addr(&mut self, addr: net::Ipv4Addr) -> io::Result<()> { - let mut octets = addr.octets(); - octets.reverse(); // Little endian. - self.inner.extend(&octets); + /// Encodes the given boolean value into the underlying buffer. + pub fn encode_bool(&mut self, val: bool) -> Result<(), ProtoEncodeError> { + self.buffer.push(val as u8); Ok(()) } - /// Attempts to encode the given string. - pub fn encode_string(&mut self, val: &str) -> io::Result<()> { - // Encode the string. - let bytes = match WINDOWS_1252.encode(val, EncoderTrap::Strict) { - Ok(bytes) => bytes, + /// Encodes the given string into the underlying buffer. + pub fn encode_string(&mut self, val: &str) -> Result<(), ProtoEncodeError> { + // Record where we were when we started. This is where we will write + // the length prefix once we are done encoding the string. Until then + // we do not know how many bytes are needed to encode the string. + let prefix_position = self.buffer.len(); + self.buffer.extend_from_slice(&[0; U32_BYTE_LEN]); + let string_position = prefix_position + U32_BYTE_LEN; + + // Encode the string. We are quite certain this cannot fail because we + // use EncoderTrap::Replace to replace any unencodable characters with + // '?' which is always encodable in Windows-1252. + WINDOWS_1252 + .encode_to(val, EncoderTrap::Replace, self.buffer) + .unwrap(); + + // Calculate the length of the string we just encoded. + let length = self.buffer.len() - string_position; + let length_u32 = match u32::try_from(length) { + Ok(value) => value, Err(_) => { - return Err(io::Error::new(io::ErrorKind::InvalidData, val.to_string())); + return Err(ProtoEncodeError::StringTooLong { + string: val.to_string(), + length: length, + }) } }; - // Prefix the bytes with the length. - self.encode_u32(bytes.len() as u32)?; - self.inner.extend(bytes); + + // Write the length prefix in the space we initially reserved for it. + self.buffer[prefix_position..string_position].copy_from_slice(&length_u32.to_le_bytes()); + Ok(()) } - /// Attempts to encode the given value. + /// Encodes the given value into the underlying buffer. /// /// Allows for easy encoding with type inference: /// ``` - /// let val : Foo = Foo::new(bar); - /// encoder.encode(&val)?; + /// encoder.encode(&Foo::new(bar))?; /// ``` - pub fn encode(&mut self, val: &T) -> io::Result<()> { + pub fn encode(&mut self, val: &T) -> Result<(), ProtoEncodeError> { val.encode(self) } } impl ProtoEncode for u32 { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(*self) } } -impl ProtoEncode for bool { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { - encoder.encode_bool(*self) +impl ProtoEncode for u16 { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { + encoder.encode_u16(*self) } } -impl ProtoEncode for u16 { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { - encoder.encode_u32(*self as u32) +impl ProtoEncode for bool { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { + encoder.encode_bool(*self) } } impl ProtoEncode for net::Ipv4Addr { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { - encoder.encode_ipv4_addr(*self) + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { + encoder.encode_u32(u32::from(*self)) } } @@ -401,32 +435,32 @@ impl ProtoEncode for net::Ipv4Addr { // Proto{De,En}code) but it is not really worth the hassle. impl ProtoEncode for str { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(self) } } impl ProtoEncode for String { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(self) } } impl<'a> ProtoEncode for &'a String { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(*self) } } impl ProtoEncode for (T, U) { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { self.0.encode(encoder)?; self.1.encode(encoder) } } impl ProtoEncode for [T] { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.len() as u32)?; for ref item in self { item.encode(encoder)?; @@ -436,7 +470,7 @@ impl ProtoEncode for [T] { } impl ProtoEncode for Vec { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { let slice: &[T] = &*self; slice.encode(encoder) } diff --git a/src/proto/codec.rs b/src/proto/codec.rs index cf6980e..91022a3 100644 --- a/src/proto/codec.rs +++ b/src/proto/codec.rs @@ -9,6 +9,8 @@ //! This enables wrapping AsyncRead and AsyncWrite objects into Stream and Sink //! objects using tokio_codec's FramedRead and FramedWrite adapters. +// TODO: Refactor all this into futures and remove tokio dependency. + use std::io; use std::marker; @@ -37,18 +39,19 @@ impl tokio_codec::Encoder for LengthPrefixedEncoder { type Error = io::Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { - // Split buffer into two parts: the length prefix and the message. - dst.reserve(U32_BYTE_LEN); - let mut msg_dst = dst.split_off(U32_BYTE_LEN); - // Encode the message. - item.encode(&mut ProtoEncoder::new(&mut msg_dst))?; + // Note that this is ugly right now, but will get better once we switch + // off of Tokio and onto regular futures. + let mut buffer = vec![]; + ProtoEncoder::new(&mut buffer).encode(&item)?; // Encode the message length. - ProtoEncoder::new(dst).encode_u32(msg_dst.len() as u32)?; + let mut prefix = vec![]; + ProtoEncoder::new(&mut prefix).encode_u32(buffer.len() as u32)?; - // Reassemble both parts into one contiguous buffer. - dst.unsplit(msg_dst); + dst.reserve(prefix.len() + buffer.len()); + dst.extend_from_slice(&prefix); + dst.extend_from_slice(&buffer); Ok(()) } } diff --git a/src/proto/mod.rs b/src/proto/mod.rs index 4a28178..c68a585 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -9,7 +9,8 @@ mod stream; mod user; pub use self::base_codec::{ - Decode, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncoder, + Decode, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncodeError, + ProtoEncoder, }; pub use self::codec::*; pub use self::handler::*; diff --git a/src/proto/peer/message.rs b/src/proto/peer/message.rs index 3ed5e35..a797c0f 100644 --- a/src/proto/peer/message.rs +++ b/src/proto/peer/message.rs @@ -3,7 +3,7 @@ use std::io; use crate::proto::peer::constants::*; use crate::proto::{ MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, - ProtoEncoder, ReadFromPacket, WriteToPacket, + ProtoEncodeError, ProtoEncoder, ReadFromPacket, WriteToPacket, }; /*=========* @@ -67,7 +67,7 @@ impl ProtoDecode for Message { } impl ProtoEncode for Message { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { match *self { Message::PierceFirewall(token) => { encoder.encode_u32(CODE_PIERCE_FIREWALL)?; @@ -132,7 +132,7 @@ impl WriteToPacket for PeerInit { } impl ProtoEncode for PeerInit { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.user_name)?; encoder.encode_string(&self.connection_type)?; encoder.encode_u32(self.token)?; diff --git a/src/proto/server/request.rs b/src/proto/server/request.rs index ea58e5a..6d66f93 100644 --- a/src/proto/server/request.rs +++ b/src/proto/server/request.rs @@ -5,7 +5,9 @@ use crypto::md5::Md5; use crate::proto::packet::{MutPacket, WriteToPacket}; use crate::proto::server::constants::*; -use crate::proto::{ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncoder}; +use crate::proto::{ + ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncodeError, ProtoEncoder, +}; /* ------- * * Helpers * @@ -98,7 +100,7 @@ impl WriteToPacket for ServerRequest { } impl ProtoEncode for ServerRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { match *self { ServerRequest::CannotConnectRequest(ref request) => { encoder.encode_u32(CODE_CANNOT_CONNECT)?; @@ -225,7 +227,7 @@ impl WriteToPacket for CannotConnectRequest { } impl ProtoEncode for CannotConnectRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.token)?; encoder.encode_string(&self.user_name) } @@ -260,7 +262,7 @@ impl WriteToPacket for ConnectToPeerRequest { } impl ProtoEncode for ConnectToPeerRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.token)?; encoder.encode_string(&self.user_name)?; encoder.encode_string(&self.connection_type) @@ -299,7 +301,7 @@ impl WriteToPacket for FileSearchRequest { } impl ProtoEncode for FileSearchRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.ticket)?; encoder.encode_string(&self.query) } @@ -368,7 +370,7 @@ impl WriteToPacket for LoginRequest { } impl ProtoEncode for LoginRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.username)?; encoder.encode_string(&self.password)?; encoder.encode_u32(self.major)?; @@ -411,7 +413,7 @@ impl WriteToPacket for PeerAddressRequest { } impl ProtoEncode for PeerAddressRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.username) } } @@ -440,7 +442,7 @@ impl WriteToPacket for RoomJoinRequest { } impl ProtoEncode for RoomJoinRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name) } } @@ -471,7 +473,7 @@ impl WriteToPacket for RoomLeaveRequest { } impl ProtoEncode for RoomLeaveRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name) } } @@ -504,7 +506,7 @@ impl WriteToPacket for RoomMessageRequest { } impl ProtoEncode for RoomMessageRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name)?; encoder.encode_string(&self.message) } @@ -535,7 +537,7 @@ impl WriteToPacket for SetListenPortRequest { } impl ProtoEncode for SetListenPortRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode(&self.port) } } @@ -564,7 +566,7 @@ impl WriteToPacket for UserStatusRequest { } impl ProtoEncode for UserStatusRequest { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.user_name) } } diff --git a/src/proto/server/response.rs b/src/proto/server/response.rs index 7755a30..e1a2988 100644 --- a/src/proto/server/response.rs +++ b/src/proto/server/response.rs @@ -4,7 +4,8 @@ use std::net; use crate::proto::packet::{Packet, PacketReadError, ReadFromPacket}; use crate::proto::server::constants::*; use crate::proto::{ - ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncoder, User, UserStatus, + ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncodeError, ProtoEncoder, User, + UserStatus, }; /*=================* @@ -92,7 +93,7 @@ impl ReadFromPacket for ServerResponse { } impl ProtoEncode for ServerResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { match *self { ServerResponse::ConnectToPeerResponse(ref response) => { encoder.encode_u32(CODE_CONNECT_TO_PEER)?; @@ -290,11 +291,11 @@ impl ReadFromPacket for ConnectToPeerResponse { } impl ProtoEncode for ConnectToPeerResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { - encoder.encode_string(&self.user_name)?; - encoder.encode_string(&self.connection_type)?; - encoder.encode_ipv4_addr(self.ip)?; - encoder.encode(&self.port)?; + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { + encoder.encode(&self.user_name)?; + encoder.encode(&self.connection_type)?; + encoder.encode(&self.ip)?; + encoder.encode_u16(self.port)?; encoder.encode_u32(self.token)?; encoder.encode_bool(self.is_privileged) } @@ -346,7 +347,7 @@ impl ReadFromPacket for FileSearchResponse { } impl ProtoEncode for FileSearchResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.user_name)?; encoder.encode_u32(self.ticket)?; encoder.encode_string(&self.query) @@ -409,7 +410,7 @@ impl ReadFromPacket for LoginResponse { } impl ProtoEncode for LoginResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { match *self { LoginResponse::LoginOk { ref motd, @@ -417,12 +418,12 @@ impl ProtoEncode for LoginResponse { password_md5_opt: _, } => { encoder.encode_bool(true)?; - encoder.encode_string(motd)?; - encoder.encode_ipv4_addr(ip)?; + encoder.encode(motd)?; + encoder.encode(&ip)?; } LoginResponse::LoginFail { ref reason } => { encoder.encode_bool(false)?; - encoder.encode_string(reason)?; + encoder.encode(reason)?; } }; Ok(()) @@ -471,7 +472,7 @@ impl ReadFromPacket for ParentMinSpeedResponse { } impl ProtoEncode for ParentMinSpeedResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.value) } } @@ -500,7 +501,7 @@ impl ReadFromPacket for ParentSpeedRatioResponse { } impl ProtoEncode for ParentSpeedRatioResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.value) } } @@ -534,10 +535,10 @@ impl ReadFromPacket for PeerAddressResponse { } impl ProtoEncode for PeerAddressResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { - encoder.encode_string(&self.username)?; - encoder.encode_ipv4_addr(self.ip)?; - encoder.encode(&self.port) + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { + encoder.encode(&self.username)?; + encoder.encode(&self.ip)?; + encoder.encode_u16(self.port) } } @@ -567,7 +568,7 @@ impl ReadFromPacket for PrivilegedUsersResponse { } impl ProtoEncode for PrivilegedUsersResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode(&self.users) } } @@ -727,7 +728,7 @@ fn build_user( } impl ProtoEncode for UserInfo { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.average_speed)?; encoder.encode_u32(self.num_downloads)?; encoder.encode_u32(self.unknown)?; @@ -754,7 +755,7 @@ impl ProtoDecode for UserInfo { } impl ProtoEncode for RoomJoinResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { let mut user_names = vec![]; let mut user_statuses = vec![]; let mut user_infos = vec![]; @@ -863,7 +864,7 @@ impl ReadFromPacket for RoomLeaveResponse { } impl ProtoEncode for RoomLeaveResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name) } } @@ -964,7 +965,10 @@ impl RoomListResponse { Ok(Self::build_rooms(room_names, user_counts)) } - fn encode_rooms(rooms: &[(String, u32)], encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode_rooms( + rooms: &[(String, u32)], + encoder: &mut ProtoEncoder, + ) -> Result<(), ProtoEncodeError> { let mut room_names = vec![]; let mut user_counts = vec![]; @@ -979,7 +983,7 @@ impl RoomListResponse { } impl ProtoEncode for RoomListResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { Self::encode_rooms(&self.rooms, encoder)?; Self::encode_rooms(&self.owned_private_rooms, encoder)?; Self::encode_rooms(&self.other_private_rooms, encoder)?; @@ -1027,7 +1031,7 @@ impl ReadFromPacket for RoomMessageResponse { } impl ProtoEncode for RoomMessageResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name)?; encoder.encode_string(&self.user_name)?; encoder.encode_string(&self.message) @@ -1074,7 +1078,7 @@ impl ReadFromPacket for RoomTickersResponse { } impl ProtoEncode for RoomTickersResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name)?; encoder.encode(&self.tickers) } @@ -1132,7 +1136,7 @@ impl ReadFromPacket for RoomUserJoinedResponse { } impl ProtoEncode for RoomUserJoinedResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name)?; encoder.encode_string(&self.user.name)?; self.user.status.encode(encoder)?; @@ -1179,7 +1183,7 @@ impl ReadFromPacket for RoomUserLeftResponse { } impl ProtoEncode for RoomUserLeftResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.room_name)?; encoder.encode_string(&self.user_name) } @@ -1227,7 +1231,7 @@ impl ReadFromPacket for UserInfoResponse { } impl ProtoEncode for UserInfoResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.user_name)?; encoder.encode_u32(self.average_speed as u32)?; encoder.encode_u32(self.num_downloads as u32)?; @@ -1278,7 +1282,7 @@ impl ReadFromPacket for UserStatusResponse { } impl ProtoEncode for UserStatusResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_string(&self.user_name)?; self.status.encode(encoder)?; encoder.encode_bool(self.is_privileged) @@ -1315,7 +1319,7 @@ impl ReadFromPacket for WishlistIntervalResponse { } impl ProtoEncode for WishlistIntervalResponse { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { encoder.encode_u32(self.seconds) } } diff --git a/src/proto/user.rs b/src/proto/user.rs index c0c6154..fcd2f20 100644 --- a/src/proto/user.rs +++ b/src/proto/user.rs @@ -2,7 +2,7 @@ use std::io; use crate::proto::{ MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, - ProtoEncoder, ReadFromPacket, WriteToPacket, + ProtoEncodeError, ProtoEncoder, ReadFromPacket, WriteToPacket, }; const STATUS_OFFLINE: u32 = 1; @@ -45,7 +45,7 @@ impl WriteToPacket for UserStatus { } impl ProtoEncode for UserStatus { - fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> { + fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> { let value = match *self { UserStatus::Offline => STATUS_OFFLINE, UserStatus::Away => STATUS_AWAY,