use std::io; use crate::proto::core::value::{ ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder, }; use crate::proto::{ MutPacket, Packet, PacketReadError, ReadFromPacket, WriteToPacket, }; const STATUS_OFFLINE: u32 = 1; const STATUS_AWAY: u32 = 2; const STATUS_ONLINE: u32 = 3; /// This enumeration is the list of possible user statuses. #[derive( Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, RustcDecodable, RustcEncodable, )] pub enum UserStatus { /// The user if offline. Offline, /// The user is connected, but AFK. Away, /// The user is present. Online, } impl ReadFromPacket for UserStatus { fn read_from_packet(packet: &mut Packet) -> Result { let n: u32 = packet.read_value()?; match n { STATUS_OFFLINE => Ok(UserStatus::Offline), STATUS_AWAY => Ok(UserStatus::Away), STATUS_ONLINE => Ok(UserStatus::Online), _ => Err(PacketReadError::InvalidUserStatusError(n)), } } } impl WriteToPacket for UserStatus { fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { let n = match *self { UserStatus::Offline => STATUS_OFFLINE, UserStatus::Away => STATUS_AWAY, UserStatus::Online => STATUS_ONLINE, }; packet.write_value(&n)?; Ok(()) } } impl ValueEncode for UserStatus { fn encode_to( &self, encoder: &mut ValueEncoder, ) -> Result<(), ValueEncodeError> { let value = match *self { UserStatus::Offline => STATUS_OFFLINE, UserStatus::Away => STATUS_AWAY, UserStatus::Online => STATUS_ONLINE, }; encoder.encode_u32(value) } } impl ValueDecode for UserStatus { fn decode_from(decoder: &mut ValueDecoder) -> Result { let position = decoder.position(); let value: u32 = decoder.decode()?; match value { STATUS_OFFLINE => Ok(UserStatus::Offline), STATUS_AWAY => Ok(UserStatus::Away), STATUS_ONLINE => Ok(UserStatus::Online), _ => Err(ValueDecodeError::InvalidData { value_name: "user status".to_string(), cause: format!("unknown value {}", value), position: position, }), } } } /// This structure contains the last known information about a fellow user. #[derive( Clone, Debug, Eq, Ord, PartialEq, PartialOrd, RustcDecodable, RustcEncodable, )] pub struct User { /// The name of the user. pub name: String, /// The last known status of the user. pub status: UserStatus, /// The average upload speed of the user. pub average_speed: usize, /// ??? Nicotine calls it downloadnum. pub num_downloads: usize, /// ??? Unknown field. pub unknown: usize, /// The number of files this user shares. pub num_files: usize, /// The number of folders this user shares. pub num_folders: usize, /// The number of free download slots of this user. pub num_free_slots: usize, /// The user's country code. pub country: String, }