Browse Source

Introduce ProtoEncodeError and use it in ProtoEncoder.

Tests are not fixed yet.
wip
Titouan Rigoudy 5 years ago
parent
commit
7bb290f0ef
7 changed files with 148 additions and 104 deletions
  1. +81
    -47
      src/proto/base_codec.rs
  2. +11
    -8
      src/proto/codec.rs
  3. +2
    -1
      src/proto/mod.rs
  4. +3
    -3
      src/proto/peer/message.rs
  5. +14
    -12
      src/proto/server/request.rs
  6. +35
    -31
      src/proto/server/response.rs
  7. +2
    -2
      src/proto/user.rs

+ 81
- 47
src/proto/base_codec.rs View File

@ -299,96 +299,130 @@ impl<T: ProtoDecode> ProtoDecode for Vec<T> {
} }
} }
#[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<ProtoEncodeError> 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. /// A type for encoding various types of values into protocol messages.
pub struct ProtoEncoder<'a> { pub struct ProtoEncoder<'a> {
inner: &'a mut BytesMut,
/// The buffer to which the encoder appends encoded bytes.
buffer: &'a mut Vec<u8>,
} }
/// This trait is implemented by types that can be encoded into messages using /// This trait is implemented by types that can be encoded into messages using
/// a `ProtoEncoder`. /// a `ProtoEncoder`.
pub trait ProtoEncode { pub trait ProtoEncode {
// TODO: Rename to encode_to().
/// Attempts to encode `self` with the given encoder. /// 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> { impl<'a> ProtoEncoder<'a> {
/// Wraps the given buffer for encoding values into. /// 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<u8>) -> 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(()) 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(()) 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(_) => { 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(()) Ok(())
} }
/// Attempts to encode the given value.
/// Encodes the given value into the underlying buffer.
/// ///
/// Allows for easy encoding with type inference: /// Allows for easy encoding with type inference:
/// ``` /// ```
/// let val : Foo = Foo::new(bar);
/// encoder.encode(&val)?;
/// encoder.encode(&Foo::new(bar))?;
/// ``` /// ```
pub fn encode<T: ProtoEncode>(&mut self, val: &T) -> io::Result<()> {
pub fn encode<T: ProtoEncode>(&mut self, val: &T) -> Result<(), ProtoEncodeError> {
val.encode(self) val.encode(self)
} }
} }
impl ProtoEncode for u32 { impl ProtoEncode for u32 {
fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
encoder.encode_u32(*self) 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 { 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. // Proto{De,En}code) but it is not really worth the hassle.
impl ProtoEncode for str { impl ProtoEncode for str {
fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
encoder.encode_string(self) encoder.encode_string(self)
} }
} }
impl ProtoEncode for String { impl ProtoEncode for String {
fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
encoder.encode_string(self) encoder.encode_string(self)
} }
} }
impl<'a> ProtoEncode for &'a String { 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) encoder.encode_string(*self)
} }
} }
impl<T: ProtoEncode, U: ProtoEncode> ProtoEncode for (T, U) { impl<T: ProtoEncode, U: ProtoEncode> 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.0.encode(encoder)?;
self.1.encode(encoder) self.1.encode(encoder)
} }
} }
impl<T: ProtoEncode> ProtoEncode for [T] { impl<T: ProtoEncode> 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)?; encoder.encode_u32(self.len() as u32)?;
for ref item in self { for ref item in self {
item.encode(encoder)?; item.encode(encoder)?;
@ -436,7 +470,7 @@ impl<T: ProtoEncode> ProtoEncode for [T] {
} }
impl<T: ProtoEncode> ProtoEncode for Vec<T> { impl<T: ProtoEncode> ProtoEncode for Vec<T> {
fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
let slice: &[T] = &*self; let slice: &[T] = &*self;
slice.encode(encoder) slice.encode(encoder)
} }


+ 11
- 8
src/proto/codec.rs View File

@ -9,6 +9,8 @@
//! This enables wrapping AsyncRead and AsyncWrite objects into Stream and Sink //! This enables wrapping AsyncRead and AsyncWrite objects into Stream and Sink
//! objects using tokio_codec's FramedRead and FramedWrite adapters. //! objects using tokio_codec's FramedRead and FramedWrite adapters.
// TODO: Refactor all this into futures and remove tokio dependency.
use std::io; use std::io;
use std::marker; use std::marker;
@ -37,18 +39,19 @@ impl<T: ProtoEncode> tokio_codec::Encoder for LengthPrefixedEncoder<T> {
type Error = io::Error; type Error = io::Error;
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::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. // 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. // 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(()) Ok(())
} }
} }


