<commit_before>// Copyright 2015 Gomez Guillaume
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fs::{self, File, OpenOptions};
use std::io::{BufReader, SeekFrom, BufRead, Write, Read, Seek};
use std::fmt::{Display, Formatter, Error};
use std::path::PathBuf;
use std::ops::Deref;

enum EventType {
    Comment(String),
    FileComment(String),
    Type(TypeStruct),
    InScope,
    OutScope,
}

struct TypeStruct {
    ty: Type,
    parent: Option<Box<TypeStruct>>,
    name: String,
    args: Vec<String>,
}

impl TypeStruct {
    fn new(ty: Type, name: &str) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: name.to_owned(),
            args: vec!(),
            parent: None,
        }
    }

    fn from_args(ty: Type, args: Vec<String>) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: String::new(),
            args: args,
            parent: None,
        }
    }

    fn empty() -> TypeStruct {
        TypeStruct {
            ty: Type::Unknown,
            name: String::new(),
            args: Vec::new(),
            parent: None,
        }
    }
}

impl Clone for TypeStruct {
    fn clone(&self) -> TypeStruct {
        TypeStruct {
            ty: self.ty,
            name: self.name.clone(),
            args: self.args.clone(),
            parent: match self.parent {
                Some(ref p) => Some(Box::new(p.deref().clone())),
                None => None,
            }
        }
    }

    fn clone_from(&mut self, source: &TypeStruct) {
        self.ty = source.ty;
        self.name = source.name.clone();
        self.args = source.args.clone();
        self.parent = match source.parent {
            Some(ref p) => Some(Box::new(p.deref().clone())),
            None => None,
        };
    }
}

impl Display for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let parent = &self.parent;
        match parent {
            &Some(ref p) => write!(f, "{}({} {}{})", p, self.ty, self.name, self.args.join(" ")),
            &None => write!(f, "{} {}{}", self.ty, self.name, self.args.join(" ")),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum Type {
    Struct,
    Mod,
    Enum,
    Fn,
    Const,
    Static,
    Type,
    Variant,
    Impl,
    Unknown,
}

impl Type {
    fn from(s: &str) -> Type {
        match s {
            "struct" => Type::Struct,
            "mod" => Type::Mod,
            "enum" => Type::Enum,
            "fn" => Type::Fn,
            "const" => Type::Const,
            "static" => Type::Static,
            "type" => Type::Type,
            "impl" => Type::Impl,
            _ => Type::Variant,
        }
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            Type::Struct => write!(f, "struct"),
            Type::Mod => write!(f, "mod"),
            Type::Enum => write!(f, "enum"),
            Type::Fn => write!(f, "fn"),
            Type::Const => write!(f, "const"),
            Type::Static => write!(f, "static"),
            Type::Type => write!(f, "type"),
            Type::Variant => write!(f, "variant"),
            Type::Impl => write!(f, "impl"),
            _ => write!(f, "?"),
        }
    }
}

fn loop_over_files(path: &str, f: &mut File) {
    match fs::read_dir(path) {
        Ok(it) => {
            for entry in it {
                check_path_type(entry.unwrap().path().to_str().unwrap(), f);
            }
        }
        Err(e) => {
            println!("Error while trying to iterate over {}: {}", path, e);
        }
    }
}

fn move_to(words: &[&str], it: &mut usize, limit: &str) {
    while (*it + 1) < words.len() && limit.contains(words[*it + 1]) == false {
        *it += 1;
    }
}

fn get_impl(words: &[&str], it: &mut usize) -> Vec<String> {
    let mut v = vec!();

    while (*it + 1) < words.len() {
        if words[(*it + 1)] == "{" || words[(*it + 1)] == ";" {
            break;
        }
        *it += 1;
        v.push(words[*it].to_owned());
    }
    v
}

fn add_to_type_scope(current: &Option<TypeStruct>, e: &Option<TypeStruct>) -> Option<TypeStruct> {
    match current {
        &Some(ref c) => {
            match e {
                &Some(ref t) => {
                    let mut tmp = t.clone();
                    tmp.parent = Some(Box::new(c.clone()));
                    Some(tmp)
                }
                &None => {
                    let mut tmp = TypeStruct::empty();
                    tmp.parent = Some(Box::new(c.clone()));
                    Some(tmp)
                }
            }
        },
        &None => match e {
            &Some(ref t) => Some(t.clone()),
            &None => None,
        }
    }
}

fn type_out_scope(current: &Option<TypeStruct>) -> Option<TypeStruct> {
    match current {
        &Some(ref c) => match c.parent {
            Some(ref p) => Some(p.deref().clone()),
            None => None,
        },
        &None => None,
    }
}

fn strip_comments(path: &str, out_file: &mut File) {
    match File::open(path) {
        Ok(mut f) => {
            let mut b_content = String::new();
            f.read_to_string(&mut b_content).unwrap();
            let content = b_content.replace("{", " { ")
                                   .replace("}", " } ")
                                   .replace("///", "/// ")
                                   .replace("//!", "//! ")
                                   .replace("\n", " \n ")
                                   .replace("(", " (");
            let b_content : Vec<&str> = b_content.split('\n').collect();
            let words : Vec<&str> = content.split(' ').filter(|s| s.len() > 0).collect();
            let mut it = 0;
            let mut line = 0;
            let mut event_list = vec!();

            while it < words.len() {
                match words[it] {
                    "///" => {
                        event_list.push(EventType::Comment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n");
                    }
                    "//!" => {
                        event_list.push(EventType::FileComment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n");
                    }
                    "struct" | "mod" | "fn" | "enum" | "const" | "static" | "type" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from(words[it]), words[it + 1])));
                        it += 1;
                    }
                    "impl" => {
                        event_list.push(EventType::Type(TypeStruct::from_args(Type::Impl, get_impl(&words, &mut it))));
                    }
                    "{" => {
                        event_list.push(EventType::InScope);
                    }
                    "}" => {
                        event_list.push(EventType::OutScope);
                    }
                    "\n" => {
                        line += 1;
                    }
                    _ => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::Unknown, words[it])));
                    }
                }
                it += 1;
            }
            writeln!(out_file, "=! {}", path).unwrap();
            let mut current : Option<TypeStruct> = None;
            let mut waiting_type : Option<TypeStruct> = None;

            it = 0;
            while it < event_list.len() {
                match event_list[it] {
                    EventType::Type(ref t) => {
                        if t.ty != Type::Unknown {
                            waiting_type = Some(t.clone());
                            //println!("current : {}", t);
                        }
                    }
                    EventType::InScope => {
                        current = add_to_type_scope(&current, &waiting_type);
                        /*if waiting_type.is_some() {
                            println!("in : {}", waiting_type.unwrap());
                        }*/
                        waiting_type = None;
                    }
                    EventType::OutScope => {
                        /*if current.is_some() {
                            println!("out : {}", current.clone().unwrap());
                        }*/
                        current = type_out_scope(&current);
                        waiting_type = None;
                    }
                    EventType::FileComment(ref c) => {
                        let mut comments = format!("{}\n", c);

                        it += 1;
                        while match event_list[it] {
                            EventType::FileComment(ref c) => {
                                comments.push_str(&format!("=/ {}\n", c));
                                true
                            }
                            _ => false,
                        } {
                            it += 1;
                        }
                        write!(out_file, "{}", comments).unwrap();
                    }
                    EventType::Comment(ref c) => {
                        let mut comments = format!("{}\n", c);

                        it += 1;
                        while match event_list[it] {
                            EventType::Comment(ref c) => {
                                comments.push_str(&format!("{}\n", c));
                                true
                            }
                            EventType::Type(ref t) => {
                                false
                            }
                            _ => panic!("Comments cannot be written everywhere"),
                        } {
                            it += 1;
                        }
                        while match event_list[it] {
                            EventType::Type(ref t) => {
                                match t.ty {
                                    Type::Unknown => true,
                                    _ => {
                                        let tmp = add_to_type_scope(&current, &Some(t.clone()));
                                        write!(out_file, "=| {}\n{}", tmp.unwrap(), comments).unwrap();
                                        false
                                    }
                                }
                            }
                            _ => panic!("An item was expected"),
                        } {
                            it += 1;
                        }
                        it -= 1;
                    }
                }
                it += 1;
            }
        }
        Err(e) => {
            println!("Unable to open \"{}\": {}", path, e);
        }
    }
}

fn check_path_type(path: &str, f: &mut File) {
    match fs::metadata(path) {
        Ok(m) => {
            if m.is_dir() {
                if path == ".." || path == "." {
                    return;
                }
                loop_over_files(path, f);
            } else {
                if path == "./comments.cmts" {
                    return;
                }
                println!("-> {}", path);
                strip_comments(path, f);
            }
        }
        Err(e) => {
            println!("An error occurred: {}", e);
        }
    }
}

fn main() {
    println!("Starting...");
    match fs::remove_file("comments.cmts") { _ => {} }
    match OpenOptions::new().write(true).create(true).truncate(true).open("comments.cmts") {
        Ok(mut f) => {
            loop_over_files(".", &mut f);
            /*for com_entry in comments {
                write!(f, "{}", com_entry).unwrap();
            }*/
            println!("Done !");
        }
        Err(e) => {
            println!("Error while opening \"{}\": {}", "comments.cmts", e);
        }
    }
}

