aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Pasquet <dev@etenil.net>2021-11-14 22:50:17 +0000
committerGuillaume Pasquet <dev@etenil.net>2021-11-14 22:50:17 +0000
commitc9486ece952d2e07a78192a9ae0e7764fdee4164 (patch)
tree1fd086959e4fc7cbe52a1228acfa1b62cc26ac38 /src
parentfce52576205ebbb6b03a466b8f9a137c45420fde (diff)
First working version of the barbfile parser
Diffstat (limited to 'src')
-rw-r--r--src/barbfile.rs168
-rw-r--r--src/main.rs9
2 files changed, 177 insertions, 0 deletions
diff --git a/src/barbfile.rs b/src/barbfile.rs
new file mode 100644
index 0000000..be7cead
--- /dev/null
+++ b/src/barbfile.rs
@@ -0,0 +1,168 @@
+use std::matches;
+use std::str::FromStr;
+use std::{error::Error, fmt};
+
+#[derive(Debug)]
+struct BarbParseError {}
+
+impl Error for BarbParseError {}
+
+impl fmt::Display for BarbParseError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Error parsing barb file")
+ }
+}
+
+enum Method {
+ GET,
+ PUT,
+ POST,
+ PATCH,
+ DELETE,
+}
+
+impl FromStr for Method {
+ type Err = BarbParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "GET" => Ok(Self::GET),
+ "PUT" => Ok(Self::PUT),
+ "POST" => Ok(Self::POST),
+ "PATCH" => Ok(Self::PATCH),
+ "DELETE" => Ok(Self::DELETE),
+ _ => Err(BarbParseError {}),
+ }
+ }
+}
+
+#[derive(Debug)]
+struct Header {
+ name: String,
+ value: String,
+}
+
+impl fmt::Display for Header {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}: {}", self.name, self.value)
+ }
+}
+
+struct BarbHeader {
+ pub method: Method,
+ pub url: String,
+ pub headers: Vec<Header>,
+ pub filter: Option<String>,
+}
+
+impl BarbHeader {
+ fn new(method: Method, url: String, headers: Vec<Header>, filter: Option<String>) -> Self {
+ BarbHeader {
+ method: method,
+ url: url,
+ headers: headers,
+ filter: filter,
+ }
+ }
+}
+
+struct BarbFile {
+ header: BarbHeader,
+ body: Option<String>,
+}
+
+fn decode_url_line(line: &str) -> Result<(Method, String), BarbParseError> {
+ let mut components = line[1..].split('^');
+ let meth = components.next().ok_or(BarbParseError {})?;
+ let url = components.next().ok_or(BarbParseError {})?;
+ return Ok((Method::from_str(meth)?, String::from(url)));
+}
+
+fn decode_header(line: &str) -> Result<Header, BarbParseError> {
+ let mut components = line[1..].split(':');
+ let header_name = components.next().ok_or(BarbParseError {})?;
+ let header_val = components.next().ok_or(BarbParseError {})?.trim();
+ Ok(Header {
+ name: String::from(header_name),
+ value: String::from(header_val),
+ })
+}
+
+impl FromStr for BarbFile {
+ type Err = BarbParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut lines = s.split('\n');
+ let (method, url) = decode_url_line(lines.next().ok_or(BarbParseError {})?)?;
+ let mut headers: Vec<Header> = vec![];
+ let mut filter = None;
+ for line in lines {
+ if !matches!(line.chars().nth(0), Some('#')) {
+ break; // Reached the end of the header.
+ }
+
+ if let Some(_) = line.find(':') {
+ headers.push(decode_header(line).unwrap());
+ }
+
+ if let None = filter {
+ filter = match &line[0..2] {
+ "#|" => Some(String::from(&line[2..])),
+ _ => None,
+ }
+ }
+ }
+
+ Ok(BarbFile {
+ header: BarbHeader::new(method, url, headers, filter),
+ body: None,
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_method_from_str() {
+ assert!(matches!(Method::from_str("GET").unwrap(), Method::GET));
+ assert!(matches!(Method::from_str("GET").unwrap(), Method::GET));
+ assert!(matches!(Method::from_str("PUT").unwrap(), Method::PUT));
+ assert!(matches!(Method::from_str("POST").unwrap(), Method::POST));
+ assert!(matches!(Method::from_str("PATCH").unwrap(), Method::PATCH));
+ assert!(matches!(
+ Method::from_str("DELETE").unwrap(),
+ Method::DELETE
+ ));
+ }
+
+ #[test]
+ fn test_decode_url_line() {
+ let (method, url) = decode_url_line("#GET^http://blahblah").unwrap();
+ assert!(matches!(method, Method::GET));
+ assert_eq!(url, "http://blahblah");
+ }
+
+ #[test]
+ fn test_decode_header() {
+ let hdr = decode_header("#Authorization: TOKEN 12345").unwrap();
+ assert_eq!(hdr.name, "Authorization");
+ assert_eq!(hdr.value, "TOKEN 12345");
+ }
+
+ #[test]
+ fn test_parse_barbfile() {
+ let barbfile =
+ BarbFile::from_str("#GET^https://blah.com/api/blah\n#Authorization: BLAH\n#|filtr\n")
+ .unwrap();
+ assert_eq!(barbfile.body, None);
+ assert!(matches!(barbfile.header.method, Method::GET));
+ assert_eq!(barbfile.header.url, "https://blah.com/api/blah");
+ assert_eq!(barbfile.header.filter, Some(String::from("filtr")));
+ println!("{:?}", barbfile.header.headers);
+ assert_eq!(barbfile.header.headers.len(), 1);
+ assert_eq!(barbfile.header.headers[0].name, "Authorization");
+ assert_eq!(barbfile.header.headers[0].value, "BLAH");
+ }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..816bebc
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,9 @@
+mod barbfile;
+
+use std::fs;
+use ureq;
+
+fn main() {
+ let barbfile = fs::read_to_string("test.barb").expect("Failed to read file");
+ ureq::get("https://api.met.no/weatherapi/tafmetar/1.0/tafmetar?icao=EGKK");
+}