Skip to content

Commit 013401a

Browse files
committed
feat: add serde serialize/deserialize support
1 parent b10e3f8 commit 013401a

File tree

3 files changed

+76
-5
lines changed

3 files changed

+76
-5
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,20 @@ libcpp = []
2828

2929
[dependencies]
3030
thiserror = "1"
31+
serde = { version = "1.0", optional = true, features = ["derive"] }
3132

3233
[dev-dependencies]
3334
criterion = "0.5"
3435
url = "2" # Used by benchmarks
36+
serde = { version = "1.0", features = ["derive"] }
37+
serde_json = "1.0"
3538

3639
[build-dependencies]
3740
cc = { version = "1.0", features = ["parallel"] }
3841
link_args = "0.6"
42+
43+
[package.metadata.docs.rs]
44+
features = ["serde"]
45+
46+
[package.metadata.playground]
47+
features = ["serde"]

src/lib.rs

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@
1919
//! servo url ▏ 664 ns/URL ███████████▎
2020
//! CURL ▏ 1471 ns/URL █████████████████████████
2121
//! ```
22+
//!
23+
//! # Feature: `serde`
24+
//!
25+
//! If you enable the `serde` feature, [`Url`](struct.Url.html) will implement
26+
//! [`serde::Serialize`](https://docs.rs/serde/1/serde/trait.Serialize.html) and
27+
//! [`serde::Deserialize`](https://docs.rs/serde/1/serde/trait.Deserialize.html).
28+
//! See [serde documentation](https://serde.rs) for more information.
29+
//!
30+
//! ```toml
31+
//! ada-url = { version = "1", features = ["serde"] }
32+
//! ```
2233
2334
pub mod ffi;
2435
mod idna;
@@ -27,21 +38,23 @@ pub use idna::Idna;
2738
use std::{borrow, fmt, hash, ops};
2839
use thiserror::Error;
2940

41+
#[cfg(feature = "serde")]
42+
extern crate serde;
43+
3044
#[derive(Error, Debug)]
3145
pub enum Error {
3246
#[error("Invalid url: \"{0}\"")]
3347
ParseUrl(String),
3448
}
3549

50+
#[derive(Eq)]
3651
pub struct Url {
3752
url: *mut ffi::ada_url,
3853
}
3954

4055
impl Drop for Url {
4156
fn drop(&mut self) {
42-
unsafe {
43-
ffi::ada_free(self.url);
44-
}
57+
unsafe { ffi::ada_free(self.url) }
4558
}
4659
}
4760

@@ -354,15 +367,61 @@ impl Url {
354367
}
355368
}
356369

370+
/// Serializes this URL into a `serde` stream.
371+
///
372+
/// This implementation is only available if the `serde` Cargo feature is enabled.
373+
#[cfg(feature = "serde")]
374+
impl serde::Serialize for Url {
375+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
376+
where
377+
S: serde::Serializer,
378+
{
379+
serializer.serialize_str(self.as_str())
380+
}
381+
}
382+
383+
/// Deserializes this URL from a `serde` stream.
384+
///
385+
/// This implementation is only available if the `serde` Cargo feature is enabled.
386+
#[cfg(feature = "serde")]
387+
impl<'de> serde::Deserialize<'de> for Url {
388+
fn deserialize<D>(deserializer: D) -> Result<Url, D::Error>
389+
where
390+
D: serde::Deserializer<'de>,
391+
{
392+
use serde::de::{Error, Unexpected, Visitor};
393+
394+
struct UrlVisitor;
395+
396+
impl<'de> Visitor<'de> for UrlVisitor {
397+
type Value = Url;
398+
399+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
400+
formatter.write_str("a string representing an URL")
401+
}
402+
403+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
404+
where
405+
E: Error,
406+
{
407+
Url::parse(s, None).map_err(|err| {
408+
let err_s = format!("{}", err);
409+
Error::invalid_value(Unexpected::Str(s), &err_s.as_str())
410+
})
411+
}
412+
}
413+
414+
deserializer.deserialize_str(UrlVisitor)
415+
}
416+
}
417+
357418
/// URLs compare like their stringification.
358419
impl PartialEq for Url {
359420
fn eq(&self, other: &Self) -> bool {
360421
self.href() == other.href()
361422
}
362423
}
363424

364-
impl Eq for Url {}
365-
366425
impl PartialOrd for Url {
367426
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
368427
self.href().partial_cmp(other.href())
@@ -476,6 +535,7 @@ impl ops::Deref for Url {
476535
self.href()
477536
}
478537
}
538+
479539
impl AsRef<str> for Url {
480540
fn as_ref(&self) -> &str {
481541
self.href()

0 commit comments

Comments
 (0)