// au lieu de splitter le fichier via '\n', lis le sur "une seule ligne".
// quand tu croises un "///", tu stockes ça comme un commentaire, un "mod", comme un module, etc...
// il faudra compter les '{' / '}' pour voir si t'es toujours danns le truc courant ou non<commit_msg>Add "use" keyword handling (beginning at least)<commit_after>// Copyright 2015 Gomez Guillaume
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fs::{self, File, OpenOptions};
use std::io::{BufRead, Write, Read};
use std::fmt::{Display, Formatter, Error};
use std::ops::Deref;

enum EventType {
    Comment(String),
    FileComment(String),
    Type(TypeStruct),
    InScope,
    OutScope,
}

struct TypeStruct {
    ty: Type,
    parent: Option<Box<TypeStruct>>,
    name: String,
    args: Vec<String>,
}

impl TypeStruct {
    fn new(ty: Type, name: &str) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: name.to_owned(),
            args: vec!(),
            parent: None,
        }
    }

    fn from_args(ty: Type, args: Vec<String>) -> TypeStruct {
        TypeStruct {
            ty: ty,
            name: String::new(),
            args: args,
            parent: None,
        }
    }

    fn empty() -> TypeStruct {
        TypeStruct {
            ty: Type::Unknown,
            name: String::new(),
            args: Vec::new(),
            parent: None,
        }
    }
}

impl Clone for TypeStruct {
    fn clone(&self) -> TypeStruct {
        TypeStruct {
            ty: self.ty,
            name: self.name.clone(),
            args: self.args.clone(),
            parent: match self.parent {
                Some(ref p) => Some(Box::new(p.deref().clone())),
                None => None,
            }
        }
    }

    fn clone_from(&mut self, source: &TypeStruct) {
        self.ty = source.ty;
        self.name = source.name.clone();
        self.args = source.args.clone();
        self.parent = match source.parent {
            Some(ref p) => Some(Box::new(p.deref().clone())),
            None => None,
        };
    }
}

impl Display for TypeStruct {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let parent = &self.parent;
        match parent {
            &Some(ref p) => write!(f, "{}({} {}{})", p, self.ty, self.name, self.args.join(" ")),
            &None => write!(f, "{} {}{}", self.ty, self.name, self.args.join(" ")),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum Type {
    Struct,
    Mod,
    Enum,
    Fn,
    Const,
    Static,
    Type,
    Variant,
    Impl,
    Use,
    Unknown,
}

impl Type {
    fn from(s: &str) -> Type {
        match s {
            "struct" => Type::Struct,
            "mod" => Type::Mod,
            "enum" => Type::Enum,
            "fn" => Type::Fn,
            "const" => Type::Const,
            "static" => Type::Static,
            "type" => Type::Type,
            "impl" => Type::Impl,
            "use" => Type::Use,
            _ => Type::Variant,
        }
    }
}

impl Display for Type {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            Type::Struct => write!(f, "struct"),
            Type::Mod => write!(f, "mod"),
            Type::Enum => write!(f, "enum"),
            Type::Fn => write!(f, "fn"),
            Type::Const => write!(f, "const"),
            Type::Static => write!(f, "static"),
            Type::Type => write!(f, "type"),
            Type::Variant => write!(f, "variant"),
            Type::Impl => write!(f, "impl"),
            Type::Use => write!(f, "use"),
            _ => write!(f, "?"),
        }
    }
}

fn loop_over_files(path: &str, f: &mut File) {
    match fs::read_dir(path) {
        Ok(it) => {
            for entry in it {
                check_path_type(entry.unwrap().path().to_str().unwrap(), f);
            }
        }
        Err(e) => {
            println!("Error while trying to iterate over {}: {}", path, e);
        }
    }
}

fn move_to(words: &[&str], it: &mut usize, limit: &str, line: &mut usize) {
    while (*it + 1) < words.len() && limit.contains(words[*it + 1]) == false {
        if words[*it] == "\n" {
            *line += 1;
        }
        *it += 1;
    }
    if words[*it] == "\n" {
        *line += 1;
    }
}

fn move_until(words: &[&str], it: &mut usize, limit: &str, line: &mut usize) {
    while (*it + 1) < words.len() && limit != words[*it + 1] {
        if words[*it] == "\n" {
            *line += 1;
        }
        *it += 1;
    }
    if words[*it] == "\n" {
        *line += 1;
    }
}

fn get_impl(words: &[&str], it: &mut usize, line: &mut usize) -> Vec<String> {
    let mut v = vec!();

    while (*it + 1) < words.len() {
        if words[*it] == "\n" {
            *line += 1;
        }
        if words[(*it + 1)] == "{" || words[(*it + 1)] == ";" {
            break;
        }
        *it += 1;
        v.push(words[*it].to_owned());
    }
    v
}

fn add_to_type_scope(current: &Option<TypeStruct>, e: &Option<TypeStruct>) -> Option<TypeStruct> {
    match current {
        &Some(ref c) => {
            match e {
                &Some(ref t) => {
                    let mut tmp = t.clone();
                    tmp.parent = Some(Box::new(c.clone()));
                    Some(tmp)
                }
                &None => {
                    let mut tmp = TypeStruct::empty();
                    tmp.parent = Some(Box::new(c.clone()));
                    Some(tmp)
                }
            }
        },
        &None => match e {
            &Some(ref t) => Some(t.clone()),
            &None => None,
        }
    }
}

fn type_out_scope(current: &Option<TypeStruct>) -> Option<TypeStruct> {
    match current {
        &Some(ref c) => match c.parent {
            Some(ref p) => Some(p.deref().clone()),
            None => None,
        },
        &None => None,
    }
}

fn strip_comments(path: &str, out_file: &mut File) {
    match File::open(path) {
        Ok(mut f) => {
            let mut b_content = String::new();
            f.read_to_string(&mut b_content).unwrap();
            let content = b_content.replace("{", " { ")
                                   .replace("}", " } ")
                                   .replace("///", "/// ")
                                   .replace("//!", "//! ")
                                   .replace("/*!", "/*! ")
                                   .replace("*/", " */")
                                   .replace("\n", " \n ")
                                   .replace("(", " (");
            let b_content : Vec<&str> = b_content.split('\n').collect();
            let words : Vec<&str> = content.split(' ').filter(|s| s.len() > 0).collect();
            let mut it = 0;
            let mut line = 0;
            let mut event_list = vec!();

            while it < words.len() {
                match words[it] {
                    "///" => {
                        event_list.push(EventType::Comment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n", &mut line);
                    }
                    "//!" => {
                        event_list.push(EventType::FileComment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n", &mut line);
                    }
                    "/*!" => {
                        event_list.push(EventType::FileComment(b_content[line].to_owned()));
                        move_until(&words, &mut it, "*/", &mut line);
                    }
                    "struct" | "mod" | "fn" | "enum" | "const" | "static" | "type" | "use" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from(words[it]), words[it + 1])));
                        it += 1;
                    }
                    "impl" => {
                        event_list.push(EventType::Type(TypeStruct::from_args(Type::Impl, get_impl(&words, &mut it, &mut line))));
                    }
                    "{" => {
                        event_list.push(EventType::InScope);
                    }
                    "}" => {
                        event_list.push(EventType::OutScope);
                    }
                    "\n" => {
                        line += 1;
                    }
                    _ => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::Unknown, words[it])));
                    }
                }
                it += 1;
            }
            writeln!(out_file, "=! {}", path).unwrap();
            let mut current : Option<TypeStruct> = None;
            let mut waiting_type : Option<TypeStruct> = None;

            it = 0;
            while it < event_list.len() {
                match event_list[it] {
                    EventType::Type(ref t) => {
                        if t.ty != Type::Unknown {
                            waiting_type = Some(t.clone());
                            //println!("current : {}", t);
                        }
                    }
                    EventType::InScope => {
                        current = add_to_type_scope(&current, &waiting_type);
                        /*if waiting_type.is_some() {
                            println!("in : {}", waiting_type.unwrap());
                        }*/
                        waiting_type = None;
                    }
                    EventType::OutScope => {
                        /*if current.is_some() {
                            println!("out : {}", current.clone().unwrap());
                        }*/
                        current = type_out_scope(&current);
                        waiting_type = None;
                    }
                    EventType::FileComment(ref c) => {
                        let mut comments = format!("{}\n", c);

                        it += 1;
                        while match event_list[it] {
                            EventType::FileComment(ref c) => {
                                comments.push_str(&format!("=/ {}\n", c));
                                true
                            }
                            _ => false,
                        } {
                            it += 1;
                        }
                        write!(out_file, "{}", comments).unwrap();
                    }
                    EventType::Comment(ref c) => {
                        let mut comments = format!("{}\n", c);

                        it += 1;
                        while match event_list[it] {
                            EventType::Comment(ref c) => {
                                comments.push_str(&format!("{}\n", c));
                                true
                            }
                            EventType::Type(_) => {
                                false
                            }
                            _ => panic!("Comments cannot be written everywhere"),
                        } {
                            it += 1;
                        }
                        while match event_list[it] {
                            EventType::Type(ref t) => {
                                match t.ty {
                                    Type::Unknown => true,
                                    _ => {
                                        let tmp = add_to_type_scope(&current, &Some(t.clone()));
                                        write!(out_file, "=| {}\n{}", tmp.unwrap(), comments).unwrap();
                                        false
                                    }
                                }
                            }
                            _ => panic!("An item was expected for this comment: {}", comments),
                        } {
                            it += 1;
                        }
                        it -= 1;
                    }
                }
                it += 1;
            }
        }
        Err(e) => {
            println!("Unable to open \"{}\": {}", path, e);
        }
    }
}

