Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add faster serde serialization, sacrificing invariant-safety for speed in release mode; test that it roudtrips #252

Closed
wants to merge 4 commits into from

Use serialize_efficient and deserialize_efficient instead of hijackin…

…g regular Serialize impl
  • Loading branch information
Manishearth committed Dec 18, 2016
commit 1c00b566133a397f74f6bfacc8f2e06f178dedec
@@ -3,6 +3,8 @@ rust:
- nightly
- beta
- stable
script: make test
script:
- make test
- cd serde-code-generator && cargo run && diff="$(git diff)" && echo "${diff}" && [[ -z "${diff}" ]]
notifications:
webhooks: http://build.servo.org:54856/travis
@@ -1510,13 +1510,11 @@ impl rustc_serialize::Decodable for Url {
}
}

/// Serializes this URL into a `serde` stream.
///
/// This implementation is only available if the `serde` Cargo feature is enabled.
#[cfg(feature="serde")]
#[deny(unused)]
impl serde::Serialize for Url {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer {
impl Url {
/// Serialize the URL efficiently, for use with IPC
pub fn serialize_efficient<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer {

This comment has been minimized.

@nox

nox Dec 18, 2016

Member

Please don't name if efficient. Its main property is that it is risky, not efficient.

This comment has been minimized.

@Manishearth

Manishearth Dec 18, 2016

Author Member

Renamed to _unsafe

use serde::Serialize;
// Destructuring first lets us ensure that adding or removing fields forces this method
// to be updated
let Url { ref serialization, ref scheme_end,
@@ -1528,15 +1526,16 @@ impl serde::Serialize for Url {
host_start, host_end, host, port, path_start,
query_start, fragment_start).serialize(serializer)
}
}

/// Deserializes this URL from a `serde` stream.
///
/// This implementation is only available if the `serde` Cargo feature is enabled.
#[cfg(feature="serde")]
#[deny(unused)]
impl serde::Deserialize for Url {
fn deserialize<D>(deserializer: &mut D) -> Result<Url, D::Error> where D: serde::Deserializer {
/// Deserialize the URL efficiently, without re-parsing
///
/// Deserializer must be known to contain the output of serialize_efficient
///
/// Cannot cause memory unsafety if used incorrectly, but may cause security issues.
/// Only use with trusted input.
pub fn deserialize_efficient<D>(deserializer: &mut D)
-> Result<Url, D::Error>
where D: serde::Deserializer {
use serde::{Deserialize, Error};
let (serialization, scheme_end, username_end,
host_start, host_end, host, port, path_start,
@@ -1561,6 +1560,28 @@ impl serde::Deserialize for Url {
Ok(url)
}
}
/// Serializes this URL into a `serde` stream.
///
/// This implementation is only available if the `serde` Cargo feature is enabled.
#[cfg(feature="serde")]
#[deny(unused)]
impl serde::Serialize for Url {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer {
format!("{}", self).serialize(serializer)
}
}

/// Deserializes this URL from a `serde` stream.
///
/// This implementation is only available if the `serde` Cargo feature is enabled.
#[cfg(feature="serde")]
#[deny(unused)]
impl serde::Deserialize for Url {
fn deserialize<D>(deserializer: &mut D) -> Result<Url, D::Error> where D: serde::Deserializer {
let string_representation: String = try!(serde::Deserialize::deserialize(deserializer));
Ok(Url::parse(&string_representation).unwrap())
}
}

#[cfg(any(unix, target_os = "redox"))]
fn path_to_file_url_segments(path: &Path, serialization: &mut String) -> Result<(), ()> {
@@ -22,9 +22,15 @@ fn assert_invariants(url: &Url) {
url.assert_invariants();
#[cfg(feature="serde")] {
use bincode::SizeLimit;
use bincode::serde::{deserialize, serialize};
let bytes = serialize(url, SizeLimit::Infinite).unwrap();
let new_url: Url = deserialize(&bytes).unwrap();
use bincode::serde::{Deserializer, Serializer};
let mut write = Vec::<u8>::new();
{
let mut serializer = Serializer::new(&mut write);
url.serialize_efficient(&mut serializer).unwrap();
}
let mut read = &*write;
let mut deserializer = Deserializer::new(&mut read, SizeLimit::Infinite);
let new_url = Url::deserialize_efficient(&mut deserializer).unwrap();
assert_eq!(url, &new_url);
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.