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
111
112
113
114
115
#[macro_use]
extern crate nereon_derive;
extern crate nereon;
extern crate tiny_http;
mod artifacts;
use nereon::{parse_noc, FromValue, Value};
use std::env;
use std::io::Write;
use std::io::{self, Read};
use tiny_http::{Method, Request, Response, Server, StatusCode};
const NOS: &str = r#"
name noc
authors ["John Hedges <john@drystone.co.uk>"]
version "0.1.0"
license "BSD-2-Clause"
option port {
short p
long "http-port"
key [port]
usage "NOC playground http port"
hint PORT
}"#;
#[derive(FromValue)]
struct Config {
port: Option<u32>,
}
pub fn main() -> Result<(), String> {
let config = nereon::configure::<Config, _, _>(NOS, env::args_os())?;
config
.port
.map_or_else(parse, playground)
.map_err(|e| format!("{:?}", e))
}
fn parse() -> io::Result<()> {
let stdin = io::stdin();
io::stdout().write_all({
let mut noc = String::new();
stdin.lock().read_to_string(&mut noc)?;
parse_noc::<Value>(&noc).unwrap().as_noc_string().as_ref()
})?;
Ok(())
}
fn playground(port: u32) -> io::Result<()> {
Server::http(format!("{}:{}", "127.0.0.1", port))
.and_then(|server| loop {
match server.recv() {
Ok(req) => handle_request(req)?,
Err(e) => return Err(Box::new(e)),
};
}).map_err(|e| *e.downcast::<io::Error>().unwrap())
}
fn handle_request(mut req: Request) -> io::Result<()> {
if req.method() == &Method::Get || req.method() == &Method::Head {
match req.url() {
"/" => req.respond(artifacts::html()),
"/js" => req.respond(artifacts::js()),
"/css" => req.respond(artifacts::css()),
"/favicon.png" => req.respond(artifacts::favicon()),
_ => req.respond(Response::from_string("Not found").with_status_code(StatusCode(404))),
}
} else if req.method() == &Method::Post {
match req.url() {
"/parse" => {
let mut body = String::new();
if req.as_reader().read_to_string(&mut body).is_ok() {
req.respond(Response::from_string(match parse_noc::<Value>(&body) {
Ok(s) => s.as_noc_string_pretty(),
Err(e) => format!("{:?}", e),
}))
} else {
req.respond(
Response::from_string("Non-UTF8 request body")
.with_status_code(StatusCode(400)),
)
}
}
_ => req.respond(Response::from_string("Not found").with_status_code(StatusCode(404))),
}
} else {
req.respond(Response::from_string("Method not allowed").with_status_code(StatusCode(405)))
}
}