mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
The new version of rust allows us to elide some lifetimes and clippy is now complaining about this. This change elides them where possible and removes the clippy exceptions. Fixes #34804. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
643 lines
17 KiB
Rust
643 lines
17 KiB
Rust
// Copyright 2023 The Servo Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
//! This crate provides wrappers and convenience functions to make Hyper and
|
|
//! Serde work hand in hand.
|
|
//!
|
|
//! The supported types are:
|
|
//!
|
|
//! * `cookie::Cookie`
|
|
//! * `headers_ext::ContentType`
|
|
//! * `hyper::header::Headers`
|
|
//! * `hyper::StatusCode`
|
|
//! * `hyper::Method`
|
|
//! * `hyper::Uri`
|
|
//! * `mime::Mime`
|
|
//!
|
|
//! # How do I use a data type with a `HeaderMap` member with Serde?
|
|
//!
|
|
//! Use the serde attributes `deserialize_with` and `serialize_with`.
|
|
//!
|
|
//! ```
|
|
//! struct MyStruct {
|
|
//! #[serde(deserialize_with = "hyper_serde::deserialize",
|
|
//! serialize_with = "hyper_serde::serialize")]
|
|
//! headers: HeaderMap,
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! # How do I encode a `HeaderMap` value with `serde_json::to_string`?
|
|
//!
|
|
//! Use the `Ser` wrapper.
|
|
//!
|
|
//! ```
|
|
//! serde_json::to_string(&Ser::new(&headers))
|
|
//! ```
|
|
//!
|
|
//! # How do I decode a `Method` value with `serde_json::parse`?
|
|
//!
|
|
//! Use the `De` wrapper.
|
|
//!
|
|
//! ```
|
|
//! serde_json::parse::<De<Method>>("\"PUT\"").map(De::into_inner)
|
|
//! ```
|
|
//!
|
|
//! # How do I send `Cookie` values as part of an IPC channel?
|
|
//!
|
|
//! Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for
|
|
//! convenience.
|
|
//!
|
|
//! ```
|
|
//! ipc::channel::<Serde<Cookie>>()
|
|
//! ```
|
|
//!
|
|
//!
|
|
|
|
#![deny(missing_docs)]
|
|
#![deny(unsafe_code)]
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
use std::str::FromStr;
|
|
use std::{cmp, fmt, str};
|
|
|
|
use cookie::Cookie;
|
|
use headers::ContentType;
|
|
use http::HeaderMap;
|
|
use hyper::header::{HeaderName, HeaderValue};
|
|
use hyper::{Method, StatusCode, Uri};
|
|
use mime::Mime;
|
|
use serde::de::{self, Error, MapAccess, SeqAccess, Visitor};
|
|
use serde::ser::{SerializeMap, SerializeSeq};
|
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
use serde_bytes::{ByteBuf, Bytes};
|
|
|
|
/// Deserialises a `T` value with a given deserializer.
|
|
///
|
|
/// This is useful to deserialize Hyper types used in structure fields or
|
|
/// tuple members with `#[serde(deserialize_with = "hyper_serde::deserialize")]`.
|
|
#[inline(always)]
|
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
De<T>: Deserialize<'de>,
|
|
{
|
|
De::deserialize(deserializer).map(De::into_inner)
|
|
}
|
|
|
|
/// Serialises `value` with a given serializer.
|
|
///
|
|
/// This is useful to serialize Hyper types used in structure fields or
|
|
/// tuple members with `#[serde(serialize_with = "hyper_serde::serialize")]`.
|
|
#[inline(always)]
|
|
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
Ser::new(value).serialize(serializer)
|
|
}
|
|
|
|
/// Serialises `value` with a given serializer in a pretty way.
|
|
///
|
|
/// This does the same job as `serialize` but with a prettier format
|
|
/// for some combinations of types and serialisers.
|
|
///
|
|
/// For now, the only change from `serialize` is when serialising `Headers`,
|
|
/// where the items in the header values get serialised as strings instead
|
|
/// of sequences of bytes, if they represent UTF-8 text.
|
|
#[inline(always)]
|
|
pub fn serialize_pretty<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
Ser::new_pretty(value).serialize(serializer)
|
|
}
|
|
|
|
/// A wrapper to deserialize Hyper types.
|
|
///
|
|
/// This is useful with functions such as `serde_json::from_str`.
|
|
///
|
|
/// Values of this type can only be obtained through
|
|
/// the `serde::Deserialize` trait.
|
|
#[derive(Debug, PartialEq)]
|
|
pub struct De<T> {
|
|
v: T,
|
|
}
|
|
|
|
impl<T> De<T> {
|
|
/// Returns a new `De` wrapper
|
|
#[inline(always)]
|
|
pub fn new(v: T) -> Self {
|
|
De { v }
|
|
}
|
|
}
|
|
|
|
impl<'de, T> De<T>
|
|
where
|
|
De<T>: Deserialize<'de>,
|
|
{
|
|
/// Consumes this wrapper, returning the deserialized value.
|
|
#[inline(always)]
|
|
pub fn into_inner(self) -> T {
|
|
self.v
|
|
}
|
|
}
|
|
|
|
/// A wrapper to serialize Hyper types.
|
|
///
|
|
/// This is useful with functions such as `serde_json::to_string`.
|
|
///
|
|
/// Values of this type can only be passed to the `serde::Serialize` trait.
|
|
#[derive(Debug)]
|
|
pub struct Ser<'a, T: 'a> {
|
|
v: &'a T,
|
|
pretty: bool,
|
|
}
|
|
|
|
impl<'a, T> Ser<'a, T>
|
|
where
|
|
Ser<'a, T>: serde::Serialize,
|
|
{
|
|
/// Returns a new `Ser` wrapper.
|
|
#[inline(always)]
|
|
pub fn new(value: &'a T) -> Self {
|
|
Ser {
|
|
v: value,
|
|
pretty: false,
|
|
}
|
|
}
|
|
|
|
/// Returns a new `Ser` wrapper, in pretty mode.
|
|
///
|
|
/// See `serialize_pretty`.
|
|
#[inline(always)]
|
|
pub fn new_pretty(value: &'a T) -> Self {
|
|
Ser {
|
|
v: value,
|
|
pretty: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A convenience wrapper to be used as a type parameter, for example when
|
|
/// a `Vec<T>` need to be passed to serde.
|
|
#[derive(Clone, PartialEq)]
|
|
pub struct Serde<T>(pub T)
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize;
|
|
|
|
impl<T> Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
/// Consumes this wrapper, returning the inner value.
|
|
#[inline(always)]
|
|
pub fn into_inner(self) -> T {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl<T> fmt::Debug for Serde<T>
|
|
where
|
|
T: fmt::Debug,
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
self.0.fmt(formatter)
|
|
}
|
|
}
|
|
|
|
impl<T> Deref for Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &T {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<T> DerefMut for Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
fn deref_mut(&mut self) -> &mut T {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
impl<T: PartialEq> PartialEq<T> for Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
fn eq(&self, other: &T) -> bool {
|
|
self.0 == *other
|
|
}
|
|
}
|
|
|
|
impl<'b, T> Deserialize<'b> for Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'b>,
|
|
{
|
|
De::deserialize(deserializer).map(De::into_inner).map(Serde)
|
|
}
|
|
}
|
|
|
|
impl<T> Serialize for Serde<T>
|
|
where
|
|
for<'de> De<T>: Deserialize<'de>,
|
|
for<'a> Ser<'a, T>: Serialize,
|
|
{
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
Ser::new(&self.0).serialize(serializer)
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<ContentType> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
deserialize(deserializer)
|
|
.map(|v: mime::Mime| ContentType::from(v))
|
|
.map(De::new)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, ContentType> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
serialize(&mime::Mime::from(self.v.clone()), serializer)
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<Cookie<'static>> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct CookieVisitor;
|
|
|
|
impl Visitor<'_> for CookieVisitor {
|
|
type Value = De<Cookie<'static>>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "an HTTP cookie header value")
|
|
}
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Cookie::parse(v)
|
|
.map(Cookie::into_owned)
|
|
.map(De::new)
|
|
.map_err(|e| E::custom(format!("{:?}", e)))
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_string(CookieVisitor)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, Cookie<'_>> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
serializer.serialize_str(&self.v.to_string())
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<HeaderMap> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct HeadersVisitor;
|
|
|
|
impl<'de> Visitor<'de> for HeadersVisitor {
|
|
type Value = De<HeaderMap>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "a map from header names to header values")
|
|
}
|
|
|
|
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(De::new(HeaderMap::new()))
|
|
}
|
|
|
|
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
|
where
|
|
V: MapAccess<'de>,
|
|
{
|
|
let mut headers = HeaderMap::new();
|
|
while let Some((k, values)) = visitor.next_entry::<String, Value>()? {
|
|
for v in values.0.iter() {
|
|
headers.append(
|
|
HeaderName::from_str(&k).map_err(V::Error::custom)?,
|
|
HeaderValue::from_bytes(v).map_err(V::Error::custom)?,
|
|
);
|
|
}
|
|
}
|
|
Ok(De::new(headers))
|
|
}
|
|
}
|
|
|
|
struct Value(Vec<Vec<u8>>);
|
|
|
|
impl<'de> Deserialize<'de> for Value {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
deserializer.deserialize_seq(ValueVisitor)
|
|
}
|
|
}
|
|
|
|
struct ValueVisitor;
|
|
|
|
impl<'de> Visitor<'de> for ValueVisitor {
|
|
type Value = Value;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "an array of strings and sequences of bytes")
|
|
}
|
|
|
|
fn visit_unit<E>(self) -> Result<Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(Value(vec![]))
|
|
}
|
|
|
|
fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
|
|
where
|
|
V: SeqAccess<'de>,
|
|
{
|
|
// Clamp to not OOM on rogue values.
|
|
let capacity = cmp::min(visitor.size_hint().unwrap_or(0), 64);
|
|
let mut values = Vec::with_capacity(capacity);
|
|
while let Some(v) = visitor.next_element::<ByteBuf>()? {
|
|
values.push(v.into_vec());
|
|
}
|
|
Ok(Value(values))
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_map(HeadersVisitor)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, HeaderMap> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
struct Value<'headers>(&'headers [Vec<u8>], bool);
|
|
|
|
impl Serialize for Value<'_> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut serializer = serializer.serialize_seq(Some(self.0.len()))?;
|
|
for v in self.0 {
|
|
if self.1 {
|
|
if let Ok(v) = str::from_utf8(v) {
|
|
serializer.serialize_element(v)?;
|
|
continue;
|
|
}
|
|
}
|
|
serializer.serialize_element(&Bytes::new(v))?;
|
|
}
|
|
serializer.end()
|
|
}
|
|
}
|
|
|
|
let mut serializer = serializer.serialize_map(Some(self.v.keys_len()))?;
|
|
for name in self.v.keys() {
|
|
let values = self.v.get_all(name);
|
|
serializer.serialize_entry(
|
|
name.as_str(),
|
|
&Value(
|
|
&values
|
|
.iter()
|
|
.map(|v| v.as_bytes().to_vec())
|
|
.collect::<Vec<Vec<u8>>>(),
|
|
self.pretty,
|
|
),
|
|
)?;
|
|
}
|
|
serializer.end()
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<Method> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct MethodVisitor;
|
|
|
|
impl Visitor<'_> for MethodVisitor {
|
|
type Value = De<Method>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "an HTTP method")
|
|
}
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
v.parse::<Method>().map(De::new).map_err(E::custom)
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_string(MethodVisitor)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, Method> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
Serialize::serialize(self.v.as_ref(), serializer)
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<Mime> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct MimeVisitor;
|
|
|
|
impl Visitor<'_> for MimeVisitor {
|
|
type Value = De<Mime>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "a mime type")
|
|
}
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
v.parse::<Mime>()
|
|
.map(De::new)
|
|
.map_err(|_| E::custom("could not parse mime type"))
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_string(MimeVisitor)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, Mime> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
serializer.serialize_str(self.v.as_ref())
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<StatusCode> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
let code = Deserialize::deserialize(deserializer)?;
|
|
Ok(De::new(
|
|
StatusCode::from_u16(code).map_err(D::Error::custom)?,
|
|
))
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, StatusCode> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
self.v.as_u16().serialize(serializer)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, (StatusCode, String)> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut serializer = serializer.serialize_seq(Some(2))?;
|
|
serializer.serialize_element(&Ser::new(&self.v.0))?;
|
|
serializer.serialize_element(&self.v.1)?;
|
|
serializer.end()
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<(StatusCode, String)> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
Ok(De::new(deserializer.deserialize_seq(StatusVisitor)?))
|
|
}
|
|
}
|
|
|
|
struct StatusVisitor;
|
|
|
|
impl<'de> Visitor<'de> for StatusVisitor {
|
|
type Value = (StatusCode, String);
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
formatter,
|
|
"an array containing a status code and a reason string"
|
|
)
|
|
}
|
|
|
|
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
|
where
|
|
V: SeqAccess<'de>,
|
|
{
|
|
let code = visitor
|
|
.next_element::<u16>()?
|
|
.ok_or_else(|| V::Error::custom("Can't find the status code"))?;
|
|
let code = StatusCode::from_u16(code).map_err(V::Error::custom)?;
|
|
let reason = visitor
|
|
.next_element::<String>()?
|
|
.ok_or_else(|| V::Error::custom("Can't find the reason string"))?;
|
|
Ok((code, reason))
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for De<Uri> {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
struct UriVisitor;
|
|
|
|
impl Visitor<'_> for UriVisitor {
|
|
type Value = De<Uri>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(formatter, "an HTTP Uri value")
|
|
}
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Uri::from_str(v)
|
|
.map(De::new)
|
|
.map_err(|e| E::custom(format!("{}", e)))
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_string(UriVisitor)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Ser<'_, Uri> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
// As of hyper 0.12, hyper::Uri (re-exported http::Uri)
|
|
// does not implement as_ref due to underlying implementation
|
|
// so we must construct a string to serialize it
|
|
serializer.serialize_str(&self.v.to_string())
|
|
}
|
|
}
|