http-serde-ext 0.1.1

serde support for http crate types Request, Response, Uri, StatusCode, HeaderMap
Documentation
use http::{request::Builder, HeaderMap, Method, Uri, Version};
use serde::{de, Deserialize, Serialize};

type Type<T> = http::Request<T>;
const STRUCT_NAME: &str = "Request";

#[derive(Serialize)]
struct BorrowedHead<'a> {
    #[serde(with = "crate::method")]
    method: &'a Method,
    #[serde(with = "crate::uri")]
    uri: &'a Uri,
    #[serde(with = "crate::header_map")]
    headers: &'a HeaderMap,
    #[serde(with = "crate::version")]
    version: Version,
}

impl<'a, T> From<&'a Type<T>> for BorrowedHead<'a> {
    fn from(val: &'a Type<T>) -> Self {
        Self {
            method: val.method(),
            uri: val.uri(),
            headers: val.headers(),
            version: val.version(),
        }
    }
}

#[derive(Deserialize)]
struct Head {
    #[serde(with = "crate::method")]
    method: Method,
    #[serde(with = "crate::uri")]
    uri: Uri,
    #[serde(with = "crate::header_map")]
    headers: HeaderMap,
    #[serde(with = "crate::version")]
    version: Version,
}

impl Head {
    fn try_into<T, E>(self, body: T) -> Result<Type<T>, E>
    where
        E: de::Error,
    {
        let mut builder = Builder::new()
            .method(self.method)
            .uri(self.uri)
            .version(self.version);

        if let Some(headers) = builder.headers_mut() {
            headers.reserve(self.headers.len());
        }
        let mut curr = None;
        for (k, v) in self.headers.into_iter() {
            if k.is_some() {
                curr = k;
            }
            if let Some(ref name) = curr {
                builder = builder.header(name, v);
            } else {
                return Err(de::Error::custom("invalid headers"));
            }
        }

        builder.body(body).map_err(de::Error::custom)
    }
}

serde_request_response!(Type<T>, STRUCT_NAME, Head, BorrowedHead);

derive_extension_types!(super::Type<T>, T);