summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2016-09-02 19:10:46 +0200
committerYorhel <git@yorhel.nl>2016-09-02 19:10:46 +0200
commit39eb2ac55f5b8f4192064f1c05e6c77b8ca11eaa (patch)
tree04798e75286d6c6167f34f23f73728910d2ccd9b
Initial commit. Mostly learning Rust
-rw-r--r--.gitignore2
-rw-r--r--Cargo.lock129
-rw-r--r--Cargo.toml10
-rw-r--r--src/config.rs131
-rw-r--r--src/main.rs68
5 files changed, 340 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6262ea
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target
+*.swp
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..728b178
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,129 @@
+[root]
+name = "webs"
+version = "0.1.0"
+dependencies = [
+ "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "getopts"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "nom"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "regex"
+version = "0.1.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "thread-id"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "utf8-ranges"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
+"checksum env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82dcb9ceed3868a03b335657b85a159736c961900f7e7747d3b0b97b9ccb5ccb"
+"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2"
+"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
+"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
+"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
+"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
+"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
+"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
+"checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
+"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..9a6c76d
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "webs"
+version = "0.1.0"
+authors = ["Yorhel <git@yorhel.nl>"]
+
+[dependencies]
+log = "0.*"
+env_logger = "0.*"
+getopts = "0.2"
+nom = "1.2"
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..7d01c77
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,131 @@
+use std;
+use nom;
+use std::str;
+use std::net::SocketAddr;
+use nom::{IResult,Input,Consumer,ConsumerState,Move,Producer,HexDisplay};
+use nom::{alphanumeric,space,multispace,line_ending,not_line_ending};
+
+#[derive(Debug,Clone)]
+pub struct Interface {
+ addr: Vec<SocketAddr>
+}
+
+#[derive(Debug,Clone)]
+pub struct Config {
+ itf: Vec<Interface>
+}
+
+
+#[derive(Debug)]
+pub enum Err {
+ Io(std::io::Error),
+ Parse(()) // TODO: error info
+}
+
+
+#[derive(Debug,PartialEq,Eq)]
+enum Expr<'a> {
+ Keyval(&'a str,&'a str),
+ Interface(&'a str),
+ Close,
+ Comment
+}
+
+enum ParseState {
+ Root,
+ Interface
+}
+
+named!(one_multispace, value!(b" ", one_of!(" \t\r\n")));
+
+named!(keyval<&[u8],Expr>, chain!(
+ key: map_res!(alphanumeric, std::str::from_utf8) ~
+ space ~
+ val: map_res!(not_line_ending, std::str::from_utf8) ~
+ line_ending,
+ ||{ Expr::Keyval(key, val.trim()) }
+));
+
+named!(expr<&[u8],Expr>,
+ // The switch!() macro doesn't support wildcard, so put keyval in an alt!()
+ alt!(
+ switch!(peek!(alt!(tag!("#") | tag!("}") | one_multispace)),
+ b" " => value!(Expr::Comment, multispace) |
+ b"#" => value!(Expr::Comment, delimited!(tag!("#"), not_line_ending, line_ending)) |
+ b"}" => value!(Expr::Close, take!(1))
+ ) | keyval
+ )
+);
+
+
+struct ConfigConsumer {
+ c_state: ConsumerState<(), (), nom::Move>,
+ state: ParseState,
+ cfg: Config
+}
+
+
+impl<'a> Consumer<&'a[u8], (), (), nom::Move> for ConfigConsumer {
+ fn handle(&mut self, input: Input<&[u8]>) -> &ConsumerState<(), (), nom::Move> {
+ match input {
+ Input::Eof(None) => { self.c_state = ConsumerState::Done(Move::Consume(0), ()); },
+ Input::Empty => { self.c_state = ConsumerState::Continue(Move::Consume(0)); },
+ Input::Element(x) | Input::Eof(Some(x)) => {
+ match expr(x) {
+ IResult::Done(i, e) => {
+ println!("{:?}", e);
+ // TODO: Pass to state handler (if not comment)
+ self.c_state = ConsumerState::Continue(Move::Consume(x.offset(i)));
+ },
+ IResult::Error(_) => { self.c_state = ConsumerState::Error(()); },
+ IResult::Incomplete(i) => { self.c_state = ConsumerState::Continue(Move::Await(i)); }
+ }
+ }
+ }
+ &self.c_state
+ }
+
+ fn state(&self) -> &ConsumerState<(), (), nom::Move> {
+ &self.c_state
+ }
+}
+
+
+impl Config {
+ fn new() -> Config {
+ Config {
+ itf: Vec::new()
+ }
+ }
+
+ pub fn parse(file: &str) -> Result<Config, Err> {
+ let mut p = try!(nom::FileProducer::new(file, 4096).map_err(Err::Io));
+ let mut c = ConfigConsumer{
+ state: ParseState::Root,
+ c_state: ConsumerState::Continue(Move::Consume(0)),
+ cfg: Config::new()
+ };
+ loop {
+ match *p.apply(&mut c) {
+ ConsumerState::Done(_, x) => { return Ok(c.cfg) }
+ ConsumerState::Error(e) => { return Result::Err(Err::Parse(e)) }
+ ConsumerState::Continue(_) => {}
+ }
+ }
+ }
+}
+
+
+#[test]
+fn parse_expr() {
+ let x = |e| { IResult::Done(&b"x"[..], e) };
+ assert_eq!(expr(b" \r\n\tx"), x(Expr::Comment));
+ assert_eq!(expr(b"\nx"), x(Expr::Comment));
+ assert_eq!(expr(b"#\nx"), x(Expr::Comment));
+ assert_eq!(expr(b"##/!@$% \nx"), x(Expr::Comment));
+ assert_eq!(expr(b"}x"), x(Expr::Close));
+ assert_eq!(expr(b"key val\nx"), x(Expr::Keyval("key", "val")));
+ assert_eq!(expr(b"ke\t v a \nx"), x(Expr::Keyval("ke", "v a")));
+ assert_eq!(expr(b""), IResult::Incomplete(nom::Needed::Size(1)));
+ assert_eq!(expr(b"something"), IResult::Error(nom::Err::Position(nom::ErrorKind::Alt, &b"something"[..])));
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..215670d
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,68 @@
+// I'm playing around. Let me.
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_mut)]
+#![allow(unused_imports)]
+
+#[macro_use] extern crate nom;
+#[macro_use] extern crate log;
+extern crate env_logger;
+extern crate getopts;
+
+
+use std::process::exit;
+use std::io::prelude::*;
+
+mod config;
+
+
+struct CliOpts {
+ config: String,
+}
+
+impl CliOpts {
+ fn new() -> CliOpts {
+ CliOpts {
+ config: "/etc/webs.conf".to_string()
+ }
+ }
+
+ fn parse(mut self) -> CliOpts {
+ let mut args = std::env::args();
+ let prog = args.next().unwrap();
+
+ let mut opts = getopts::Options::new();
+ opts.optflag("h", "help", "print this help menu");
+ opts.optflag("V", "version", "show program version");
+ opts.optopt("c", "config", "config file", "FILE");
+
+ let m = match opts.parse(args) {
+ Ok(m) => { m }
+ Err(e) => {
+ let _ = writeln!(std::io::stderr(), "{}", e);
+ exit(1);
+ }
+ };
+ if m.opt_present("h") {
+ let _ = println!("{}", opts.usage(&prog));
+ exit(0);
+ }
+ if m.opt_present("V") {
+ let _ = println!("{} {}", prog, option_env!("CARGO_PKG_VERSION").unwrap_or(""));
+ exit(0);
+ }
+ if let Some(f) = m.opt_str("c") {
+ self.config = f;
+ }
+
+ self
+ }
+}
+
+
+fn main() {
+ let opts = CliOpts::new().parse();
+ let conf = config::Config::parse(&opts.config);
+ println!("{:?}", conf);
+ env_logger::init().unwrap();
+}