+ 2
- 1
src/proto/mod.rs View File

@ -9,7 +9,8 @@ mod stream;
mod user; mod user;
pub use self::base_codec::{ 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::codec::*;
pub use self::handler::*; pub use self::handler::*;


+ 3
- 3
src/proto/peer/message.rs View File

@ -3,7 +3,7 @@ use std::io;
use crate::proto::peer::constants::*; use crate::proto::peer::constants::*;
use crate::proto::{ use crate::proto::{
MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, 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 { impl ProtoEncode for Message {
fn encode(&self, encoder: &mut ProtoEncoder) -> io::Result<()> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
match *self { match *self {
Message::PierceFirewall(token) => { Message::PierceFirewall(token) => {
encoder.encode_u32(CODE_PIERCE_FIREWALL)?; encoder.encode_u32(CODE_PIERCE_FIREWALL)?;
@ -132,7 +132,7 @@ impl WriteToPacket for PeerInit {
} }
impl ProtoEncode 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.user_name)?;
encoder.encode_string(&self.connection_type)?; encoder.encode_string(&self.connection_type)?;
encoder.encode_u32(self.token)?; encoder.encode_u32(self.token)?;


+ 14
- 12
src/proto/server/request.rs View File

@ -5,7 +5,9 @@ use crypto::md5::Md5;
use crate::proto::packet::{MutPacket, WriteToPacket}; use crate::proto::packet::{MutPacket, WriteToPacket};
use crate::proto::server::constants::*; use crate::proto::server::constants::*;
use crate::proto::{ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncoder};
use crate::proto::{
ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, ProtoEncodeError, ProtoEncoder,
};
/* ------- * /* ------- *
* Helpers * * Helpers *
@ -98,7 +100,7 @@ impl WriteToPacket for ServerRequest {
} }
impl ProtoEncode 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 { match *self {
ServerRequest::CannotConnectRequest(ref request) => { ServerRequest::CannotConnectRequest(ref request) => {
encoder.encode_u32(CODE_CANNOT_CONNECT)?; encoder.encode_u32(CODE_CANNOT_CONNECT)?;
@ -225,7 +227,7 @@ impl WriteToPacket for CannotConnectRequest {
} }
impl ProtoEncode 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_u32(self.token)?;
encoder.encode_string(&self.user_name) encoder.encode_string(&self.user_name)
} }
@ -260,7 +262,7 @@ impl WriteToPacket for ConnectToPeerRequest {
} }
impl ProtoEncode 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_u32(self.token)?;
encoder.encode_string(&self.user_name)?; encoder.encode_string(&self.user_name)?;
encoder.encode_string(&self.connection_type) encoder.encode_string(&self.connection_type)
@ -299,7 +301,7 @@ impl WriteToPacket for FileSearchRequest {
} }
impl ProtoEncode 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_u32(self.ticket)?;
encoder.encode_string(&self.query) encoder.encode_string(&self.query)
} }
@ -368,7 +370,7 @@ impl WriteToPacket for LoginRequest {
} }
impl ProtoEncode 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.username)?;
encoder.encode_string(&self.password)?; encoder.encode_string(&self.password)?;
encoder.encode_u32(self.major)?; encoder.encode_u32(self.major)?;
@ -411,7 +413,7 @@ impl WriteToPacket for PeerAddressRequest {
} }
impl ProtoEncode 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) encoder.encode_string(&self.username)
} }
} }
@ -440,7 +442,7 @@ impl WriteToPacket for RoomJoinRequest {
} }
impl ProtoEncode 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) encoder.encode_string(&self.room_name)
} }
} }
@ -471,7 +473,7 @@ impl WriteToPacket for RoomLeaveRequest {
} }
impl ProtoEncode 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) encoder.encode_string(&self.room_name)
} }
} }
@ -504,7 +506,7 @@ impl WriteToPacket for RoomMessageRequest {
} }
impl ProtoEncode 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.room_name)?;
encoder.encode_string(&self.message) encoder.encode_string(&self.message)
} }
@ -535,7 +537,7 @@ impl WriteToPacket for SetListenPortRequest {
} }
impl ProtoEncode 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) encoder.encode(&self.port)
} }
} }
@ -564,7 +566,7 @@ impl WriteToPacket for UserStatusRequest {
} }
impl ProtoEncode 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) encoder.encode_string(&self.user_name)
} }
} }


+ 35
- 31
src/proto/server/response.rs View File

@ -4,7 +4,8 @@ use std::net;
use crate::proto::packet::{Packet, PacketReadError, ReadFromPacket}; use crate::proto::packet::{Packet, PacketReadError, ReadFromPacket};
use crate::proto::server::constants::*; use crate::proto::server::constants::*;
use crate::proto::{ 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 { impl ProtoEncode for ServerResponse {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), io::Error> {
fn encode(&self, encoder: &mut ProtoEncoder) -> Result<(), ProtoEncodeError> {
match *self { match *self {
ServerResponse::ConnectToPeerResponse(ref response) => { ServerResponse::ConnectToPeerResponse(ref response) => {
encoder.encode_u32(CODE_CONNECT_TO_PEER)?; encoder.encode_u32(CODE_CONNECT_TO_PEER)?;
@ -290,11 +291,11 @@ impl ReadFromPacket for ConnectToPeerResponse {
} }
impl ProtoEncode 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_u32(self.token)?;
encoder.encode_bool(self.is_privileged) encoder.encode_bool(self.is_privileged)
} }
@ -346,7 +347,7 @@ impl ReadFromPacket for FileSearchResponse {
} }
impl ProtoEncode 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_string(&self.user_name)?;
encoder.encode_u32(self.ticket)?; encoder.encode_u32(self.ticket)?;
encoder.encode_string(&self.query) encoder.encode_string(&self.query)
@ -409,7 +410,7 @@ impl ReadFromPacket for LoginResponse {
} }
impl ProtoEncode 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 { match *self {
LoginResponse::LoginOk { LoginResponse::LoginOk {
ref motd, ref motd,
@ -417,12 +418,12 @@ impl ProtoEncode for LoginResponse {
password_md5_opt: _, password_md5_opt: _,
} => { } => {
encoder.encode_bool(true)?; encoder.encode_bool(true)?;
encoder.encode_string(motd)?;
encoder.encode_ipv4_addr(ip)?;
encoder.encode(motd)?;
encoder.encode(&ip)?;
} }
LoginResponse::LoginFail { ref reason } => { LoginResponse::LoginFail { ref reason } => {
encoder.encode_bool(false)?; encoder.encode_bool(false)?;
encoder.encode_string(reason)?;
encoder.encode(reason)?;
} }
}; };
Ok(()) Ok(())
@ -471,7 +472,7 @@ impl ReadFromPacket for ParentMinSpeedResponse {
} }
impl ProtoEncode 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) encoder.encode_u32(self.value)
} }
} }
@ -500,7 +501,7 @@ impl ReadFromPacket for ParentSpeedRatioResponse {
} }
impl ProtoEncode 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) encoder.encode_u32(self.value)
} }
} }
@ -534,10 +535,10 @@ impl ReadFromPacket for PeerAddressResponse {
} }
impl ProtoEncode 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 { 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) encoder.encode(&self.users)
} }
} }
@ -727,7 +728,7 @@ fn build_user(
} }
impl ProtoEncode for UserInfo { 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.average_speed)?;
encoder.encode_u32(self.num_downloads)?; encoder.encode_u32(self.num_downloads)?;
encoder.encode_u32(self.unknown)?; encoder.encode_u32(self.unknown)?;
@ -754,7 +755,7 @@ impl ProtoDecode for UserInfo {
} }
impl ProtoEncode for RoomJoinResponse { 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_names = vec![];
let mut user_statuses = vec![]; let mut user_statuses = vec![];
let mut user_infos = vec![]; let mut user_infos = vec![];
@ -863,7 +864,7 @@ impl ReadFromPacket for RoomLeaveResponse {
} }
impl ProtoEncode 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) encoder.encode_string(&self.room_name)
} }
} }
@ -964,7 +965,10 @@ impl RoomListResponse {
Ok(Self::build_rooms(room_names, user_counts)) 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 room_names = vec![];
let mut user_counts = vec![]; let mut user_counts = vec![];
@ -979,7 +983,7 @@ impl RoomListResponse {
} }
impl ProtoEncode for 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.rooms, encoder)?;
Self::encode_rooms(&self.owned_private_rooms, encoder)?; Self::encode_rooms(&self.owned_private_rooms, encoder)?;
Self::encode_rooms(&self.other_private_rooms, encoder)?; Self::encode_rooms(&self.other_private_rooms, encoder)?;
@ -1027,7 +1031,7 @@ impl ReadFromPacket for RoomMessageResponse {
} }
impl ProtoEncode 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.room_name)?;
encoder.encode_string(&self.user_name)?; encoder.encode_string(&self.user_name)?;
encoder.encode_string(&self.message) encoder.encode_string(&self.message)
@ -1074,7 +1078,7 @@ impl ReadFromPacket for RoomTickersResponse {
} }
impl ProtoEncode 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_string(&self.room_name)?;
encoder.encode(&self.tickers) encoder.encode(&self.tickers)
} }
@ -1132,7 +1136,7 @@ impl ReadFromPacket for RoomUserJoinedResponse {
} }
impl ProtoEncode 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.room_name)?;
encoder.encode_string(&self.user.name)?; encoder.encode_string(&self.user.name)?;
self.user.status.encode(encoder)?; self.user.status.encode(encoder)?;
@ -1179,7 +1183,7 @@ impl ReadFromPacket for RoomUserLeftResponse {
} }
impl ProtoEncode 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.room_name)?;
encoder.encode_string(&self.user_name) encoder.encode_string(&self.user_name)
} }
@ -1227,7 +1231,7 @@ impl ReadFromPacket for UserInfoResponse {
} }
impl ProtoEncode 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_string(&self.user_name)?;
encoder.encode_u32(self.average_speed as u32)?; encoder.encode_u32(self.average_speed as u32)?;
encoder.encode_u32(self.num_downloads as u32)?; encoder.encode_u32(self.num_downloads as u32)?;
@ -1278,7 +1282,7 @@ impl ReadFromPacket for UserStatusResponse {
} }
impl ProtoEncode 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)?; encoder.encode_string(&self.user_name)?;
self.status.encode(encoder)?; self.status.encode(encoder)?;
encoder.encode_bool(self.is_privileged) encoder.encode_bool(self.is_privileged)
@ -1315,7 +1319,7 @@ impl ReadFromPacket for WishlistIntervalResponse {
} }
impl ProtoEncode 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) encoder.encode_u32(self.seconds)
} }
} }


+ 2
- 2
src/proto/user.rs View File

@ -2,7 +2,7 @@ use std::io;
use crate::proto::{ use crate::proto::{
MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode, MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecodeError, ProtoDecoder, ProtoEncode,
ProtoEncoder, ReadFromPacket, WriteToPacket,
ProtoEncodeError, ProtoEncoder, ReadFromPacket, WriteToPacket,
}; };
const STATUS_OFFLINE: u32 = 1; const STATUS_OFFLINE: u32 = 1;
@ -45,7 +45,7 @@ impl WriteToPacket for UserStatus {
} }
impl ProtoEncode 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 { let value = match *self {
UserStatus::Offline => STATUS_OFFLINE, UserStatus::Offline => STATUS_OFFLINE,
UserStatus::Away => STATUS_AWAY, UserStatus::Away => STATUS_AWAY,


Loading…
Cancel
Save