fn check_path_type(path: &str, f: &mut File) {
    match fs::metadata(path) {
        Ok(m) => {
            if m.is_dir() {
                if path == ".." || path == "." {
                    return;
                }
                loop_over_files(path, f);
            } else {
                if path == "./comments.cmts" {
                    return;
                }
                println!("-> {}", path);
                strip_comments(path, f);
            }
        }
        Err(e) => {
            println!("An error occurred: {}", e);
        }
    }
}

fn main() {
    println!("Starting...");
    match fs::remove_file("comments.cmts") { _ => {} }
    match OpenOptions::new().write(true).create(true).truncate(true).open("comments.cmts") {
        Ok(mut f) => {
            loop_over_files(".", &mut f);
            /*for com_entry in comments {
                write!(f, "{}", com_entry).unwrap();
            }*/
            println!("Done !");
        }
        Err(e) => {
            println!("Error while opening \"{}\": {}", "comments.cmts", e);
        }
    }
}

// au lieu de splitter le fichier via '\n', lis le sur "une seule ligne".
// quand tu croises un "///", tu stockes ça comme un commentaire, un "mod", comme un module, etc...
// il faudra compter les '{' / '}' pour voir si t'es toujours danns le truc courant ou non<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

use std::fmt;

use rocket::Outcome;
use rocket::request::{self, Request, FromRequest};

struct IndexData(String);

impl<'a, 'r> FromRequest<'a, 'r> for IndexData {
    type Error = ();
    fn from_request(request: &'a Request<'r>) -> request::Outcome<IndexData, ()> {
        Outcome::Success(IndexData(format!("{}", request)))
    }
}

impl fmt::Display for IndexData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[get("/")]
fn index(data: IndexData) -> String {
    format!("<!doctype html><title>HTTPTIN></title>{}", data)
}

#[get("/ip")]
fn origin() -> String {
    String::from("Remote address decoding is not implemented yet")
}

#[get("/get")]
fn get() -> String {
    String::from("method")
}

fn main() {
    rocket::ignite().mount("/", routes![index, origin, get]).launch();
}

// fn get(req: &mut Request) -> PencilResult {
//     let mut data = BTreeMap::new();
//     // data.insert("args", format!("{:?}", req.args().listiter().collect::<Vec<_>>()));
//     data.insert("ip", format!("{}", req.remote_addr().ip()));
//     if let Some(endpoint) = req.endpoint() {
//         data.insert("endpoint", endpoint);
//     }
//     data.insert("url", req.url());
//
//     let mut args = BTreeMap::new();
//     for (key, value) in req.args().listiter() {
//         args.insert(key, format!("{:?}", value));
//     }
//     data.insert("args", format!("{:?}", args));
//     jsonify(&data)
// }
<commit_msg>Uppercase DOCTYPE<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

use std::fmt;

use rocket::Outcome;
use rocket::request::{self, Request, FromRequest};

struct IndexData(String);

impl<'a, 'r> FromRequest<'a, 'r> for IndexData {
    type Error = ();
    fn from_request(request: &'a Request<'r>) -> request::Outcome<IndexData, ()> {
        Outcome::Success(IndexData(format!("{}", request)))
    }
}

impl fmt::Display for IndexData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[get("/")]
fn index(data: IndexData) -> String {
    format!("<!DOCTYPE html><title>HTTPTIN></title>{}", data)
}

#[get("/ip")]
fn origin() -> String {
    String::from("Remote address decoding is not implemented yet")
}

#[get("/get")]
fn get() -> String {
    String::from("method")
}

fn main() {
    rocket::ignite().mount("/", routes![index, origin, get]).launch();
}

