diff --git a/crates/buffers/src/lib.rs b/crates/buffers/src/lib.rs index c059e9c..3079b34 100644 --- a/crates/buffers/src/lib.rs +++ b/crates/buffers/src/lib.rs @@ -3,16 +3,16 @@ // // Not useful outside of librqbit. -use serde::Deserialize; +use std::marker::PhantomData; + +use serde::Deserializer; use clone_to_owned::CloneToOwned; -#[derive(Default, Deserialize, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] -#[serde(transparent)] +#[derive(Default, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] pub struct ByteBufOwned(pub Box<[u8]>); -#[derive(Default, Deserialize, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] -#[serde(transparent)] +#[derive(Default, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] pub struct ByteBuf<'a>(pub &'a [u8]); pub trait ByteBufT { @@ -170,3 +170,54 @@ impl serde::ser::Serialize for ByteBufOwned { serializer.serialize_bytes(self.as_slice()) } } + +impl<'de> serde::de::Deserialize<'de> for ByteBufOwned { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = ByteBufOwned; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("byte string") + } + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + Ok(ByteBufOwned::from(v.to_owned())) + } + } + Ok(deserializer.deserialize_byte_buf(Visitor {})?) + } +} + +impl<'de: 'a, 'a> serde::de::Deserialize<'de> for ByteBuf<'a> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Default)] + struct Visitor<'a> { + _p: PhantomData<&'a ()>, + } + + impl<'de: 'a, 'a> serde::de::Visitor<'de> for Visitor<'a> { + type Value = ByteBuf<'a>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("byte string") + } + fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result + where + E: serde::de::Error, + { + Ok(ByteBuf::from(v)) + } + } + Ok(deserializer.deserialize_byte_buf(Visitor::default())?) + } +} diff --git a/crates/librqbit/src/torrent_state/live/mod.rs b/crates/librqbit/src/torrent_state/live/mod.rs index c0a8ece..532c3f0 100644 --- a/crates/librqbit/src/torrent_state/live/mod.rs +++ b/crates/librqbit/src/torrent_state/live/mod.rs @@ -248,10 +248,10 @@ impl TorrentStateLive { let stats = state.stats_snapshot(); let fetched = stats.fetched_bytes; let needed = state.initially_needed(); - // fetched can be too high in theory, so for safety make sure that it doesn't wrap around u64. - let remaining = needed - .wrapping_sub(fetched) - .min(needed - stats.downloaded_and_checked_bytes); + // TODO: this is very coarse, as it doesn't capture partially + // downloaded pieces. But it's better than using "fetched" which is bugged, + // see #92 + let remaining = needed - stats.downloaded_and_checked_bytes; state .down_speed_estimator .add_snapshot(fetched, Some(remaining), now);