use crate::error::{Error, Result};
use alloc::string::String;
use alloc::vec::Vec;
use nextjson::{NsonDeserialize, NsonSerialize};
#[derive(Debug, Clone, PartialEq, Eq, NsonSerialize, NsonDeserialize)]
pub struct TorrentState {
pub info_hash: Vec<u8>,
pub save_path: String,
pub have: Vec<u8>,
pub partial: Vec<(u32, Vec<u8>)>,
pub added_at: i64,
pub paused: bool,
pub file_priorities: Vec<u8>,
pub upload_limit_bps: u64,
pub download_limit_bps: u64,
pub reputation: Vec<u8>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, NsonSerialize, NsonDeserialize)]
pub struct SessionState {
pub version: u32,
pub torrents: Vec<TorrentState>,
pub dht_nodes: Vec<Vec<u8>>,
}
impl SessionState {
pub fn to_binary(&self) -> Result<Vec<u8>> {
let config = rustbinary::options().with_limit(64 * 1024 * 1024);
config.serialize(self).map_err(|_| Error::InvalidInput)
}
pub fn from_binary(bytes: &[u8]) -> Result<SessionState> {
let config = rustbinary::options().with_limit(64 * 1024 * 1024);
config.deserialize(bytes).map_err(|_| Error::InvalidInput)
}
pub fn to_json(&self) -> Result<Vec<u8>> {
nextjson::nextencode(self).map_err(|_| Error::InvalidInput)
}
pub fn from_json(bytes: &[u8]) -> Result<SessionState> {
nextjson::nextdecode(bytes).map_err(|_| Error::InvalidInput)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample() -> SessionState {
SessionState {
version: 1,
torrents: vec![TorrentState {
info_hash: vec![1u8; 20],
save_path: String::from("/data/downloads"),
have: vec![0b1010_0000, 0],
partial: vec![(3, vec![0b1000_0000])],
added_at: 1_700_000_000,
paused: false,
file_priorities: vec![1, 0, 2],
upload_limit_bps: 0,
download_limit_bps: 1_000_000,
reputation: vec![1, 2, 3],
}],
dht_nodes: vec![vec![2u8; 26]],
}
}
#[test]
fn binary_roundtrip() {
let s = sample();
let bytes = s.to_binary().unwrap();
let back = SessionState::from_binary(&bytes).unwrap();
assert_eq!(back, s);
}
#[test]
fn json_roundtrip() {
let s = sample();
let bytes = s.to_json().unwrap();
let back = SessionState::from_json(&bytes).unwrap();
assert_eq!(back, s);
}
}