Skip to content

Commit 0ab166e

Browse files
author
bors-servo
authored
Auto merge of #521 - servo:serde, r=SimonSapin
Some serde improvements <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/521) <!-- Reviewable:end -->
2 parents 3c71cac + c2ff51b commit 0ab166e

File tree

4 files changed

+29
-78
lines changed

4 files changed

+29
-78
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bencher = "0.1"
4040
idna = { version = "0.2.0", path = "./idna" }
4141
matches = "0.1"
4242
percent-encoding = { version = "2.0.0", path = "./percent_encoding" }
43-
serde = {version = "1.0", optional = true}
43+
serde = {version = "1.0", optional = true, features = ["derive"]}
4444

4545
[[bench]]
4646
name = "parse_url"

src/host.rs

+5-71
Original file line numberDiff line numberDiff line change
@@ -9,57 +9,21 @@
99
use idna;
1010
use parser::{ParseError, ParseResult};
1111
use percent_encoding::{percent_decode, utf8_percent_encode, CONTROLS};
12+
#[cfg(feature = "serde")]
13+
use serde::{Deserialize, Serialize};
1214
use std::cmp;
1315
use std::fmt::{self, Formatter};
1416
use std::net::{Ipv4Addr, Ipv6Addr};
1517

18+
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1619
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
17-
pub enum HostInternal {
20+
pub(crate) enum HostInternal {
1821
None,
1922
Domain,
2023
Ipv4(Ipv4Addr),
2124
Ipv6(Ipv6Addr),
2225
}
2326

24-
#[cfg(feature = "serde")]
25-
impl ::serde::Serialize for HostInternal {
26-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
27-
where
28-
S: ::serde::Serializer,
29-
{
30-
// This doesn’t use `derive` because that involves
31-
// large dependencies (that take a long time to build), and
32-
// either Macros 1.1 which are not stable yet or a cumbersome build script.
33-
//
34-
// Implementing `Serializer` correctly for an enum is tricky,
35-
// so let’s use existing enums that already do.
36-
use std::net::IpAddr;
37-
match *self {
38-
HostInternal::None => None,
39-
HostInternal::Domain => Some(None),
40-
HostInternal::Ipv4(addr) => Some(Some(IpAddr::V4(addr))),
41-
HostInternal::Ipv6(addr) => Some(Some(IpAddr::V6(addr))),
42-
}
43-
.serialize(serializer)
44-
}
45-
}
46-
47-
#[cfg(feature = "serde")]
48-
impl<'de> ::serde::Deserialize<'de> for HostInternal {
49-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
50-
where
51-
D: ::serde::Deserializer<'de>,
52-
{
53-
use std::net::IpAddr;
54-
Ok(match ::serde::Deserialize::deserialize(deserializer)? {
55-
None => HostInternal::None,
56-
Some(None) => HostInternal::Domain,
57-
Some(Some(IpAddr::V4(addr))) => HostInternal::Ipv4(addr),
58-
Some(Some(IpAddr::V6(addr))) => HostInternal::Ipv6(addr),
59-
})
60-
}
61-
}
62-
6327
impl<S> From<Host<S>> for HostInternal {
6428
fn from(host: Host<S>) -> HostInternal {
6529
match host {
@@ -71,6 +35,7 @@ impl<S> From<Host<S>> for HostInternal {
7135
}
7236

7337
/// The host name of an URL.
38+
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
7439
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
7540
pub enum Host<S = String> {
7641
/// A DNS domain name, as '.' dot-separated labels.
@@ -92,37 +57,6 @@ pub enum Host<S = String> {
9257
Ipv6(Ipv6Addr),
9358
}
9459

95-
#[cfg(feature = "serde")]
96-
impl<S: ::serde::Serialize> ::serde::Serialize for Host<S> {
97-
fn serialize<R>(&self, serializer: R) -> Result<R::Ok, R::Error>
98-
where
99-
R: ::serde::Serializer,
100-
{
101-
use std::net::IpAddr;
102-
match *self {
103-
Host::Domain(ref s) => Ok(s),
104-
Host::Ipv4(addr) => Err(IpAddr::V4(addr)),
105-
Host::Ipv6(addr) => Err(IpAddr::V6(addr)),
106-
}
107-
.serialize(serializer)
108-
}
109-
}
110-
111-
#[cfg(feature = "serde")]
112-
impl<'de, S: ::serde::Deserialize<'de>> ::serde::Deserialize<'de> for Host<S> {
113-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
114-
where
115-
D: ::serde::Deserializer<'de>,
116-
{
117-
use std::net::IpAddr;
118-
Ok(match ::serde::Deserialize::deserialize(deserializer)? {
119-
Ok(s) => Host::Domain(s),
120-
Err(IpAddr::V4(addr)) => Host::Ipv4(addr),
121-
Err(IpAddr::V6(addr)) => Host::Ipv6(addr),
122-
})
123-
}
124-
}
125-
12660
impl<'a> Host<&'a str> {
12761
/// Return a copy of `self` that owns an allocated `String` but does not borrow an `&Url`.
12862
pub fn to_owned(&self) -> Host<String> {

src/lib.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -2281,11 +2281,28 @@ impl<'de> serde::Deserialize<'de> for Url {
22812281
where
22822282
D: serde::Deserializer<'de>,
22832283
{
2284-
use serde::de::{Error, Unexpected};
2285-
let string_representation: String = serde::Deserialize::deserialize(deserializer)?;
2286-
Url::parse(&string_representation).map_err(|err| {
2287-
Error::invalid_value(Unexpected::Str(&string_representation), &err.description())
2288-
})
2284+
use serde::de::{Error, Unexpected, Visitor};
2285+
2286+
struct UrlVisitor;
2287+
2288+
impl<'de> Visitor<'de> for UrlVisitor {
2289+
type Value = Url;
2290+
2291+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2292+
formatter.write_str("a string representing an URL")
2293+
}
2294+
2295+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
2296+
where
2297+
E: Error,
2298+
{
2299+
Url::parse(s).map_err(|err| {
2300+
Error::invalid_value(Unexpected::Str(s), &err.description())
2301+
})
2302+
}
2303+
}
2304+
2305+
deserializer.deserialize_str(UrlVisitor)
22892306
}
22902307
}
22912308

src/parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ impl<'a> Parser<'a> {
972972
Ok((host, input))
973973
}
974974

975-
pub fn parse_file_host<'i>(
975+
pub(crate) fn parse_file_host<'i>(
976976
&mut self,
977977
input: Input<'i>,
978978
) -> ParseResult<(bool, HostInternal, Input<'i>)> {

0 commit comments

Comments
 (0)