use chrono::prelude::NaiveDateTime;
use serde::{Deserialize, Serialize};
use transmission_sys;
use crate::error::Error;
#[derive(Debug, Serialize, Deserialize)]
pub enum TorrentState {
Downloading,
DownloadingWait,
Seeding,
SeedingWait,
Stopped,
Checking,
CheckingWait,
Error,
}
impl From<transmission_sys::tr_torrent_activity> for TorrentState {
fn from(act: transmission_sys::tr_torrent_activity) -> Self {
match act {
transmission_sys::tr_torrent_activity::TR_STATUS_DOWNLOAD => TorrentState::Downloading,
transmission_sys::tr_torrent_activity::TR_STATUS_DOWNLOAD_WAIT => {
TorrentState::DownloadingWait
}
transmission_sys::tr_torrent_activity::TR_STATUS_SEED => TorrentState::Seeding,
transmission_sys::tr_torrent_activity::TR_STATUS_SEED_WAIT => TorrentState::SeedingWait,
transmission_sys::tr_torrent_activity::TR_STATUS_CHECK => TorrentState::Checking,
transmission_sys::tr_torrent_activity::TR_STATUS_CHECK_WAIT => {
TorrentState::CheckingWait
}
transmission_sys::tr_torrent_activity::TR_STATUS_STOPPED => TorrentState::Stopped,
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TorrentStats {
pub id: i32,
pub state: TorrentState,
pub error: Error,
pub error_string: String,
pub recheck_progress: f32,
pub percent_complete: f32,
pub metadata_percent_complete: f32,
pub percent_done: f32,
pub seed_ratio_percent_done: f32,
pub raw_upload_speed_kbps: f32,
pub raw_download_speed_kbps: f32,
pub piece_upload_speed_kbps: f32,
pub piece_download_speed_kbps: f32,
pub eta: i32,
pub eta_idle: i32,
pub peers_connected: i32,
pub peers_from: [i32; 7],
pub peers_sending_to_us: i32,
pub peers_getting_from_us: i32,
pub webseeds_sending_to_us: i32,
pub size_when_done: u64,
pub left_until_done: u64,
pub desired_available: u64,
pub corrupt_ever: u64,
pub uploaded_ever: u64,
pub downloaded_ever: u64,
pub have_valid: u64,
pub have_unchecked: u64,
pub manual_announce_time: NaiveDateTime,
pub ratio: f32,
pub added_date: NaiveDateTime,
pub done_date: NaiveDateTime,
pub start_date: NaiveDateTime,
pub activity_date: NaiveDateTime,
pub idle_secs: i32,
pub seconds_downloading: i32,
pub seconds_seeding: i32,
pub finished: bool,
pub queue_position: i32,
pub is_stalled: bool,
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
impl From<*const transmission_sys::tr_stat> for TorrentStats {
fn from(stat: *const transmission_sys::tr_stat) -> Self {
let stat = unsafe { *stat };
Self {
id: stat.id,
state: TorrentState::from(stat.activity),
error: Error::from(stat.error),
error_string: {
let slice = unsafe { &*(&stat.errorString[0..] as *const _ as *const [u8]) };
if slice[0] == 0 {
String::new()
} else {
String::from_utf8(slice.to_owned()).unwrap()
}
},
recheck_progress: stat.recheckProgress,
percent_complete: stat.percentComplete,
metadata_percent_complete: stat.metadataPercentComplete,
percent_done: stat.percentDone,
seed_ratio_percent_done: stat.seedRatioPercentDone,
raw_upload_speed_kbps: stat.rawUploadSpeed_KBps,
raw_download_speed_kbps: stat.rawDownloadSpeed_KBps,
piece_upload_speed_kbps: stat.pieceUploadSpeed_KBps,
piece_download_speed_kbps: stat.pieceDownloadSpeed_KBps,
eta: stat.eta,
eta_idle: stat.etaIdle,
peers_connected: stat.peersConnected,
peers_from: stat.peersFrom,
peers_sending_to_us: stat.peersSendingToUs,
peers_getting_from_us: stat.peersGettingFromUs,
webseeds_sending_to_us: stat.webseedsSendingToUs,
size_when_done: stat.sizeWhenDone,
left_until_done: stat.leftUntilDone,
desired_available: stat.desiredAvailable,
corrupt_ever: stat.corruptEver,
uploaded_ever: stat.uploadedEver,
downloaded_ever: stat.downloadedEver,
have_valid: stat.haveValid,
have_unchecked: stat.haveUnchecked,
manual_announce_time: NaiveDateTime::from_timestamp(stat.manualAnnounceTime, 0),
ratio: stat.ratio,
added_date: NaiveDateTime::from_timestamp(stat.addedDate, 0),
done_date: NaiveDateTime::from_timestamp(stat.doneDate, 0),
start_date: NaiveDateTime::from_timestamp(stat.startDate, 0),
activity_date: NaiveDateTime::from_timestamp(stat.activityDate, 0),
idle_secs: stat.idleSecs,
seconds_downloading: stat.secondsDownloading,
seconds_seeding: stat.secondsSeeding,
finished: stat.finished,
queue_position: stat.queuePosition,
is_stalled: stat.isStalled,
}
}
}