// fn get(req: &mut Request) -> PencilResult {
//     let mut data = BTreeMap::new();
//     // data.insert("args", format!("{:?}", req.args().listiter().collect::<Vec<_>>()));
//     data.insert("ip", format!("{}", req.remote_addr().ip()));
//     if let Some(endpoint) = req.endpoint() {
//         data.insert("endpoint", endpoint);
//     }
//     data.insert("url", req.url());
//
//     let mut args = BTreeMap::new();
//     for (key, value) in req.args().listiter() {
//         args.insert(key, format!("{:?}", value));
//     }
//     data.insert("args", format!("{:?}", args));
//     jsonify(&data)
// }
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl
        / method_decl

    class_decl
        = kw_class constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block > method_decl

    block
        = lbracket ((stmt / expr) terminator?)* rbracket > block

    stmt
        = if_stmt
        / while_stmt

    if_stmt
        = kw_if expr block (kw_else block)? > if_stmt

    while_stmt
        = kw_while expr block > while_stmt

    call_with_receiver
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    call_no_receiver
        = identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr
          / call_with_receiver > call_with_receiver
          / receiver_expr

    receiver_expr
        = call_no_receiver > call_no_receiver
        / literal
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*) > arg_list

    param_list
        = (identifier ("," spacing identifier)*) > param_list

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_no_receiver(method: PExpr, args: Option<Vec<PExpr>>) -> PExpr {
        Box::new(Call(None, method, args))
    }

    fn call_with_receiver(receiver: Option<PExpr>, method: PExpr, args: Option<Vec<PExpr>>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<PExpr>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<Vec<PExpr>>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn block(exprs: Vec<(PExpr, Option<()>)>) -> Vec<PExpr> {
        exprs.into_iter().map(|expr| {
            match expr {
                (e, _) => e
            }
        }).collect()
    }

    fn if_stmt(condition: PExpr, block: Vec<PExpr>, else_block: Option<Vec<PExpr>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn arg_list(first: PExpr, mut rest: Vec<PExpr>) -> Vec<PExpr> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PExpr, mut rest: Vec<PExpr>) -> Vec<PExpr> {
        combine_one_with_many(first, rest)
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        let mut result = vec![first];
        combine(result, rest)
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug, Clone)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<PExpr>),
        IfStatement(PExpr, Vec<PExpr>, Option<Vec<PExpr>>),
        MethodDecl(PExpr, Option<Vec<PExpr>>, Vec<PExpr>),
        WhileStatement(PExpr, Vec<PExpr>),
        Call(Option<PExpr>, PExpr, Option<Vec<PExpr>>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug, Clone)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", awesome::parse_program(contents.stream()).unwrap_data());
}
<commit_msg>Renamed project to 'Bailey'.<commit_after>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! bailey {
    program
        = ((expr / decl / stmt) terminator?)*

    decl
        = class_decl
        / method_decl

    class_decl
        = kw_class constant class_body > class_decl

    class_body
        = lbracket method_decl* rbracket

    method_decl
        = kw_def identifier lparen param_list? rparen block > method_decl

    block
        = lbracket ((stmt / expr) terminator?)* rbracket > block

    stmt
        = if_stmt
        / while_stmt

    if_stmt
        = kw_if expr block (kw_else block)? > if_stmt

    while_stmt
        = kw_while expr block > while_stmt

    call_with_receiver
        = (receiver_expr ".")? identifier lparen arg_list? rparen

    call_no_receiver
        = identifier lparen arg_list? rparen

    assign_expr
        = identifier bind_op expr > assign_expr

    expr
        = spacing cond_expr

    cond_expr
        = add_expr (cond_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (add_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr (mult_expr_op primary_expr)* > fold_left

    primary_expr
        = assign_expr
          / call_with_receiver > call_with_receiver
          / receiver_expr

    receiver_expr
        = call_no_receiver > call_no_receiver
        / literal
        / constant
        / identifier
        / lparen expr rparen

    arg_list
        = (expr ("," spacing expr)*) > arg_list

    param_list
        = (identifier ("," spacing identifier)*) > param_list

    digit = ["0-9"]
    identifier_char = ["A-Za-z0-9_"]

    identifier = !digit !keyword identifier_char+ spacing > identifier
    constant = !keyword !digit ["A-Z"]+ identifier_char+ spacing > constant

    literal
        = lit_string
        / lit_float
        / lit_int

    lit_int = digit+ spacing > lit_int
    lit_float = digit+ "." digit+ spacing > lit_float
    lit_string = (dbl_quot_lit_string / sng_quot_lit_string) spacing > lit_string

    dbl_quot_lit_string = dbl_quot (spacing_char / !dbl_quot .)* dbl_quot
    sng_quot_lit_string = sng_quot (spacing_char / !sng_quot .)* sng_quot

    spacing_char = [" \n\r\t"]
    spacing = spacing_char* -> ()

    kw_class = "class" spacing
    kw_def = "def" spacing
    kw_else = "else" spacing
    kw_false = "false" spacing
    kw_if = "if" spacing
    kw_nil = "nil" spacing
    kw_true = "true" spacing
    kw_while = "while" spacing

    keyword
        = kw_def
        / kw_if
        / kw_else
        / kw_class
        / kw_true
        / kw_false
        / kw_nil

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\"" spacing
    sng_quot = "'" spacing
    terminator = ";" spacing

    fn lit_int(raw_text: Vec<char>) -> PExpr {
        Box::new(IntegerLiteral(to_number(raw_text)))
    }

    // FIXME: Please remove this hacky wacky '.' thingy
    fn lit_float(integer: Vec<char>, fractional: Vec<char>) -> PExpr {
        let mut buf = integer;
        buf.push('.');
        Box::new(FloatLiteral(to_float(combine(buf, fractional))))
    }

    fn lit_string(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn constant(first: Vec<char>, rest: Vec<char>) -> PExpr {
        Box::new(Constant(to_string(combine(first, rest))))
    }

    fn identifier(raw_text: Vec<char>) -> PExpr {
        Box::new(Identifier(to_string(raw_text)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_no_receiver(method: PExpr, args: Option<Vec<PExpr>>) -> PExpr {
        Box::new(Call(None, method, args))
    }

    fn call_with_receiver(receiver: Option<PExpr>, method: PExpr, args: Option<Vec<PExpr>>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn assign_expr(identifier: PExpr, expr: PExpr) -> PExpr {
        Box::new(AssingExpr(identifier, expr))
    }

    fn class_decl(class: PExpr, methods: Vec<PExpr>) -> PExpr {
        Box::new(ClassDecl(class, methods))
    }

    fn method_decl(identifier: PExpr, params: Option<Vec<PExpr>>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(identifier, params, body))
    }

    fn block(exprs: Vec<(PExpr, Option<()>)>) -> Vec<PExpr> {
        exprs.into_iter().map(|expr| {
            match expr {
                (e, _) => e
            }
        }).collect()
    }

    fn if_stmt(condition: PExpr, block: Vec<PExpr>, else_block: Option<Vec<PExpr>>) -> PExpr {
        Box::new(IfStatement(condition, block, else_block))
    }

    fn while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }

    fn arg_list(first: PExpr, mut rest: Vec<PExpr>) -> Vec<PExpr> {
        combine_one_with_many(first, rest)
    }

    fn param_list(first: PExpr, mut rest: Vec<PExpr>) -> Vec<PExpr> {
        combine_one_with_many(first, rest)
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn to_float(raw_text: Vec<char>) -> f32 {
        f32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn combine<T: Clone>(left: Vec<T>, right: Vec<T>) -> Vec<T> {
        let mut result = left.clone();
        result.extend(right.into_iter());
        result
    }

    fn combine_one_with_many<T: Clone>(first: T, rest: Vec<T>) -> Vec<T> {
        let mut result = vec![first];
        combine(result, rest)
    }

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug, Clone)]
    pub enum Expression {
        Identifier(String),
        Constant(String),
        IntegerLiteral(u32),
        FloatLiteral(f32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        AssingExpr(PExpr, PExpr),
        ClassDecl(PExpr, Vec<PExpr>),
        IfStatement(PExpr, Vec<PExpr>, Option<Vec<PExpr>>),
        MethodDecl(PExpr, Option<Vec<PExpr>>, Vec<PExpr>),
        WhileStatement(PExpr, Vec<PExpr>),
        Call(Option<PExpr>, PExpr, Option<Vec<PExpr>>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug, Clone)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:#?}", bailey::parse_program(contents.stream()).unwrap_data());
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(test))]

pub static ASCII_TEXT: &'static str = "Attend to hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";
pub static UNICODE_TEXT: &'static str = "Attend \u{20000}\u{20000} hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";

#[derive(Clone)]
pub struct Entity {
    start: usize,
    end: usize,
    html: String
}

#[derive(Clone)]
pub struct DecodedEntity {
    start: usize,
    end: usize,
    html: Vec<char>,
}

impl Entity {
    fn decode(&self) -> DecodedEntity {
        DecodedEntity {start: self.start, end: self.end, html: self.html.chars().collect()}
    }
}

fn render(text: &str, entities: &mut Vec<Entity>) -> String {
    let mut sb = String::with_capacity(text.len()*2);
    entities.sort_by(|e1, e2| e1.start.cmp(&e2.start) );

    let mut pos = 0 as usize;
    for entity in entities {
        for c in text.chars().skip(pos).take(entity.start - pos) {
            sb.push(c);
        }
        sb.push_str(entity.html.as_str());
        pos = entity.end;
    }
    for c in text.chars().skip(pos).take(text.chars().count() - pos) {
        sb.push(c);
    }
    sb
}

fn render_chars(text: &Vec<char>, entities: &mut Vec<DecodedEntity>) -> String {
    let mut sb: Vec<char> = Vec::with_capacity(text.len()*2);
    entities.sort_by(|e1, e2| e1.start.cmp(&e2.start) );

    let mut pos = 0 as usize;
    for entity in entities {
        for c in text[pos..entity.start].iter() {
            sb.push(*c);
        }
        for c in entity.html.iter() {
            sb.push(*c);
        }
        pos = entity.end;
    }
    for c in text[pos..text.len()].iter() {
        sb.push(*c);
    }
    sb.into_iter().collect()
}

fn main() {
    let result = classic(&ASCII_TEXT, &mut entities());
    println!("Result: {}", result);
}

pub fn classic(text: &str, entities: &mut Vec<Entity>) -> String {
    render(&text, entities)
}

pub fn classic_chars(text: &Vec<char>, entities: &mut Vec<DecodedEntity>) -> String {
    render_chars(&text, entities)
}

pub fn entities() -> Vec<Entity> {
    let entities = vec![
    Entity {start: 82, end: 102, html:"<http://t.co/HtzEMgAC>".to_string()},
    Entity {start: 128, end: 132, html:"<@500>".to_string()},
    Entity {start: 25, end: 32, html:"<#mobile>".to_string()},
    Entity {start: 33, end: 42, html:"<#startups>".to_string()},
    Entity {start: 111, end: 127, html:"<@sv_entrepreneur>".to_string()},
    Entity {start: 46, end: 51, html:"<#OF12>".to_string()},
    Entity {start: 103, end: 110, html:"<@TiEcon>".to_string()},
    ];
    entities
}

pub fn decoded_entities() -> Vec<DecodedEntity> {
    entities().into_iter().map( |e| e.decode() ).collect()
}

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

#[cfg(test)]
mod rendertest {
    use super::*;
    use rand::{self,Rng};
    use test::Bencher;

    fn generate_entities() -> Vec<Vec<Entity>> {
        let mut rng = rand::thread_rng();
        let mut entities_list: Vec<Vec<Entity>> = Vec::with_capacity(1000);

        for _ in 0..1000 {
            let total = rng.gen::<usize>() % 10;
            let mut indices = Vec::with_capacity(total);
            for _ in 0..(total*2) {
                loop {
                    let index = rng.gen::<usize>() % ASCII_TEXT.len();
                    if !indices.contains(&index) {
                        indices.push(index);
                        break;
                    }
                }
            }

            indices.sort();
            let entities = indices.chunks(2).map(|chunk| {
                let (start, end) = (chunk[0], chunk[1]);
                let length = end - start;
                Entity {start: start, end: end, html: (0..length).map(|_| "X").collect()}
            });
            entities_list.push(entities.collect());
        }

        entities_list
    }

    fn generate_decoded_entities() -> Vec<Vec<DecodedEntity>> {
        generate_entities().into_iter().map(|entries| {
            entries.into_iter().map(|e| { e.decode() } ).collect()
        }).collect()
    }

    #[test]
    fn correctness_chars() {
        let result = "Attend \u{20000}\u{20000} hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  <http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
        assert_eq!(result, classic_chars(&UNICODE_TEXT.chars().collect(), &mut decoded_entities()))
    }

    #[test]
    fn correctness() {
        let result = "Attend \u{20000}\u{20000} hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  <http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
        assert_eq!(result, classic(&UNICODE_TEXT, &mut entities()))
    }

    #[bench]
    fn bench_replacement(b: &mut Bencher) {
        let mut entities_list = generate_entities();
        let mut index_iter = (0..1000).into_iter().cycle();
        b.iter(|| {
            classic(UNICODE_TEXT, &mut entities_list[index_iter.next().unwrap()])
        });
    }

    #[bench]
    fn bench_replacement_chars(b: &mut Bencher) {
        let mut entities_list = generate_decoded_entities();
        let mut index_iter = (0..1000).into_iter().cycle();
        let decoded_text = UNICODE_TEXT.chars().collect();
        b.iter(|| {
            classic_chars(&decoded_text, &mut entities_list[index_iter.next().unwrap()])
        });
    }
}
<commit_msg>learning more about the rust std lib<commit_after>#![cfg_attr(test, feature(test))]

pub static ASCII_TEXT: &'static str = "Attend to hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";
pub static UNICODE_TEXT: &'static str = "Attend \u{20000}\u{20000} hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";

#[derive(Clone)]
pub struct Entity {
    start: usize,
    end: usize,
    html: String
}

#[derive(Clone)]
pub struct DecodedEntity {
    start: usize,
    end: usize,
    html: Vec<char>,
}

impl Entity {
    fn decode(&self) -> DecodedEntity {
        DecodedEntity {start: self.start, end: self.end, html: self.html.chars().collect()}
    }
}

fn render(text: &str, entities: &mut Vec<Entity>) -> String {
    let mut sb = String::with_capacity(text.len()*2);
    entities.sort_by(|e1, e2| e1.start.cmp(&e2.start) );

    let mut pos = 0 as usize;
    for entity in entities {
        sb.extend(text.chars().skip(pos).take(entity.start - pos));
        sb.push_str(entity.html.as_str());
        pos = entity.end;
    }
    for c in text.chars().skip(pos).take(text.chars().count() - pos) {
        sb.push(c);
    }
    sb
}

fn render_chars(text: &Vec<char>, entities: &mut Vec<DecodedEntity>) -> String {
    let mut sb: Vec<char> = Vec::with_capacity(text.len()*2);
    entities.sort_by(|e1, e2| e1.start.cmp(&e2.start) );

    let mut pos = 0 as usize;
    for entity in entities {
        sb.extend_from_slice(&text[pos..entity.start]);
        sb.extend_from_slice(&entity.html);
        pos = entity.end;
    }
    sb.extend_from_slice(&text[pos..text.len()]);
    sb.into_iter().collect()
}

fn main() {
    let result = classic(&ASCII_TEXT, &mut entities());
    println!("Result: {}", result);
}

pub fn classic(text: &str, entities: &mut Vec<Entity>) -> String {
    render(&text, entities)
}

pub fn classic_chars(text: &Vec<char>, entities: &mut Vec<DecodedEntity>) -> String {
    render_chars(&text, entities)
}

pub fn entities() -> Vec<Entity> {
    let entities = vec![
    Entity {start: 82, end: 102, html:"<http://t.co/HtzEMgAC>".to_string()},
    Entity {start: 128, end: 132, html:"<@500>".to_string()},
    Entity {start: 25, end: 32, html:"<#mobile>".to_string()},
    Entity {start: 33, end: 42, html:"<#startups>".to_string()},
    Entity {start: 111, end: 127, html:"<@sv_entrepreneur>".to_string()},
    Entity {start: 46, end: 51, html:"<#OF12>".to_string()},
    Entity {start: 103, end: 110, html:"<@TiEcon>".to_string()},
    ];
    entities
}

pub fn decoded_entities() -> Vec<DecodedEntity> {
    entities().into_iter().map( |e| e.decode() ).collect()
}

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

#[cfg(test)]
mod rendertest {
    use super::*;
    use rand::{self,Rng};
    use test::Bencher;

    fn generate_entities() -> Vec<Vec<Entity>> {
        let mut rng = rand::thread_rng();
        let mut entities_list: Vec<Vec<Entity>> = Vec::with_capacity(1000);

        for _ in 0..1000 {
            let total = rng.gen::<usize>() % 10;
            let mut indices = Vec::with_capacity(total);
            for _ in 0..(total*2) {
                loop {
                    let index = rng.gen::<usize>() % ASCII_TEXT.len();
                    if !indices.contains(&index) {
                        indices.push(index);
                        break;
                    }
                }
            }

            indices.sort();
            let entities = indices.chunks(2).map(|chunk| {
                let (start, end) = (chunk[0], chunk[1]);
                let length = end - start;
                Entity {start: start, end: end, html: (0..length).map(|_| "X").collect()}
            });
            entities_list.push(entities.collect());
        }

        entities_list
    }

    fn generate_decoded_entities() -> Vec<Vec<DecodedEntity>> {
        generate_entities().into_iter().map(|entries| {
            entries.into_iter().map(|e| { e.decode() } ).collect()
        }).collect()
    }

    #[test]
    fn correctness_chars() {
        let result = "Attend \u{20000}\u{20000} hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  <http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
        assert_eq!(result, classic_chars(&UNICODE_TEXT.chars().collect(), &mut decoded_entities()))
    }

    #[test]
    fn correctness() {
        let result = "Attend \u{20000}\u{20000} hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  <http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
        assert_eq!(result, classic(&UNICODE_TEXT, &mut entities()))
    }

    #[bench]
    fn bench_replacement(b: &mut Bencher) {
        let mut entities_list = generate_entities();
        let mut index_iter = (0..1000).into_iter().cycle();
        b.iter(|| {
            classic(UNICODE_TEXT, &mut entities_list[index_iter.next().unwrap()])
        });
    }

    #[bench]
    fn bench_replacement_chars(b: &mut Bencher) {
        let mut entities_list = generate_decoded_entities();
        let mut index_iter = (0..1000).into_iter().cycle();
        let decoded_text = UNICODE_TEXT.chars().collect();
        b.iter(|| {
            classic_chars(&decoded_text, &mut entities_list[index_iter.next().unwrap()])
        });
    }
}
<|endoftext|>


<commit_before>extern crate practice_game;

// Files
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

// Game Objects
use practice_game::unit::{Unit, Hero, NonHero};

// Tests
use std::mem;

const GAME_NAME: &'static str = "Fighter";
const HERO_INIT_HEALTH: f64 = 200.0;
const HERO_INIT_ATTACK: f64 = 20.0;
const NONHERO_INIT_HEALTH: f64 = 100.0;
const NONHERO_INIT_ATTACK: f64 = 10.0;

// ======================================================================
// Abstractions
//
#[derive(Clone)]
pub struct Resources {
    player: Hero,
    enemy: NonHero,
}

impl Resources {
    pub fn realize_player(&self) -> Hero {
        let cloned_self = self.clone();
        cloned_self.player
    }

    pub fn realize_enemy(&self) -> NonHero {
        let cloned_self = self.clone();
        cloned_self.enemy
    }
}
// ======================================================================

// ======================================================================
//
fn main() {
    let database_path = Path::new("database.txt");
    let database_display = database_path.display();
    let mut database_file = match File::open(&database_path) {
        Err(why) => panic!("couldn't open {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(database_file) => database_file, };
    let mut database_reader = String::new();
    match database_file.read_to_string(&mut database_reader) {
        Err(why) => panic!("couldn't read {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(_) => print!("{file} contains:\n{contents}",
                        file = database_display,
                        contents = database_reader), }

    let mut game_data: Resources = Resources {
        player: Hero::new(HERO_INIT_HEALTH, HERO_INIT_ATTACK),
        enemy: NonHero::new(NONHERO_INIT_HEALTH, NONHERO_INIT_ATTACK), };
    println!("Welcome to {}!", GAME_NAME);
    draw_line_break();
    draw_line_break();
    println!("An enemy appears!");
    battle(&mut game_data);
    battle(&mut game_data);

}
// ======================================================================

// ======================================================================
// Helper Routines
//
// UI
//
pub fn draw_line_break() {
    println!("");
}

pub fn draw_hp_bars(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    println!("--------------------");
    println!("enemy: {}", enemy.show());
    println!("player: {}", player.show());
    println!("--------------------");
}

pub fn draw_combat_text(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    let old_health: f64 = enemy.realize_hp() + player.realize_atk();
    let new_health: f64 = enemy.realize_hp();
    let damage: f64 = player.realize_atk();
    print!("{}hp -> ", old_health as i32);
    print!("{}hp ", new_health as i32);
    println!("{}!", damage as i32);
}

// Memory
//
#[allow(dead_code)]
fn show_mem(in_game_data: &Resources) {
    let ref enemy = in_game_data.realize_enemy();
    let ref player = in_game_data.realize_player();

    println!("resource    bytes in the stack");
    println!("GAME_NAME:  {}", mem::size_of_val(&GAME_NAME));
    println!("game_data:  {}", mem::size_of_val(&in_game_data));
    println!("enemy:      {}", mem::size_of_val(&enemy));
    println!("enemy.hp:   {}", mem::size_of_val(&enemy.realize_hp()));
    println!("enemy.atk:  {}", mem::size_of_val(&enemy.realize_atk()));
    println!("player:     {}", mem::size_of_val(&player));
    println!("player.hp:  {}", mem::size_of_val(&player.realize_hp()));
    println!("player.atk: {}", mem::size_of_val(&player.realize_atk()));
    println!("player.lvl: {}", mem::size_of_val(&player.realize_lvl()));
    println!("player.exp: {}", mem::size_of_val(&player.realize_exp()));
}

// Misc
//
fn battle(in_game_data: &mut Resources) {
    let mut game_data: &mut Resources = in_game_data;
    draw_hp_bars(&game_data);
    read_user_input();
    deal_damage(&mut game_data);
    draw_combat_text(&game_data);
    draw_line_break();
    draw_line_break();
}

fn read_user_input() {
    let user_input: &str = &"attack";
    println!("{}", user_input);
}

fn deal_damage(in_game_data: &mut Resources) {
    let cloned_game_data = in_game_data.clone();
    let ref player = cloned_game_data.player;
    let ref mut enemy = in_game_data.enemy;

    let dmg = -player.realize_atk();
    enemy.change_current_hp(dmg);
}
// ======================================================================
<commit_msg>Program Design: Condensing.<commit_after>extern crate practice_game;

// Files
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

// Game Objects
use practice_game::unit::{Unit, Hero, NonHero};

// Tests
use std::mem;

const GAME_NAME: &'static str = "Fighter";
const HERO_INIT_HEALTH: f64 = 200.0;
const HERO_INIT_ATTACK: f64 = 20.0;
const NONHERO_INIT_HEALTH: f64 = 100.0;
const NONHERO_INIT_ATTACK: f64 = 10.0;

// ======================================================================
// Abstractions
//
#[derive(Clone)]
pub struct Resources {
    player: Hero,
    enemy: NonHero, }
impl Resources {
    pub fn realize_player(&self) -> Hero {
        let cloned_self = self.clone();
        cloned_self.player }
    pub fn realize_enemy(&self) -> NonHero {
        let cloned_self = self.clone();
        cloned_self.enemy }
}
// ======================================================================

// ======================================================================
//
fn main() {
    // Files ======================================================
    let database_path = Path::new("database.txt");
    let database_display = database_path.display();
    let mut database_file = match File::open(&database_path) {
        Err(why) => panic!("couldn't open {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(database_file) => database_file, };
    let mut database_reader = String::new();
    match database_file.read_to_string(&mut database_reader) {
        Err(why) => panic!("couldn't read {file}: {reason}",
                           file = database_display,
                           reason = Error::description(&why)),
        Ok(_) => print!("{file} contains:\n{contents}",
                        file = database_display,
                        contents = database_reader), }
    // ============================================================

    let mut game_data: Resources = Resources {
        player: Hero::new(HERO_INIT_HEALTH, HERO_INIT_ATTACK),
        enemy: NonHero::new(NONHERO_INIT_HEALTH, NONHERO_INIT_ATTACK), };
    println!("Welcome to {}!", GAME_NAME);
    draw_line_break();
    draw_line_break();
    println!("An enemy appears!");
    battle(&mut game_data);
    battle(&mut game_data);

}
// ======================================================================

// ======================================================================
// Helper Routines
//
// UI
//
pub fn draw_line_break() {
    println!(""); }
pub fn draw_hp_bars(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    println!("--------------------");
    println!("enemy: {}", enemy.show());
    println!("player: {}", player.show());
    println!("--------------------"); }
pub fn draw_combat_text(in_game_data: &Resources) {
    let ref enemy = in_game_data.enemy;
    let ref player = in_game_data.player;

    let old_health: f64 = enemy.realize_hp() + player.realize_atk();
    let new_health: f64 = enemy.realize_hp();
    let damage: f64 = player.realize_atk();
    print!("{}hp -> ", old_health as i32);
    print!("{}hp ", new_health as i32);
    println!("{}!", damage as i32); }

// Memory
//
#[allow(dead_code)]
fn show_mem(in_game_data: &Resources) {
    let ref enemy = in_game_data.realize_enemy();
    let ref player = in_game_data.realize_player();

    println!("resource    bytes in the stack");
    println!("GAME_NAME:  {}", mem::size_of_val(&GAME_NAME));
    println!("game_data:  {}", mem::size_of_val(&in_game_data));
    println!("enemy:      {}", mem::size_of_val(&enemy));
    println!("enemy.hp:   {}", mem::size_of_val(&enemy.realize_hp()));
    println!("enemy.atk:  {}", mem::size_of_val(&enemy.realize_atk()));
    println!("player:     {}", mem::size_of_val(&player));
    println!("player.hp:  {}", mem::size_of_val(&player.realize_hp()));
    println!("player.atk: {}", mem::size_of_val(&player.realize_atk()));
    println!("player.lvl: {}", mem::size_of_val(&player.realize_lvl()));
    println!("player.exp: {}", mem::size_of_val(&player.realize_exp())); }

// Misc
//
fn battle(in_game_data: &mut Resources) {
    let mut game_data: &mut Resources = in_game_data;
    draw_hp_bars(&game_data);
    read_user_input();
    deal_damage(&mut game_data);
    draw_combat_text(&game_data);
    draw_line_break();
    draw_line_break(); }
fn read_user_input() {
    let user_input: &str = &"attack";
    println!("{}", user_input); }
fn deal_damage(in_game_data: &mut Resources) {
    let cloned_game_data = in_game_data.clone();
    let ref player = cloned_game_data.player;
    let ref mut enemy = in_game_data.enemy;

    let dmg = -player.realize_atk();
    enemy.change_current_hp(dmg); }
// ======================================================================
<|endoftext|>


<commit_before>extern crate log;
extern crate pretty_env_logger;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
extern crate trust_dns;

use log::info;

use serde_json::value::*;

use std::env;
use std::io;
use std::io::prelude::*;

use trust_dns::client::{Client as _Client, SyncClient};
use trust_dns::rr::dns_class::DNSClass;
use trust_dns::rr::record_type::RecordType;
use trust_dns::rr::domain;
use trust_dns::rr::record_data::RData;
use trust_dns::udp::UdpClientConnection;

const NS1_GOOGLE_COM_IP_ADDR: &'static str = "216.239.32.10:53";

fn env_var(n: &str) -> String {
    let err = format!("Environment Variable '{}' must be set!", &n);
    env::var(n).ok().expect(&err)
}

// overloaded function. no body is treated as a get, body is treated as a put
fn cloudflare_api(url: &str, body: Option<String>) -> Result<Value, String> {
    let cloudflare_apikey = env_var("CLOUDFLARE_APIKEY");
    let cloudflare_email = env_var("CLOUDFLARE_EMAIL");

    let client = reqwest::Client::new();
    let request = match body {
        Some(body) => { client.put(url).body(body) }
        None => { client.get(url) }
    };
    let response_json : Value = request
        .header("X-Auth-Key", cloudflare_apikey.to_owned())
        .header("X-Auth-Email", cloudflare_email.to_owned())
        .send().unwrap()
        .json().unwrap();

    let success = response_json
        .as_object().unwrap()
        .get("success").unwrap()
        .as_bool().unwrap();
    if !success {
        return Err(format!("Request not successful: {}", response_json));
    }

    Ok(response_json)
}

fn get_current_ip() -> Result<String, ()> {
    let gdns_addr = (NS1_GOOGLE_COM_IP_ADDR).parse().expect("Couldn't get Google DNS Socket Addr");
    let conn = UdpClientConnection::new(gdns_addr).expect("Couldn't open DNS UDP Connection");
    let client = SyncClient::new(conn);

    let name = domain::Name::new();
    let name = name.append_label("o-o").unwrap()
        .append_label("myaddr").unwrap()
        .append_label("l").unwrap()
        .append_label("google").unwrap()
        .append_label("com").unwrap();
    let response = client.query(&name, DNSClass::IN, RecordType::TXT).unwrap();

    let record = &response.answers()[0];
    match record.rdata() {
        &RData::TXT(ref txt) => {
            let val = txt.txt_data();
            return Ok(String::from_utf8(val[0].to_vec()).unwrap())
        },
        _ => return Err(())
    }
}

fn main() {
    pretty_env_logger::init();

    let current_ip = get_current_ip().ok().expect("Was unable to determine current IP address.");
    info!("{}", current_ip);

    let cloudflare_records_env = env_var("CLOUDFLARE_RECORDS");
    let cloudflare_records: Vec<&str> = cloudflare_records_env.split(|c: char| c == ',').collect();

    let zones_url = "https://api.cloudflare.com/client/v4/zones";
    let zones_json = cloudflare_api(zones_url, None).unwrap();

    let zone_ids = zones_json
        .as_object().unwrap()
        .get("result").unwrap()
        .as_array().unwrap()
        .iter()
        .map(|ref zone_node|
             zone_node.get("id").unwrap()
             .as_str().unwrap());

    for zone_id in zone_ids {
        let records_url = format!("https://api.cloudflare.com/client/v4/zones/{}/dns_records", zone_id);
        let records_json = cloudflare_api(&*records_url, None).unwrap();

        let records = records_json
            .as_object().unwrap()
            .get("result").unwrap()
            .as_array().unwrap()
            .iter();

        for record in records {
            let record_id = record.get("id").unwrap().as_str().unwrap();
            let record_type = record.get("type").unwrap().as_str().unwrap();
            let record_name = record.get("name").unwrap().as_str().unwrap();
            let record_content = record.get("content").unwrap().as_str().unwrap();

            if !cloudflare_records.contains(&record_name) || record_type != "A" {
                continue
            }

            if record_content == current_ip {
                info!("{} skipped, up to date", record_name);
                continue;
            }

            print!("{} ({} -> {})... ", record_name, record_content, current_ip);
            io::stdout().flush().ok();

            let record_url = format!(
                "https://api.cloudflare.com/client/v4/zones/{}/dns_records/{}",
                zone_id,
                record_id);
            let record_update_body = format!(
                r#"{{"name": "{}", "content": "{}", "type": "{}", "proxied": true}}"#,
                record_name,
                current_ip,
                record_type);
            cloudflare_api(&*record_url, Some(record_update_body.to_string())).unwrap();
        }
    }
}
<commit_msg>Reuse the reqwest Client for Cloudflare API calls<commit_after>extern crate log;
extern crate pretty_env_logger;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
extern crate trust_dns;

use log::info;

use serde_json::value::*;

use std::env;
use std::io;
use std::io::prelude::*;

use trust_dns::client::{Client as _Client, SyncClient};
use trust_dns::rr::dns_class::DNSClass;
use trust_dns::rr::record_type::RecordType;
use trust_dns::rr::domain;
use trust_dns::rr::record_data::RData;
use trust_dns::udp::UdpClientConnection;

const NS1_GOOGLE_COM_IP_ADDR: &'static str = "216.239.32.10:53";

fn env_var(n: &str) -> String {
    let err = format!("Environment Variable '{}' must be set!", &n);
    env::var(n).ok().expect(&err)
}

// overloaded function. no body is treated as a get, body is treated as a put
fn cloudflare_api(client: &reqwest::Client, url: &str, body: Option<String>) -> Result<Value, String> {
    let cloudflare_apikey = env_var("CLOUDFLARE_APIKEY");
    let cloudflare_email = env_var("CLOUDFLARE_EMAIL");

    let request = match body {
        Some(body) => { client.put(url).body(body) }
        None => { client.get(url) }
    };
    let response_json : Value = request
        .header("X-Auth-Key", cloudflare_apikey.to_owned())
        .header("X-Auth-Email", cloudflare_email.to_owned())
        .send().unwrap()
        .json().unwrap();

    let success = response_json
        .as_object().unwrap()
        .get("success").unwrap()
        .as_bool().unwrap();
    if !success {
        return Err(format!("Request not successful: {}", response_json));
    }

    Ok(response_json)
}

fn get_current_ip() -> Result<String, ()> {
    let gdns_addr = (NS1_GOOGLE_COM_IP_ADDR).parse().expect("Couldn't get Google DNS Socket Addr");
    let conn = UdpClientConnection::new(gdns_addr).expect("Couldn't open DNS UDP Connection");
    let client = SyncClient::new(conn);

    let name = domain::Name::new();
    let name = name.append_label("o-o").unwrap()
        .append_label("myaddr").unwrap()
        .append_label("l").unwrap()
        .append_label("google").unwrap()
        .append_label("com").unwrap();
    let response = client.query(&name, DNSClass::IN, RecordType::TXT).unwrap();

    let record = &response.answers()[0];
    match record.rdata() {
        &RData::TXT(ref txt) => {
            let val = txt.txt_data();
            return Ok(String::from_utf8(val[0].to_vec()).unwrap())
        },
        _ => return Err(())
    }
}

fn main() {
    pretty_env_logger::init();

    let current_ip = get_current_ip().ok().expect("Was unable to determine current IP address.");
    info!("{}", current_ip);
    let client = reqwest::Client::new();

    let cloudflare_records_env = env_var("CLOUDFLARE_RECORDS");
    let cloudflare_records: Vec<&str> = cloudflare_records_env.split(|c: char| c == ',').collect();

    let zones_url = "https://api.cloudflare.com/client/v4/zones";
    let zones_json = cloudflare_api(&client, zones_url, None).unwrap();

    let zone_ids = zones_json
        .as_object().unwrap()
        .get("result").unwrap()
        .as_array().unwrap()
        .iter()
        .map(|ref zone_node|
             zone_node.get("id").unwrap()
             .as_str().unwrap());

    for zone_id in zone_ids {
        let records_url = format!("https://api.cloudflare.com/client/v4/zones/{}/dns_records", zone_id);
        let records_json = cloudflare_api(&client, &*records_url, None).unwrap();

        let records = records_json
            .as_object().unwrap()
            .get("result").unwrap()
            .as_array().unwrap()
            .iter();

        for record in records {
            let record_id = record.get("id").unwrap().as_str().unwrap();
            let record_type = record.get("type").unwrap().as_str().unwrap();
            let record_name = record.get("name").unwrap().as_str().unwrap();
            let record_content = record.get("content").unwrap().as_str().unwrap();

            if !cloudflare_records.contains(&record_name) || record_type != "A" {
                continue
            }

            if record_content == current_ip {
                info!("{} skipped, up to date", record_name);
                continue;
            }

            print!("{} ({} -> {})... ", record_name, record_content, current_ip);
            io::stdout().flush().ok();

            let record_url = format!(
                "https://api.cloudflare.com/client/v4/zones/{}/dns_records/{}",
                zone_id,
                record_id);
            let record_update_body = format!(
                r#"{{"name": "{}", "content": "{}", "type": "{}", "proxied": true}}"#,
                record_name,
                current_ip,
                record_type);
            cloudflare_api(&client, &*record_url, Some(record_update_body.to_string())).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>#![feature(collections, convert, core, exit_status, std_misc)]
#![deny(unused_imports)]

extern crate num;
extern crate num_cpus;
extern crate rand;
extern crate rustc_serialize;
extern crate threadpool;
extern crate time;

use scene::{Camera, Scene};

use std::fs::File;
use std::io::{self, Read, Write};
use std::env;
use std::sync::Arc;
use rustc_serialize::json;
use rustc_serialize::json::DecoderError::MissingFieldError;

mod geometry;
mod light;
mod material;
mod my_scene;
mod raytracer;
mod scene;
mod util;
mod vec3;
mod mat4;

// Replace this with argparse eventually
struct ProgramArgs {
    config_file: String
}

#[derive(RustcDecodable, RustcEncodable)]
struct SceneConfig {
    name: String,
    size: (u32, u32),
    fov: f64,
    reflect_depth: u32,
    refract_depth: u32,
    shadow_samples: u32,
    pixel_samples: u32,
    output_file: String,
    animating: bool,
    fps: f64,
    time_slice: (f64, f64),
    starting_frame_number: u32
}

fn parse_args(args: env::Args) -> Result<ProgramArgs, String> {
    let args = args.collect::<Vec<String>>();
    if args.len() == 0 {
        panic!("Args do not even include a program name");
    }

    let program_name = &args[0];
    match args.len() {
        // I wouldn't expect this in the wild
        0 => unreachable!(),
        1 => Err(format!("Usage: {} scene_config.json", program_name)),
        2 => Ok(ProgramArgs { config_file: args[1].clone() }),
        _ => Err(format!("Usage: {} scene_config.json", program_name)),
    }
}

fn get_camera_and_scene(config: &SceneConfig) -> Option<(Camera, Scene)> {
    let scene_name = config.name.clone();
    let (image_width, image_height) = config.size;
    let fov = config.fov;

    // Cameras, scenes created in ./my_scene.rs
    // Scenes with an octree supplied (see my_scene.rs) will use it.
    // Lower the render quality (especially shadow_samples) for complex scenes
    return match scene_name.as_ref() {
        "box" => {
            // Box. Simplest scene with 9 primitives, no octree
            let camera = my_scene::cornell::get_camera(image_width, image_height, fov);
            let scene = my_scene::cornell::get_scene();
            Some((camera, scene))
        },
        "bunny" => {
            // Bunny. Around 300 primitives, 2 lights. Uses octree. Has skybox, textures are
            // in another repository.
            let camera = my_scene::bunny::get_camera(image_width, image_height, fov);
            let scene = my_scene::bunny::get_scene();
            Some((camera, scene))
        },
        "teapot" => {
            // Teapot. Around 2500 polygons. Octree helps a bit. Has skybox.
            let camera = my_scene::teapot::get_teapot_camera(image_width, image_height, fov);
            let scene = my_scene::teapot::get_teapot_scene();
            Some((camera, scene))
        },
        "cow" => {
            // Cow. Around 5000 polygons. Octree helps considerably.
            let camera = my_scene::cow::get_camera(image_width, image_height, fov);
            let scene = my_scene::cow::get_scene();
            Some((camera, scene))
        },
        "lucy" => {
            // Lucy. Around 525814+1 primitives. Octree pretty much required. The model is included
            // separately, in another repository. Has skybox.
            let camera = my_scene::lucy::get_camera(image_width, image_height, fov);
            let scene = my_scene::lucy::get_scene();
            Some((camera, scene))
        },
        "sponza" => {
            // Sponza. Around 28K triangles, but more complex than Lucy. 2 lights.
            let camera = my_scene::sponza::get_camera(image_width, image_height, fov);
            let scene = my_scene::sponza::get_scene();
            Some((camera, scene))
        },
        "sibenik" => {
            // Sibenik, around 70K triangles, no texture work, 3 lights.
            let camera = match config.animating {
                true => my_scene::sibenik::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sibenik::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sibenik::get_scene();
            Some((camera, scene))
        },
        "heptoroid-white" => {
            // Heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("white");
            Some((camera, scene))
        },
        "heptoroid-shiny" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("shiny");
            Some((camera, scene))
        },
        "heptoroid-refractive" => {
            // Refractive heptoroid, you want to limit your reflect levels (2/3?)
            // and up your refract levels (10/16?) for this
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("refractive");
            Some((camera, scene))
        },
        "tachikoma" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            // You can forget about refractions, it's too complex a scene
            let camera = my_scene::tachikoma::get_camera(image_width, image_height, fov);
            let scene = my_scene::tachikoma::get_scene();
            Some((camera, scene))
        },
        "sphere" => {
            // Sphere skybox test scene
            let camera = match config.animating {
                true => my_scene::sphere::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sphere::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sphere::get_scene();
            Some((camera, scene))
        },
        "fresnel" => {
            // Fresnel test scene
            let camera = match config.animating {
                true => my_scene::fresnel::get_animation_camera(image_width, image_height, fov),
                false => my_scene::fresnel::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::fresnel::get_scene();
            Some((camera, scene))
        },
        _ => None
    };
}

fn main() {
    let start_time = ::time::get_time().sec;

    let program_args = match parse_args(env::args()) {
        Ok(program_args) => program_args,
        Err(error_str) => {
            write!(&mut io::stderr(), "{}\n", error_str).unwrap();
            env::set_exit_status(1);
            return
        }
    };
    let mut file_handle = match File::open(&program_args.config_file) {
        Ok(file) => file,
        Err(err) => {
            write!(&mut io::stderr(), "{}\n", err).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    let mut json_data = String::new();
    if let Err(ref err) = file_handle.read_to_string(&mut json_data) {
        write!(&mut io::stderr(), "{}\n", err).unwrap();
        env::set_exit_status(1);
        return
    }

    let config: SceneConfig = match json::decode(&json_data) {
        Ok(data) => data,
        Err(err) => {
            let msg = match err {
                MissingFieldError(field_name) => {
                    format!("parse failure, missing field ``{}''\n", field_name)
                },
                _ => {
                    format!("parse failure: {:?}", err)
                }
            };
            write!(&mut io::stderr(), "{}\n", msg).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    println!("Job started at {}...\nLoading scene...", start_time);

    let scenepair = get_camera_and_scene(&config);
    let (camera, scene) = match scenepair {
        Some(pair) => pair,
        None => {
            write!(&mut io::stderr(), "unknown scene ``{}''\n", config.name).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    let shared_scene = Arc::new(scene); // Hackish solution for animator

    let scene_time = ::time::get_time().sec;
    println!("Scene loaded at {} ({}s)...", scene_time, scene_time - start_time);

    let renderer = raytracer::Renderer {
        reflect_depth: config.reflect_depth,
        refract_depth: config.refract_depth,
        shadow_samples: config.shadow_samples,
        pixel_samples: config.pixel_samples,
        // Number of tasks to spawn. Will use up max available cores.
        tasks: ::num_cpus::get()
    };

    if config.animating {
        let (animate_from, animate_to) = config.time_slice;

        let animator = raytracer::animator::Animator {
            fps: config.fps,
            animate_from: animate_from,
            animate_to: animate_to,
            starting_frame_number: config.starting_frame_number,
            renderer: renderer
        };

        println!("Animating - tasks: {}, FPS: {}, start: {}s, end:{}s, starting frame: {}",
                 ::num_cpus::get(), animator.fps, animator.animate_from, animator.animate_to,
                 animator.starting_frame_number);
        animator.animate(camera, shared_scene, &config.output_file);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)",
                 render_time, render_time - scene_time);
    } else {
        // Still frame
        println!("Rendering with {} tasks...", ::num_cpus::get());
        let image_data = renderer.render(camera, shared_scene);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)...\nWriting file...",
                 render_time, render_time - scene_time);

        let out_file = format!("{}{}", config.output_file, ".ppm");
        util::export::to_ppm(image_data, &out_file);
        let export_time = ::time::get_time().sec;

        println!("Write done: {} ({}s). Written to {}\nTotal: {}s",
                 export_time, export_time - render_time,
                 config.output_file, export_time - start_time);
    }
}
<commit_msg>Track rust nightly<commit_after>#![feature(collections, convert, core, exit_status, float_consts, semaphore, slice_extras, std_misc, vec_push_all)]
#![deny(unused_imports)]

extern crate num;
extern crate num_cpus;
extern crate rand;
extern crate rustc_serialize;
extern crate threadpool;
extern crate time;

use scene::{Camera, Scene};

use std::fs::File;
use std::io::{self, Read, Write};
use std::env;
use std::sync::Arc;
use rustc_serialize::json;
use rustc_serialize::json::DecoderError::MissingFieldError;

mod geometry;
mod light;
mod material;
mod my_scene;
mod raytracer;
mod scene;
mod util;
mod vec3;
mod mat4;

// Replace this with argparse eventually
struct ProgramArgs {
    config_file: String
}

#[derive(RustcDecodable, RustcEncodable)]
struct SceneConfig {
    name: String,
    size: (u32, u32),
    fov: f64,
    reflect_depth: u32,
    refract_depth: u32,
    shadow_samples: u32,
    pixel_samples: u32,
    output_file: String,
    animating: bool,
    fps: f64,
    time_slice: (f64, f64),
    starting_frame_number: u32
}

fn parse_args(args: env::Args) -> Result<ProgramArgs, String> {
    let args = args.collect::<Vec<String>>();
    if args.len() == 0 {
        panic!("Args do not even include a program name");
    }

    let program_name = &args[0];
    match args.len() {
        // I wouldn't expect this in the wild
        0 => unreachable!(),
        1 => Err(format!("Usage: {} scene_config.json", program_name)),
        2 => Ok(ProgramArgs { config_file: args[1].clone() }),
        _ => Err(format!("Usage: {} scene_config.json", program_name)),
    }
}

fn get_camera_and_scene(config: &SceneConfig) -> Option<(Camera, Scene)> {
    let scene_name = config.name.clone();
    let (image_width, image_height) = config.size;
    let fov = config.fov;

    // Cameras, scenes created in ./my_scene.rs
    // Scenes with an octree supplied (see my_scene.rs) will use it.
    // Lower the render quality (especially shadow_samples) for complex scenes
    return match scene_name.as_ref() {
        "box" => {
            // Box. Simplest scene with 9 primitives, no octree
            let camera = my_scene::cornell::get_camera(image_width, image_height, fov);
            let scene = my_scene::cornell::get_scene();
            Some((camera, scene))
        },
        "bunny" => {
            // Bunny. Around 300 primitives, 2 lights. Uses octree. Has skybox, textures are
            // in another repository.
            let camera = my_scene::bunny::get_camera(image_width, image_height, fov);
            let scene = my_scene::bunny::get_scene();
            Some((camera, scene))
        },
        "teapot" => {
            // Teapot. Around 2500 polygons. Octree helps a bit. Has skybox.
            let camera = my_scene::teapot::get_teapot_camera(image_width, image_height, fov);
            let scene = my_scene::teapot::get_teapot_scene();
            Some((camera, scene))
        },
        "cow" => {
            // Cow. Around 5000 polygons. Octree helps considerably.
            let camera = my_scene::cow::get_camera(image_width, image_height, fov);
            let scene = my_scene::cow::get_scene();
            Some((camera, scene))
        },
        "lucy" => {
            // Lucy. Around 525814+1 primitives. Octree pretty much required. The model is included
            // separately, in another repository. Has skybox.
            let camera = my_scene::lucy::get_camera(image_width, image_height, fov);
            let scene = my_scene::lucy::get_scene();
            Some((camera, scene))
        },
        "sponza" => {
            // Sponza. Around 28K triangles, but more complex than Lucy. 2 lights.
            let camera = my_scene::sponza::get_camera(image_width, image_height, fov);
            let scene = my_scene::sponza::get_scene();
            Some((camera, scene))
        },
        "sibenik" => {
            // Sibenik, around 70K triangles, no texture work, 3 lights.
            let camera = match config.animating {
                true => my_scene::sibenik::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sibenik::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sibenik::get_scene();
            Some((camera, scene))
        },
        "heptoroid-white" => {
            // Heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("white");
            Some((camera, scene))
        },
        "heptoroid-shiny" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("shiny");
            Some((camera, scene))
        },
        "heptoroid-refractive" => {
            // Refractive heptoroid, you want to limit your reflect levels (2/3?)
            // and up your refract levels (10/16?) for this
            let camera = my_scene::heptoroid::get_camera(image_width, image_height, fov);
            let scene = my_scene::heptoroid::get_scene("refractive");
            Some((camera, scene))
        },
        "tachikoma" => {
            // Shiny heptoroid, 114688 tris, 57302 verts
            // You can forget about refractions, it's too complex a scene
            let camera = my_scene::tachikoma::get_camera(image_width, image_height, fov);
            let scene = my_scene::tachikoma::get_scene();
            Some((camera, scene))
        },
        "sphere" => {
            // Sphere skybox test scene
            let camera = match config.animating {
                true => my_scene::sphere::get_animation_camera(image_width, image_height, fov),
                false => my_scene::sphere::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::sphere::get_scene();
            Some((camera, scene))
        },
        "fresnel" => {
            // Fresnel test scene
            let camera = match config.animating {
                true => my_scene::fresnel::get_animation_camera(image_width, image_height, fov),
                false => my_scene::fresnel::get_camera(image_width, image_height, fov)
            };
            let scene = my_scene::fresnel::get_scene();
            Some((camera, scene))
        },
        _ => None
    };
}

fn main() {
    let start_time = ::time::get_time().sec;

    let program_args = match parse_args(env::args()) {
        Ok(program_args) => program_args,
        Err(error_str) => {
            write!(&mut io::stderr(), "{}\n", error_str).unwrap();
            env::set_exit_status(1);
            return
        }
    };
    let mut file_handle = match File::open(&program_args.config_file) {
        Ok(file) => file,
        Err(err) => {
            write!(&mut io::stderr(), "{}\n", err).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    let mut json_data = String::new();
    if let Err(ref err) = file_handle.read_to_string(&mut json_data) {
        write!(&mut io::stderr(), "{}\n", err).unwrap();
        env::set_exit_status(1);
        return
    }

    let config: SceneConfig = match json::decode(&json_data) {
        Ok(data) => data,
        Err(err) => {
            let msg = match err {
                MissingFieldError(field_name) => {
                    format!("parse failure, missing field ``{}''\n", field_name)
                },
                _ => {
                    format!("parse failure: {:?}", err)
                }
            };
            write!(&mut io::stderr(), "{}\n", msg).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    println!("Job started at {}...\nLoading scene...", start_time);

    let scenepair = get_camera_and_scene(&config);
    let (camera, scene) = match scenepair {
        Some(pair) => pair,
        None => {
            write!(&mut io::stderr(), "unknown scene ``{}''\n", config.name).unwrap();
            env::set_exit_status(1);
            return
        }
    };

    let shared_scene = Arc::new(scene); // Hackish solution for animator

    let scene_time = ::time::get_time().sec;
    println!("Scene loaded at {} ({}s)...", scene_time, scene_time - start_time);

    let renderer = raytracer::Renderer {
        reflect_depth: config.reflect_depth,
        refract_depth: config.refract_depth,
        shadow_samples: config.shadow_samples,
        pixel_samples: config.pixel_samples,
        // Number of tasks to spawn. Will use up max available cores.
        tasks: ::num_cpus::get()
    };

    if config.animating {
        let (animate_from, animate_to) = config.time_slice;

        let animator = raytracer::animator::Animator {
            fps: config.fps,
            animate_from: animate_from,
            animate_to: animate_to,
            starting_frame_number: config.starting_frame_number,
            renderer: renderer
        };

        println!("Animating - tasks: {}, FPS: {}, start: {}s, end:{}s, starting frame: {}",
                 ::num_cpus::get(), animator.fps, animator.animate_from, animator.animate_to,
                 animator.starting_frame_number);
        animator.animate(camera, shared_scene, &config.output_file);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)",
                 render_time, render_time - scene_time);
    } else {
        // Still frame
        println!("Rendering with {} tasks...", ::num_cpus::get());
        let image_data = renderer.render(camera, shared_scene);
        let render_time = ::time::get_time().sec;
        println!("Render done at {} ({}s)...\nWriting file...",
                 render_time, render_time - scene_time);

        let out_file = format!("{}{}", config.output_file, ".ppm");
        util::export::to_ppm(image_data, &out_file);
        let export_time = ::time::get_time().sec;

        println!("Write done: {} ({}s). Written to {}\nTotal: {}s",
                 export_time, export_time - render_time,
                 config.output_file, export_time - start_time);
    }
}
<|endoftext|>