1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! ## [`serde`] extensions for the [`http`] crate types
//!
//! Allows serializing and deserializing the following types from [`http`]:
//! - [`Response`](response)
//! - [`Request`](request)
//! - [`HeaderMap`](header_map)
//! - [`StatusCode`](status_code)
//! - [`Uri`](uri)
//! - [`Method`](method)
//! - [`HeaderName`](header_name)
//! - [`HeaderValue`](header_value)
//! - [`uri::Authority`](authority)
//! - [`uri::Scheme`](scheme)
//! - [`uri::PathAndQuery`](path_and_query)
//! - [`Version`](version)
//! - Generic [`HeaderMap<T>`](header_map_generic) where the item is not a `HeaderValue`
//!
//! Allows serializing and deserializing the above types wrapped in the following `std` container types:
//! - [`Option`]
//! - [`Vec`]
//! - [`VecDeque`](std::collections::VecDeque)
//! - [`LinkedList`](std::collections::LinkedList)
//! - [`HashMap`](std::collections::HashMap) in the `Value` position
//! - [`BTreeMap`](std::collections::BTreeMap) in the `Value` position
//!
//! ## Usage
//!
//! This library is intended to be used with `serde`'s `derive` feature.
//! Fields should use the appropriate `#[serde(with = "...")]` annotation for that
//! type. Full examples are provided in each module section of these docs.
//! ```
//! use std::collections::*;
//!
//! use http::*;
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Serialize, Deserialize)]
//! struct MyStruct {
//!    #[serde(with = "http_serde_ext::response")]
//!    base: Response<Vec<u8>>,
//!
//!    #[serde(with = "http_serde_ext::request::option")]
//!    option: Option<Request<String>>,
//!
//!    #[serde(with = "http_serde_ext::method::vec")]
//!    vec: Vec<Method>,
//!
//!    #[serde(with = "http_serde_ext::uri::vec_deque")]
//!    vec_deque: VecDeque<Uri>,
//!
//!    #[serde(with = "http_serde_ext::header_map::linked_list")]
//!    linked_list: LinkedList<HeaderMap>,
//!
//!    #[serde(with = "http_serde_ext::header_map_generic::hash_map")]
//!    hash_map: HashMap<String, HeaderMap<String>>,
//!
//!    #[serde(with = "http_serde_ext::status_code::btree_map")]
//!    btree_map: BTreeMap<i32, StatusCode>,
//! }
//! ```

#[macro_use]
mod macros;

#[derive(serde::Serialize)]
struct BorrowedNameWrapper<'a>(#[serde(with = "crate::header_name")] &'a http::HeaderName);

#[derive(serde::Deserialize)]
#[serde(untagged)]
enum Either<T> {
    One(T),
    Many(Vec<T>),
}

macro_rules! doc_mod {
    ($ty:ty, $path:ident$(, $generic:ident)?$(; $extra:expr)?) => {
        #[doc = concat!(" [`Serialize`](serde::Serialize)/[`Deserialize`](serde::Deserialize) for [`http::"$(, $extra)?, stringify!($ty), "`]")]
        ///
        /// ```
        /// use std::{cmp::Ord, collections::*, hash::Hash};
        ///
        #[doc = concat!("use http::", $($extra,)? stringify!($ty), ";")]
        /// use serde::{Serialize, Deserialize};
        ///
        /// #[derive(Serialize, Deserialize)]
        #[doc = concat!("struct MyStruct<T", $(", ", stringify!($generic), )?">")]
        /// where
        ///     T: Serialize + for<'a> Deserialize<'a> + Hash + Ord,
        $(#[doc = concat!("    ", stringify!($generic), ": Serialize + for<'a> Deserialize<'a>,") ])?
        /// {
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "\")]")]
        #[doc = concat!("    base: ", stringify!($ty), $("<", stringify!($generic), ">",)? ",")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::option\")]")]
        #[doc = concat!("    option: Option<", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::vec\")]")]
        #[doc = concat!("    vec: Vec<", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::vec_deque\")]")]
        #[doc = concat!("    vec_deque: VecDeque<", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::linked_list\")]")]
        #[doc = concat!("    linked_list: LinkedList<", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::hash_map\")]")]
        #[doc = concat!("    hash_map: HashMap<T, ", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        ///
        #[doc = concat!("    #[serde(with = \"http_serde_ext::", stringify!($path), "::btree_map\")]")]
        #[doc = concat!("    btree_map: BTreeMap<T, ", stringify!($ty), $("<", stringify!($generic), ">",)? ">,")]
        /// }
        /// ```
        pub mod $path;
    };
}

doc_mod!(Authority, authority; "uri::");
doc_mod!(HeaderMap, header_map);
doc_mod!(HeaderMap, header_map_generic, U);
doc_mod!(HeaderName, header_name);
doc_mod!(HeaderValue, header_value);
doc_mod!(Method, method);
doc_mod!(PathAndQuery, path_and_query; "uri::");
doc_mod!(Request, request, U);
doc_mod!(Response, response, U);
doc_mod!(Scheme, scheme; "uri::");
doc_mod!(StatusCode, status_code);
doc_mod!(Uri, uri);
doc_mod!(Version, version);