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    No,
17    #[default]
18    System,
19    Custom(T),
20}
21
22impl<T> Proxy<T> {
23    /// Transform the inner custom value, leaving [`Proxy::No`] and
24    /// [`Proxy::System`] unchanged.
25    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Proxy<U> {
26        match self {
27            Self::No => Proxy::No,
28            Self::System => Proxy::System,
29            Self::Custom(t) => Proxy::Custom(f(t)),
30        }
31    }
32
33    /// Borrow the inner custom value as a reference, leaving [`Proxy::No`] and
34    /// [`Proxy::System`] unchanged. Requires `T: Deref`.
35    pub fn as_deref(&self) -> Proxy<&T::Target>
36    where
37        T: Deref,
38    {
39        match self {
40            Self::No => Proxy::No,
41            Self::System => Proxy::System,
42            Self::Custom(t) => Proxy::Custom(&**t),
43        }
44    }
45
46    /// Borrow the inner custom value as a shared reference, leaving
47    /// [`Proxy::No`] and [`Proxy::System`] unchanged.
48    pub const fn as_ref(&self) -> Proxy<&T> {
49        match self {
50            Self::No => Proxy::No,
51            Self::System => Proxy::System,
52            Self::Custom(t) => Proxy::Custom(t),
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn map_transforms_custom_only() {
63        assert_eq!(Proxy::<i32>::No.map(|x| x + 1), Proxy::No);
64        assert_eq!(Proxy::<i32>::System.map(|x| x + 1), Proxy::System);
65        assert_eq!(Proxy::Custom(5).map(|x| x + 1), Proxy::Custom(6));
66    }
67
68    #[test]
69    fn as_deref_borrows_custom() {
70        let p: Proxy<String> = Proxy::Custom("http".to_string());
71        assert_eq!(p.as_deref(), Proxy::Custom("http"));
72        assert_eq!(Proxy::<String>::No.as_deref(), Proxy::No);
73        assert_eq!(Proxy::<String>::System.as_deref(), Proxy::System);
74    }
75
76    #[test]
77    fn as_ref_borrows_custom() {
78        let p: Proxy<i32> = Proxy::Custom(7);
79        assert_eq!(p.as_ref(), Proxy::Custom(&7));
80        assert_eq!(Proxy::<i32>::No.as_ref(), Proxy::No);
81        assert_eq!(Proxy::<i32>::System.as_ref(), Proxy::System);
82    }
83
84    #[test]
85    fn default_is_system() {
86        assert_eq!(Proxy::<String>::default(), Proxy::System);
87    }
88
89    #[test]
90    fn copy_and_equality() {
91        let p = Proxy::Custom(3);
92        let q = p; // Proxy is Copy
93        assert_eq!(p, q);
94    }
95}