Skip to main content

fast_down/
proxy.rs

1//! Proxy selection for outgoing HTTP requests.
2//!
3//! This module defines the [`Proxy`] enum, which tells a `FastDownPuller`
4//! how to route its connections: no proxy, the system proxy (honoring
5//! platform/Environment settings), or a caller-supplied custom proxy URL.
6
7use std::ops::Deref;
8
9/// Proxy configuration for outgoing HTTP requests.
10///
11/// Supports no proxy, system-configured proxy, or a custom proxy URL.
12/// The `Custom` variant is unconstrained but is typically used with string-like types.
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
15pub enum Proxy<T> {
16    /// Never use a proxy.
17    No,
18    /// Use the platform-configured system proxy.
19    #[default]
20    System,
21    /// Use the given custom proxy URL.
22    Custom(T),
23}
24
25impl<T> Proxy<T> {
26    /// Transform the inner custom value, leaving [`Proxy::No`] and
27    /// [`Proxy::System`] unchanged.
28    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Proxy<U> {
29        match self {
30            Self::No => Proxy::No,
31            Self::System => Proxy::System,
32            Self::Custom(t) => Proxy::Custom(f(t)),
33        }
34    }
35
36    /// Borrow the inner custom value as a reference, leaving [`Proxy::No`] and
37    /// [`Proxy::System`] unchanged. Requires `T: Deref`.
38    pub fn as_deref(&self) -> Proxy<&T::Target>
39    where
40        T: Deref,
41    {
42        match self {
43            Self::No => Proxy::No,
44            Self::System => Proxy::System,
45            Self::Custom(t) => Proxy::Custom(&**t),
46        }
47    }
48
49    /// Borrow the inner custom value as a shared reference, leaving
50    /// [`Proxy::No`] and [`Proxy::System`] unchanged.
51    pub const fn as_ref(&self) -> Proxy<&T> {
52        match self {
53            Self::No => Proxy::No,
54            Self::System => Proxy::System,
55            Self::Custom(t) => Proxy::Custom(t),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn map_transforms_custom_only() {
66        assert_eq!(Proxy::<i32>::No.map(|x| x + 1), Proxy::No);
67        assert_eq!(Proxy::<i32>::System.map(|x| x + 1), Proxy::System);
68        assert_eq!(Proxy::Custom(5).map(|x| x + 1), Proxy::Custom(6));
69    }
70
71    #[test]
72    fn as_deref_borrows_custom() {
73        let p: Proxy<String> = Proxy::Custom("http".to_string());
74        assert_eq!(p.as_deref(), Proxy::Custom("http"));
75        assert_eq!(Proxy::<String>::No.as_deref(), Proxy::No);
76        assert_eq!(Proxy::<String>::System.as_deref(), Proxy::System);
77    }
78
79    #[test]
80    fn as_ref_borrows_custom() {
81        let p: Proxy<i32> = Proxy::Custom(7);
82        assert_eq!(p.as_ref(), Proxy::Custom(&7));
83        assert_eq!(Proxy::<i32>::No.as_ref(), Proxy::No);
84        assert_eq!(Proxy::<i32>::System.as_ref(), Proxy::System);
85    }
86
87    #[test]
88    fn default_is_system() {
89        assert_eq!(Proxy::<String>::default(), Proxy::System);
90    }
91
92    #[test]
93    fn copy_and_equality() {
94        let p = Proxy::Custom(3);
95        let q = p; // Proxy is Copy
96        assert_eq!(p, q);
97    }
98}