use crate::{Error, IpType}; #[derive(Debug, PartialEq, Clone)] pub struct Provider { pub v4: Option<&'static str>, pub v6: Option<&'static str>, } impl Provider { pub fn ipify_org() -> Self { Self { v4: Some("https://api.ipify.org"), v6: Some("https://api6.ipify.org") } } pub fn ident_me() -> Self { Self { v4: Some("https://v4.ident.me"), v6: Some("https://v6.ident.me") } } pub fn ip(&self, ip_type: IpType) -> Result, Error> { let uri = match ip_type { IpType::V4 => self.v4.ok_or((ip_type, self))?, IpType::V6 => self.v6.ok_or((ip_type, self))?, }; Ok(http::Request::get(uri).body(&[][..] as &'static [u8])?) } } impl Default for Provider { fn default() -> Self { Self::ident_me() } } impl std::fmt::Display for Provider { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let provider = match self { provider if provider == &Self::ipify_org() => String::from("ipify.org"), provider if provider == &Self::ident_me() => String::from("ident.me"), _ => String::from("unknown"), }; write!(f, "{}", provider) } } impl Into for String { fn into(self) -> Provider { match self.as_ref() { "ipify.org" => Provider::ipify_org(), "ident.me" => Provider::ident_me(), provider => { // TODO: Handle this better // I tried using TryInto here, but I couldn't figure out how to // implement From<>::Error>. log::error!("Couldn't find provider {}, falling back to the default", provider); Provider::default() } } } }