Skip to content

Instantly share code, notes, and snippets.

@dustinknopoff
Created August 28, 2019 15:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustinknopoff/f26f575e85425b11aa6da0c48adca7df to your computer and use it in GitHub Desktop.
Save dustinknopoff/f26f575e85425b11aa6da0c48adca7df to your computer and use it in GitHub Desktop.
use std::convert::TryFrom;
#[derive(Debug, Copy, Clone)]
enum HttpMethod {
GET,
POST,
PUT
}
impl TryFrom<String> for HttpMethod {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
use HttpMethod::*;
match value.as_ref() {
"GET" => Ok(GET),
"POST" => Ok(POST),
"PUT" => Ok(PUT),
_ => Err("HTTP Method is invalid.")
}
}
}
#[derive(Debug, Clone)]
struct HttpHeader {
method: HttpMethod,
path: String
}
impl HttpHeader {
fn new(method: HttpMethod, path: String) -> Self {
HttpHeader {
method, path
}
}
}
#[derive(Debug, Default, Clone)]
struct HttpHeaderBuilder {
method: Option<HttpMethod>,
path: Option<String>,
state: Machine
}
impl TryFrom<HttpHeaderBuilder> for HttpHeader {
type Error = &'static str;
fn try_from(value: HttpHeaderBuilder) -> Result<Self, Self::Error> {
if let Some(method) = value.method {
if let Some(path) = value.path {
Ok(HttpHeader::new(method, path))
} else {
Err("No HTTP Method found.")
}
} else {
Err("No HTTP Method found.")
}
}
}
impl HttpHeaderBuilder {
fn extract_value(&mut self, saved: String) {
match self.state {
Machine::METHOD => {
match HttpMethod::try_from(saved) {
Ok(val) => self.method = Some(val),
Err(msg) => panic!(msg)
};
self.state = Machine::PATH;
},
Machine::PATH => {
self.path = Some(saved);
self.state = Machine::VERSION;
}
_ => {}
}
}
}
#[derive(Debug, Copy, Clone)]
enum Machine {
METHOD,
PATH,
VERSION,
FROM,
USER_AGENT
}
impl Default for Machine {
fn default() -> Machine {
Machine::METHOD
}
}
fn main() {
let src = String::from("GET /path/file.html HTTP/1.0
From: someuser@jmarshall.com
User-Agent: HTTPTool/1.0");
let ret:(HttpHeaderBuilder, String) = src.chars().fold((Default::default(), String::new()), |acc, curr| {
let (mut header, mut saved) = acc;
if curr.is_ascii_whitespace() {
header.extract_value(saved);
saved = String::new();
} else {
saved.push(curr);
}
(header, saved)
});
let header = HttpHeader::try_from(ret.0);
dbg!(&header);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment