summaryrefslogtreecommitdiffstats
path: root/third_party/rust/webrtc-sdp/src/address.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/webrtc-sdp/src/address.rs')
-rw-r--r--third_party/rust/webrtc-sdp/src/address.rs199
1 files changed, 199 insertions, 0 deletions
diff --git a/third_party/rust/webrtc-sdp/src/address.rs b/third_party/rust/webrtc-sdp/src/address.rs
new file mode 100644
index 0000000000..cc1087499a
--- /dev/null
+++ b/third_party/rust/webrtc-sdp/src/address.rs
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+extern crate url;
+use self::url::Host;
+use error::SdpParserInternalError;
+use std::convert::TryFrom;
+use std::fmt;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::str::FromStr;
+
+#[derive(Clone, Debug)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+pub enum Address {
+ Fqdn(String),
+ Ip(IpAddr),
+}
+
+impl fmt::Display for Address {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Address::Fqdn(fqdn) => fqdn.fmt(f),
+ Address::Ip(ip) => ip.fmt(f),
+ }
+ }
+}
+
+impl FromStr for Address {
+ type Err = SdpParserInternalError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut e: Option<SdpParserInternalError> = None;
+ if s.find(':').is_some() {
+ match IpAddr::from_str(s) {
+ Ok(ip) => return Ok(Address::Ip(ip)),
+ Err(err) => e = Some(err.into()),
+ }
+ }
+ Host::parse(s)
+ .map(|host| match host {
+ Host::Domain(s) => Address::Fqdn(s),
+ Host::Ipv4(ip) => Address::Ip(IpAddr::V4(ip)),
+ Host::Ipv6(ip) => Address::Ip(IpAddr::V6(ip)),
+ })
+ .map_err(|err| e.unwrap_or_else(|| err.into()))
+ }
+}
+
+impl From<ExplicitlyTypedAddress> for Address {
+ fn from(item: ExplicitlyTypedAddress) -> Self {
+ match item {
+ ExplicitlyTypedAddress::Fqdn { domain, .. } => Address::Fqdn(domain),
+ ExplicitlyTypedAddress::Ip(ip) => Address::Ip(ip),
+ }
+ }
+}
+
+impl PartialEq for Address {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Address::Fqdn(a), Address::Fqdn(b)) => a.to_lowercase() == b.to_lowercase(),
+ (Address::Ip(a), Address::Ip(b)) => a == b,
+ (_, _) => false,
+ }
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+pub enum AddressType {
+ IpV4 = 4,
+ IpV6 = 6,
+}
+
+impl fmt::Display for AddressType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ AddressType::IpV4 => "IP4",
+ AddressType::IpV6 => "IP6",
+ }
+ .fmt(f)
+ }
+}
+
+impl FromStr for AddressType {
+ type Err = SdpParserInternalError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s.to_uppercase().as_str() {
+ "IP4" => Ok(AddressType::IpV4),
+ "IP6" => Ok(AddressType::IpV6),
+ _ => Err(SdpParserInternalError::UnknownAddressType(s.to_owned())),
+ }
+ }
+}
+
+pub trait AddressTyped {
+ fn address_type(&self) -> AddressType;
+}
+
+impl AddressTyped for IpAddr {
+ fn address_type(&self) -> AddressType {
+ match self {
+ IpAddr::V4(_) => AddressType::IpV4,
+ IpAddr::V6(_) => AddressType::IpV6,
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+#[cfg_attr(feature = "serialize", derive(Serialize))]
+pub enum ExplicitlyTypedAddress {
+ Fqdn {
+ address_type: AddressType,
+ domain: String,
+ },
+ Ip(IpAddr),
+}
+
+impl fmt::Display for ExplicitlyTypedAddress {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "IN {} ", self.address_type())?;
+ match self {
+ ExplicitlyTypedAddress::Fqdn { domain, .. } => domain.fmt(f),
+ ExplicitlyTypedAddress::Ip(ip) => ip.fmt(f),
+ }
+ }
+}
+
+impl AddressTyped for ExplicitlyTypedAddress {
+ fn address_type(&self) -> AddressType {
+ match self {
+ ExplicitlyTypedAddress::Fqdn { address_type, .. } => *address_type,
+ ExplicitlyTypedAddress::Ip(ip) => ip.address_type(),
+ }
+ }
+}
+
+impl From<IpAddr> for ExplicitlyTypedAddress {
+ fn from(item: IpAddr) -> Self {
+ ExplicitlyTypedAddress::Ip(item)
+ }
+}
+
+impl From<Ipv4Addr> for ExplicitlyTypedAddress {
+ fn from(item: Ipv4Addr) -> Self {
+ ExplicitlyTypedAddress::Ip(IpAddr::V4(item))
+ }
+}
+
+impl From<Ipv6Addr> for ExplicitlyTypedAddress {
+ fn from(item: Ipv6Addr) -> Self {
+ ExplicitlyTypedAddress::Ip(IpAddr::V6(item))
+ }
+}
+
+impl TryFrom<(AddressType, &str)> for ExplicitlyTypedAddress {
+ type Error = SdpParserInternalError;
+ fn try_from(item: (AddressType, &str)) -> Result<Self, Self::Error> {
+ match Address::from_str(item.1)? {
+ Address::Ip(ip) => {
+ if ip.address_type() != item.0 {
+ Err(SdpParserInternalError::AddressTypeMismatch {
+ found: ip.address_type(),
+ expected: item.0,
+ })
+ } else {
+ Ok(ExplicitlyTypedAddress::Ip(ip))
+ }
+ }
+ Address::Fqdn(domain) => Ok(ExplicitlyTypedAddress::Fqdn {
+ address_type: item.0,
+ domain,
+ }),
+ }
+ }
+}
+
+impl PartialEq for ExplicitlyTypedAddress {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ ExplicitlyTypedAddress::Fqdn {
+ address_type: a1,
+ domain: d1,
+ },
+ ExplicitlyTypedAddress::Fqdn {
+ address_type: a2,
+ domain: d2,
+ },
+ ) => a1 == a2 && d1.to_lowercase() == d2.to_lowercase(),
+ (ExplicitlyTypedAddress::Ip(a), ExplicitlyTypedAddress::Ip(b)) => a == b,
+ (_, _) => false,
+ }
+ }
+}
+
+#[cfg(test)]
+#[path = "./address_tests.rs"]
+mod address_tests;