From 1857a74b87d74c9c5174f1514ad1c0ba0df62f73 Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:38:44 +0100 Subject: [PATCH 1/7] deps: Enable feature serde on fluent_uri --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f25abff..024a324 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ sha1 = "0.10" sha256 = "1.5" rustc-hex = "2.1" serde = { version = "1", features = [ "derive" ] } -fluent-uri = "0.4" +fluent-uri = { version = "0.4", features = [ "serde" ] } [dev-dependencies] serde_json = "1" From 82bc6ebea6b5b135e3acb736e58f3efe1dbba986 Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:39:16 +0100 Subject: [PATCH 2/7] feat: TrackerScheme implements FromStr --- CHANGELOG.md | 1 + src/tracker.rs | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4867903..478b9ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new `MagnetLinkError` variants to be more precise about what's wrong with a parsed magnet link. - `MagnetLink::trackers` lists the trackers in the magnet link +- `TrackerScheme` implements `FromStr` ## Version 0.3.2 (2025-08-29) diff --git a/src/tracker.rs b/src/tracker.rs index a780d1c..6cce125 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -1,5 +1,7 @@ use fluent_uri::{ParseError as UriParseError, Uri}; +use std::str::FromStr; + /// A source of peers. Can be a [`Tracker`](crate::tracker::Tracker) or a decentralized source. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum PeerSource { @@ -50,6 +52,21 @@ pub enum TrackerScheme { UDP, } +impl FromStr for TrackerScheme { + type Err = TrackerError; + + fn from_str(s: &str) -> Result { + match s { + "http" | "https" => Ok(Self::Http), + "ws" => Ok(Self::Websocket), + "udp" => Ok(Self::UDP), + _ => Err(TrackerError::InvalidScheme { + scheme: s.to_string(), + }), + } + } +} + /// Error occurred during parsing a [`Tracker`](crate::tracker::Tracker). #[derive(Clone, Debug, PartialEq)] pub enum TrackerError { @@ -114,19 +131,8 @@ impl Tracker { /// /// Will fail if scheme is not "http", "https", "wss" or "udp". pub fn from_url(url: &Uri) -> Result { - let scheme = match url.scheme().as_str() { - "http" | "https" => TrackerScheme::Http, - "wss" => TrackerScheme::Websocket, - "udp" => TrackerScheme::UDP, - _ => { - return Err(TrackerError::InvalidScheme { - scheme: url.scheme().to_string(), - }); - } - }; - Ok(Tracker { - scheme, + scheme: TrackerScheme::from_str(url.scheme().as_str())?, url: url.clone(), }) } From 7c679453c58fc3d666a42caa6521c072ff8af8af Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:42:31 +0100 Subject: [PATCH 3/7] breaking: TrackerScheme::UDP variant is now Udp --- CHANGELOG.md | 3 +++ src/tracker.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 478b9ec..7111ea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `fluent_uri::Uri` instead of a `url::Url` previously - all error types with an `InvalidURL` variant now have `fluent_uri::ParseError` as source instead of `url::ParseError` previously +- `TrackerScheme` variant `UDP` has been renamed `Udp` to be more consistent with + other variants, and other rust types + ### Added diff --git a/src/tracker.rs b/src/tracker.rs index 6cce125..3b38f97 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -49,7 +49,7 @@ impl Tracker { pub enum TrackerScheme { Websocket, Http, - UDP, + Udp, } impl FromStr for TrackerScheme { @@ -59,7 +59,7 @@ impl FromStr for TrackerScheme { match s { "http" | "https" => Ok(Self::Http), "ws" => Ok(Self::Websocket), - "udp" => Ok(Self::UDP), + "udp" => Ok(Self::Udp), _ => Err(TrackerError::InvalidScheme { scheme: s.to_string(), }), From d9784ad61c7383d558e0c3b7ba17ea955d61b85b Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:49:03 +0100 Subject: [PATCH 4/7] fix: Manually implement Tracker (de)serialization --- CHANGELOG.md | 5 +++++ src/tracker.rs | 23 ++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7111ea3..a6299ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `MagnetLink::trackers` lists the trackers in the magnet link - `TrackerScheme` implements `FromStr` +### Fixed + +- `Tracker` (de)serialization implementation is now custom and only uses the + inner URL instead of trying to (de)serialize all fields which was wrong + ## Version 0.3.2 (2025-08-29) ### Added diff --git a/src/tracker.rs b/src/tracker.rs index 3b38f97..fca2bf5 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -1,4 +1,5 @@ use fluent_uri::{ParseError as UriParseError, Uri}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::str::FromStr; @@ -12,7 +13,7 @@ pub enum PeerSource { } /// A centralized variant of a [`Peersource`](crate::tracker::PeerSource). -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct Tracker { scheme: TrackerScheme, url: Uri, @@ -44,6 +45,26 @@ impl Tracker { } } +impl<'de> Deserialize<'de> for Tracker { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Tracker::new(&s).map_err(serde::de::Error::custom) + } +} + +impl Serialize for Tracker { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // serializer.serialize(&self.url) + self.url.serialize(serializer) + } +} + /// A protocol used by a [`Tracker`](crate::tracker::Tracker). #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum TrackerScheme { From f4f6b46ee637684ef95a25d1c94027b411653b99 Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:51:53 +0100 Subject: [PATCH 5/7] fix: TrackerScheme no longer supports (de)serialization --- CHANGELOG.md | 2 ++ src/tracker.rs | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6299ce..c5dc76f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 as source instead of `url::ParseError` previously - `TrackerScheme` variant `UDP` has been renamed `Udp` to be more consistent with other variants, and other rust types +- `TrackerScheme` no longer derives de/serialize because that's not actually + used in torrent files ### Added diff --git a/src/tracker.rs b/src/tracker.rs index fca2bf5..32b7c03 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -66,7 +66,11 @@ impl Serialize for Tracker { } /// A protocol used by a [`Tracker`](crate::tracker::Tracker). -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +/// +/// Does not implement Serialize/Deserialize because it's actually not in the +/// torrent data. It is constructed from the parsed tracker URLs contained in +/// the torrent data. +#[derive(Clone, Debug, PartialEq)] pub enum TrackerScheme { Websocket, Http, From 39bbec0c9c3eccc0359d1e83f2cb953c387ec784 Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:54:15 +0100 Subject: [PATCH 6/7] minor: Remove unused Tracker constructors --- src/tracker.rs | 48 +++++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/tracker.rs b/src/tracker.rs index 32b7c03..ede1b8b 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -20,20 +20,25 @@ pub struct Tracker { } impl Tracker { - pub fn new_http(uri: &str) -> Result { - let uri = Uri::parse(uri)?; - Ok(Self { - scheme: TrackerScheme::Http, - url: uri.into(), - }) + /// Generate a new Tracker from a given string URL. + pub fn new(url: &str) -> Result { + let url = Uri::parse(url.to_string())?; + Tracker::from_url(&url) } - pub fn new_udp(_uri: &str) -> Result { - unimplemented!(); + /// Generate a new Tracker from a parsed URL. + /// + /// Will fail if scheme is not "http", "https", "wss" or "udp". + pub fn from_url(url: &Uri) -> Result { + Ok(Tracker { + scheme: TrackerScheme::from_str(url.scheme().as_str())?, + url: url.clone(), + }) } - pub fn new_ws(_uri: &str) -> Result { - unimplemented!(); + /// Turns a centralized Tracker into a wider PeerSource + pub fn to_peer_source(&self) -> PeerSource { + PeerSource::from_tracker(self) } pub fn scheme(&self) -> &TrackerScheme { @@ -145,29 +150,6 @@ impl PeerSource { } } -impl Tracker { - /// Generate a new Tracker from a given string URL. - pub fn new(url: &str) -> Result { - let url = Uri::parse(url.to_string())?; - Tracker::from_url(&url) - } - - /// Generate a new Tracker from a parsed URL. - /// - /// Will fail if scheme is not "http", "https", "wss" or "udp". - pub fn from_url(url: &Uri) -> Result { - Ok(Tracker { - scheme: TrackerScheme::from_str(url.scheme().as_str())?, - url: url.clone(), - }) - } - - /// Turns a centralized Tracker into a wider PeerSource - pub fn to_peer_source(&self) -> PeerSource { - PeerSource::from_tracker(self) - } -} - /// Turn a backend-specific tracker struct into an agnostic [`Tracker`](crate::tracker::Tracker). pub trait TryIntoTracker { fn try_into_tracker(&self) -> Result; From d8b89bdda12309d2e61502dfa67e95f74e3b50ae Mon Sep 17 00:00:00 2001 From: angrynode Date: Wed, 5 Nov 2025 19:55:27 +0100 Subject: [PATCH 7/7] feat: Tracker implements FromStr --- CHANGELOG.md | 2 +- src/tracker.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5dc76f..c30c15b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new `MagnetLinkError` variants to be more precise about what's wrong with a parsed magnet link. - `MagnetLink::trackers` lists the trackers in the magnet link -- `TrackerScheme` implements `FromStr` +- `TrackerScheme` and `Tracker` implement `FromStr` ### Fixed diff --git a/src/tracker.rs b/src/tracker.rs index ede1b8b..2838420 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -70,6 +70,14 @@ impl Serialize for Tracker { } } +impl FromStr for Tracker { + type Err = TrackerError; + + fn from_str(s: &str) -> Result { + Self::new(s) + } +} + /// A protocol used by a [`Tracker`](crate::tracker::Tracker). /// /// Does not implement Serialize/Deserialize because it's actually not in the