summaryrefslogtreecommitdiff
path: root/src/parse.rs
blob: 60bfc67d77226d882a550428542c5a7440d64be3 (plain)
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
use crate::header::{Header, HeaderValue, HeaderName};
use crate::error::HTTPError;
use crate::method::Method;
use crate::status::Status;
use crate::uri::{QueryMap, QueryFragment, Authority, Path, Scheme, URI};
use crate::version::Version;
use crate::response::Response;
use crate::request::Request;
use std::convert::{From, TryFrom};
use std::str::FromStr;
use std::borrow::Cow;

pub trait Parse
where
    Self: Sized
{
    fn parse(s: impl Into<String>) -> Self;
}

pub trait TryParse
where
    Self: Sized
{
    fn try_parse(s: impl Into<String>) -> Result<Self, HTTPError>;
}

macro_rules! try_into {
    ($type:ty, $struct:ty) => {
        impl TryFrom<$type> for $struct {
            type Error = HTTPError;
        
            fn try_from(value: $type) -> Result<Self, Self::Error> {
                Self::try_parse(value)
            }
        }
    };
}

macro_rules! try_into_struct {
    ($struct:ty) => {
        impl From<$struct> for String {
            fn from(value: $struct) -> Self {
                value.to_string()
            }
        }
        
        try_into!(String, $struct);
        try_into!(&String, $struct);
        try_into!(&str, $struct);
        try_into!(Cow<'_, str>, $struct);
    };
}

try_into_struct!(Header);
try_into_struct!(HeaderName);
try_into_struct!(QueryMap);
try_into_struct!(QueryFragment);
try_into_struct!(Authority);
try_into_struct!(Path);
try_into_struct!(URI);
try_into_struct!(Status);

macro_rules! try_into_res {
    ($type:ty, $struct:ty) => {
        impl<T: FromStr + ToString> TryFrom<$type> for $struct {
            type Error = HTTPError;
        
            fn try_from(value: $type) -> Result<Self, Self::Error> {
                Self::try_parse(value)
            }
        }
    };
}

macro_rules! try_into_struct_res {
    ($struct:ty) => {
        impl<T: FromStr + ToString> From<$struct> for String {
            fn from(value: $struct) -> Self {
                value.to_string()
            }
        }
        
        try_into_res!(String, $struct);
        try_into_res!(&String, $struct);
        try_into_res!(&str, $struct);
        try_into_res!(Cow<'_, str>, $struct);
    };
}

try_into_struct_res!(Request<T>);
try_into_struct_res!(Response<T>);

macro_rules! into_struct {
    ($struct:ty) => {
        impl<T> From<T> for $struct
        where
            T: Into<String>
        {
            fn from(value: T) -> Self {
                Self::parse(value)
            }
        }

    };
}

into_struct!(Scheme);
into_struct!(HeaderValue);
into_struct!(Method);
into_struct!(Version);