use crate::Error;
use std::str::FromStr;
#[derive(PartialEq, Debug)]
pub struct Ext;
impl ToString for Ext {
fn to_string(&self) -> String {
String::new()
}
}
impl FromStr for Ext {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"" => Ok(Self {}),
_ => Err(Error::IncorrectHeader("ext")),
}
}
}
#[derive(PartialEq, Debug, Default)]
pub struct ManDiscover;
impl ToString for ManDiscover {
fn to_string(&self) -> String {
String::from("\"ssdp:discover\"")
}
}
impl FromStr for ManDiscover {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ssdp:discover" | "\"ssdp:discover\"" => Ok(Self {}),
_ => Err(Error::IncorrectHeader("man")),
}
}
}
#[derive(PartialEq, Debug, Hash, Clone)]
pub enum SearchTarget {
All,
RootDevice,
UUID(uuid::Uuid),
Device {
device_type: String,
version: String,
},
Service {
service_type: String,
version: String,
},
VendorDevice {
domain_name: String,
device_type: String,
version: String,
},
VendorService {
domain_name: String,
service_type: String,
version: String,
},
Other(String),
}
impl ToString for SearchTarget {
fn to_string(&self) -> std::string::String {
use SearchTarget::*;
match self {
All => "ssdp:all".to_string(),
RootDevice => "upnp:rootdevice".to_string(),
UUID(uuid) => format!("uuid:{}", uuid.to_string()),
Device {
device_type,
version,
} => format!("urn:schemas-upnp-org:device:{}:{}", device_type, version),
Service {
service_type,
version,
} => format!("urn:schemas-upnp-org:service:{}:{}", service_type, version),
VendorDevice {
domain_name,
device_type,
version,
} => format!("urn:{}:device:{}:{}", domain_name, device_type, version),
VendorService {
domain_name,
service_type,
version,
} => format!("urn:{}:sercvice:{}:{}", domain_name, service_type, version),
Other(s) => s.to_string(),
}
}
}
impl FromStr for SearchTarget {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use SearchTarget::*;
Ok(match s.split(':').collect::<Vec<&str>>().as_slice() {
["ssdp", "all"] => All,
["upnp", "rootdevice"] => RootDevice,
["uuid", uuid] => UUID(uuid::Uuid::parse_str(uuid)?),
["urn", "schemas-upnp-org", "device", dt, v] => Device {
device_type: (*dt).to_string(),
version: (*v).to_string(),
},
["urn", "schemas-upnp-org", "service", st, v] => Service {
service_type: (*st).to_string(),
version: (*v).to_string(),
},
["urn", dn, "device", dt, v] => VendorDevice {
domain_name: (*dn).to_string(),
device_type: (*dt).to_string(),
version: (*v).to_string(),
},
["urn", dn, "service", st, v] => VendorService {
domain_name: (*dn).to_string(),
service_type: (*st).to_string(),
version: (*v).to_string(),
},
_ => Other(s.to_owned()),
})
}
}
impl Default for SearchTarget {
fn default() -> Self {
Self::All
}
}
#[derive(Default, PartialEq, Debug, Hash, Clone)]
pub struct UniqueServiceName {
pub uuid: String,
pub search_target: Option<SearchTarget>,
}
impl FromStr for UniqueServiceName {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split("::").collect::<Vec<&str>>().as_slice() {
[urn, st] if urn.starts_with("uuid:") => {
let uuid = urn[5..].to_string();
st.parse().map(|st| UniqueServiceName {
uuid,
search_target: Some(st),
})
}
[urn] if urn.starts_with("uuid:") => Ok(UniqueServiceName {
uuid: urn[5..].to_string(),
search_target: None,
}),
_ => Err(Error::MalformedHeader("usn", s.to_owned())),
}
}
}
impl ToString for UniqueServiceName {
fn to_string(&self) -> String {
let out = format!("uuid:{}", self.uuid);
if let Some(st) = &self.search_target {
format!("{}::{}", out, st.to_string())
} else {
out
}
}
}