tor_config/
setter_traits.rs

1//! Traits to allow the setter functions on our builders
2//! to accept the specific set of types we want.
3
4use std::num::NonZero;
5
6/// Module used to seal the traits declared here.
7mod seal {
8    /// A type to seal most of the traits here.
9    pub trait Sealed {}
10    /// A type to seal `PossiblyOption<T>`. (This one has to be generic.)
11    pub trait SealedPossiblyOption<T> {}
12}
13
14/// A trait implemented by `String` and `&str`.
15///
16/// This is more specific than `AsRef<str>`, which can accidentally include
17/// many other undesired types.
18pub trait StringOrStr: seal::Sealed {
19    /// Convert this object to a String.
20    fn to_string(self) -> String;
21}
22impl seal::Sealed for String {}
23impl<'a> seal::Sealed for &'a str {}
24
25impl StringOrStr for String {
26    fn to_string(self) -> String {
27        self
28    }
29}
30impl<'a> StringOrStr for &'a str {
31    fn to_string(self) -> String {
32        self.to_owned()
33    }
34}
35
36/// A trait implemented by `String`, `&str`, `Option<String>`, and `Option<&str>`
37pub trait OptionStringOrStr: seal::Sealed {
38    /// Convert this object to an `Option<String>`.
39    fn to_option_string(self) -> Option<String>;
40}
41
42impl<S> OptionStringOrStr for S
43where
44    S: StringOrStr,
45{
46    fn to_option_string(self) -> Option<String> {
47        Some(self.to_string())
48    }
49}
50impl<S> seal::Sealed for Option<S> where S: StringOrStr {}
51impl<S> OptionStringOrStr for Option<S>
52where
53    S: StringOrStr,
54{
55    fn to_option_string(self) -> Option<String> {
56        self.map(StringOrStr::to_string)
57    }
58}
59
60/// A trait implemented by `N` and `NonZero<N>`, where N is an integer type.
61pub trait PossiblyBoundsChecked<N>: seal::Sealed {
62    /// Convert this object to an instance of `N`.
63    fn to_unchecked(self) -> N;
64}
65/// A trait implemented by `N`, `NonZero<N>`, `Option<N>`, and `Option<NonZero<N>>`, where N is an
66/// integer type.
67pub trait OptionPossiblyBoundsChecked<N>: seal::Sealed {
68    /// Convert this object to an instance of `Option<N>`.
69    fn to_option_unchecked(self) -> Option<N>;
70}
71
72/// Implement [`PossiblyBoundsChecked`] and [`OptionPossiblyBoundsChecked`]
73/// for a space-separated list of integer types.
74macro_rules! impl_possibly_bounds_checked {
75    { $($num:ty)+ } => {
76        $(
77            impl seal::Sealed for $num {}
78            impl seal::Sealed for NonZero<$num> {}
79            impl seal::Sealed for Option<$num> {}
80            impl seal::Sealed for Option<NonZero<$num>> {}
81
82            impl PossiblyBoundsChecked<$num> for $num {
83                fn to_unchecked(self) -> $num {
84                    self
85                }
86            }
87            impl PossiblyBoundsChecked<$num> for NonZero<$num> {
88                fn to_unchecked(self) -> $num {
89                    self.get()
90                }
91            }
92            impl OptionPossiblyBoundsChecked<$num> for $num {
93                fn to_option_unchecked(self) -> Option<$num> {
94                    Some(self)
95                }
96            }
97            impl OptionPossiblyBoundsChecked<$num> for Option<$num> {
98                fn to_option_unchecked(self) -> Option<$num> {
99                    self
100                }
101            }
102            impl OptionPossiblyBoundsChecked<$num> for NonZero<$num> {
103                fn to_option_unchecked(self) -> Option<$num> {
104                    Some(self.get())
105                }
106            }
107            impl OptionPossiblyBoundsChecked<$num> for Option<NonZero<$num>> {
108                fn to_option_unchecked(self) -> Option<$num> {
109                    self.map(|v| v.get())
110                }
111            }
112         )+
113    }
114}
115impl_possibly_bounds_checked! { u8 u16 u32 u64 u128 }
116
117/// A trait implemented by `T` and `Option<T>`.
118pub trait PossiblyOption<T>: seal::SealedPossiblyOption<T> {
119    /// Convert this object into an `Option<T>`
120    fn to_option(self) -> Option<T>;
121}
122impl<T> seal::SealedPossiblyOption<T> for T {}
123impl<T> seal::SealedPossiblyOption<T> for Option<T> {}
124
125impl<T> PossiblyOption<T> for T {
126    fn to_option(self) -> Option<T> {
127        Some(self)
128    }
129}
130impl<T> PossiblyOption<T> for Option<T> {
131    fn to_option(self) -> Option<T> {
132        self
133    }
134}