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
/// The different HTTP-Methods as defined by
/// [RFC 2616 5.1.1](https://tools.ietf.org/html/rfc2616#section-5.1.1)
#[derive(Debug, PartialEq, Clone)]
pub enum Method {
    /// Requests the Communication-Options available
    /// for a given Ressource
    OPTIONS,
    /// Retrieves the specified Ressource from the Server
    GET,
    /// Identical to the GET-Method, but the Server is not
    /// required to return a Response-Body
    HEAD,
    /// Used to post Data to the Server
    POST,
    /// Tells the Server to store the supplied Body under a
    /// given Ressource URI
    PUT,
    /// Requests that the given Data assosicated with the
    /// Ressource-URI is deleted
    DELETE,
    /// Used to invoke a remote application-layer loopback
    TRACE,
    /// Reserved
    CONNECT,
}

impl Method {
    /// Parses the raw Method into one of the known Methods,
    /// returns None if the Method is unknown
    pub fn parse(raw_method: &str) -> Option<Method> {
        match raw_method {
            "OPTIONS" => Some(Method::OPTIONS),
            "GET" => Some(Method::GET),
            "HEAD" => Some(Method::HEAD),
            "POST" => Some(Method::POST),
            "PUT" => Some(Method::PUT),
            "DELETE" => Some(Method::DELETE),
            "TRACE" => Some(Method::TRACE),
            "CONNECT" => Some(Method::CONNECT),
            _ => None,
        }
    }

    /// Serializes the Method into a static String
    /// for that Method
    pub fn serialize(&self) -> &'static str {
        match *self {
            Method::OPTIONS => "OPTIONS",
            Method::GET => "GET",
            Method::HEAD => "HEAD",
            Method::POST => "POST",
            Method::PUT => "PUT",
            Method::DELETE => "DELETE",
            Method::TRACE => "TRACE",
            Method::CONNECT => "CONNECT",
        }
    }
}

impl std::fmt::Display for Method {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.serialize())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parse_method_options() {
        assert_eq!(Some(Method::OPTIONS), Method::parse("OPTIONS"));
    }
    #[test]
    fn parse_method_get() {
        assert_eq!(Some(Method::GET), Method::parse("GET"));
    }
    #[test]
    fn parse_method_head() {
        assert_eq!(Some(Method::HEAD), Method::parse("HEAD"));
    }
    #[test]
    fn parse_method_post() {
        assert_eq!(Some(Method::POST), Method::parse("POST"));
    }
    #[test]
    fn parse_method_put() {
        assert_eq!(Some(Method::PUT), Method::parse("PUT"));
    }
    #[test]
    fn parse_method_delete() {
        assert_eq!(Some(Method::DELETE), Method::parse("DELETE"));
    }
    #[test]
    fn parse_method_trace() {
        assert_eq!(Some(Method::TRACE), Method::parse("TRACE"));
    }
    #[test]
    fn parse_method_connect() {
        assert_eq!(Some(Method::CONNECT), Method::parse("CONNECT"));
    }
    #[test]
    fn parse_method_invalid() {
        assert_eq!(None, Method::parse("DIFFERENT"));
    }
}