use std::io;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::core::value::{
|
|
ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError,
|
|
ValueEncoder,
|
|
};
|
|
use crate::{
|
|
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,
|
|
Serialize,
|
|
Deserialize,
|
|
)]
|
|
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<Self, PacketReadError> {
|
|
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<Self, ValueDecodeError> {
|
|
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,
|
|
Serialize,
|
|
Deserialize,
|
|
)]
|
|
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,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{User, UserStatus};
|
|
|
|
#[test]
|
|
fn deserialize_user_status() {
|
|
assert_eq!(
|
|
serde_json::from_str::<UserStatus>(r#""Offline""#).unwrap(),
|
|
UserStatus::Offline
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn deserialize_user() {
|
|
assert_eq!(
|
|
serde_json::from_str::<User>(
|
|
r#"{
|
|
"name": "karandeep",
|
|
"status": "Online",
|
|
"average_speed": 1,
|
|
"num_downloads": 2,
|
|
"unknown": 3,
|
|
"num_files": 4,
|
|
"num_folders": 5,
|
|
"num_free_slots": 6,
|
|
"country": "IN"
|
|
}"#
|
|
)
|
|
.unwrap(),
|
|
User {
|
|
name: "karandeep".to_string(),
|
|
status: UserStatus::Online,
|
|
average_speed: 1,
|
|
num_downloads: 2,
|
|
unknown: 3,
|
|
num_files: 4,
|
|
num_folders: 5,
|
|
num_free_slots: 6,
|
|
country: "IN".to_string(),
|
|
}
|
|
);
|
|
}
|
|
}
|