<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::{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,
    Macro,
    Trait,
    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,
            "trait" => Type::Trait,
            "macro" => Type::Macro,
            "macro_rules" => Type::Macro,
            "macro_rules!" => Type::Macro,
            _ => 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"),
            Type::Trait => write!(f, "trait"),
            Type::Macro => write!(f, "macro"),
            _ => 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] {
        if words[*it] == "\n" {
            *line += 1;
        }
        *it += 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("!(", " !! (")
                                   .replace(",", ", ")
                                   .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!();
            let mut comments = 0;

            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);
                        comments += 1;
                    }
                    "//!" => {
                        event_list.push(EventType::FileComment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n", &mut line);
                        comments += 1;
                    }
                    "/*!" => {
                        let mark = line;
                        move_until(&words, &mut it, "*/", &mut line);
                        for pos in mark..line {
                            event_list.push(EventType::FileComment(b_content[pos].to_owned()));
                        }
                        event_list.push(EventType::FileComment("*/".to_owned()));
                        comments += 1;
                    }
                    "struct" | "mod" | "fn" | "enum" | "const" | "static" | "type" | "use" | "trait" | "macro_rules!" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from(words[it]), words[it + 1])));
                        it += 1;
                    }
                    "!!" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from("macro"), &format!("{}!{}", words[it - 1], 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;
            }
            if comments < 1 {
                return;
            }
            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 => {
                                        match current {
                                            Some(ref cur) => {
                                                if cur.ty == Type::Enum || cur.ty == Type::Struct || cur.ty == Type::Use {
                                                    if t.name == "pub" {
                                                        true
                                                    } else {
                                                        let mut copy = t.clone();
                                                        copy.ty = Type::Variant;
                                                        let tmp = add_to_type_scope(&current, &Some(copy));
                                                        write!(out_file, "=| {}\n{}", tmp.unwrap(), comments).unwrap();
                                                        false
                                                    }
                                                } else {
                                                    false
                                                }
                                            }
                                            None => false,
                                        }
                                    },
                                    _ => {
                                        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<commit_msg>Better rust style<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,
    Macro,
    Trait,
    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,
            "trait" => Type::Trait,
            "macro" | "macro_rules" | "macro_rules!" => Type::Macro,
            _ => 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"),
            Type::Trait => write!(f, "trait"),
            Type::Macro => write!(f, "macro"),
            _ => 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] {
        if words[*it] == "\n" {
            *line += 1;
        }
        *it += 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("*/", " */")
                                   .replace("\n", " \n ")
                                   .replace("!(", " !! (")
                                   .replace(",", ", ")
                                   .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!();
            let mut comments = 0;

            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);
                        comments += 1;
                    }
                    "//!" => {
                        event_list.push(EventType::FileComment(b_content[line].to_owned()));
                        move_to(&words, &mut it, "\n", &mut line);
                        comments += 1;
                    }
                    "/*!" => {
                        let mark = line;
                        move_until(&words, &mut it, "*/", &mut line);
                        for pos in mark..line {
                            event_list.push(EventType::FileComment(b_content[pos].to_owned()));
                        }
                        event_list.push(EventType::FileComment("*/".to_owned()));
                        comments += 1;
                    }
                    "struct" | "mod" | "fn" | "enum" | "const" | "static" | "type" | "use" | "trait" | "macro_rules!" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from(words[it]), words[it + 1])));
                        it += 1;
                    }
                    "!!" => {
                        event_list.push(EventType::Type(TypeStruct::new(Type::from("macro"), &format!("{}!{}", words[it - 1], 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;
            }
            if comments < 1 {
                return;
            }
            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 => {
                                        match current {
                                            Some(ref cur) => {
                                                if cur.ty == Type::Enum || cur.ty == Type::Struct || cur.ty == Type::Use {
                                                    if t.name == "pub" {
                                                        true
                                                    } else {
                                                        let mut copy = t.clone();
                                                        copy.ty = Type::Variant;
                                                        let tmp = add_to_type_scope(&current, &Some(copy));
                                                        write!(out_file, "=| {}\n{}", tmp.unwrap(), comments).unwrap();
                                                        false
                                                    }
                                                } else {
                                                    false
                                                }
                                            }
                                            None => false,
                                        }
                                    },
                                    _ => {
                                        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>struct AddressSpace {
    data: [u8; 0xFFFF],
}

impl AddressSpace {

    fn new() -> AddressSpace {
        AddressSpace { data: [0; 0xFFFF] }
    }

    fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        self.data.slice(addr as usize, (addr + bytes) as usize)
    }

    fn write(&mut self, addr: u16, data: u8) {
        self.data[addr as usize] = data;
    }

}

struct Instr {
    opcode: u8,
    data: Vec<u8>,
    cycles: u32,
}

impl Instr {

    fn parse(reg: &mut RegData, rom: &AddressSpace) -> Instr {
        let opcode = rom.read(reg.advance_pc());
        Instr {
            opcode: opcode,
            data: Vec::new(),
            cycles: 4,
        }
    }

    fn opcode(&self) -> u8 {
        self.opcode
    }

    fn cycles(&self) -> u32 {
        self.cycles
    }

    fn param(&self, i: usize) -> u8 {
        self.data[i]
    }

}

enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = ((data & 0xFF00 >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.c = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

}

static GB_FREQUENCY: u32 = 4194304;

struct Cpu {
    reg: RegData,
    ram: AddressSpace,
    freq: u32,
    clock: u64,
    cycle_block: u32,
}

impl Cpu {

    fn new() -> Cpu {
        Cpu::new_with_freq(GB_FREQUENCY)
    }

    fn new_with_freq(freq: u32) -> Cpu {
        Cpu {
            reg: RegData::new(),
            ram: AddressSpace::new(),
            freq: freq,
            clock: 0,
            cycle_block: 0,
        }
    }

    fn do_cycle(&mut self) {
        self.clock += 1;
        if self.cycle_block > 0 {
            self.cycle_block -= 1;
        } else {
            let instr = Instr::parse(&mut self.reg, &self.ram);
            match instr.opcode() {
                _ => panic!("Instruction not implemented!"),
            }
        }
    }

}

fn main() {
    println!("Hello, world!");
}
<commit_msg>Implement 16-bit instruction param reader<commit_after>struct AddressSpace {
    data: [u8; 0xFFFF],
}

impl AddressSpace {

    fn new() -> AddressSpace {
        AddressSpace { data: [0; 0xFFFF] }
    }

    fn read(&self, addr: u16) -> u8 {
        self.data[addr as usize]
    }

    fn read_slice(&self, addr: u16, bytes: u16) -> &[u8] {
        self.data.slice(addr as usize, (addr + bytes) as usize)
    }

    fn write(&mut self, addr: u16, data: u8) {
        self.data[addr as usize] = data;
    }

}

struct Instr {
    opcode: u8,
    data: Vec<u8>,
    cycles: u32,
}

impl Instr {

    fn parse(reg: &mut RegData, rom: &AddressSpace) -> Instr {
        let opcode = rom.read(reg.advance_pc());
        Instr {
            opcode: opcode,
            data: Vec::new(),
            cycles: 4,
        }
    }

    fn opcode(&self) -> u8 {
        self.opcode
    }

    fn cycles(&self) -> u32 {
        self.cycles
    }

    fn param(&self, i: usize) -> u8 {
        self.data[i]
    }

    fn param_u16(&self, i: usize) -> u16 {
        (self.data[i] as u16) | ((self.data[i + 1] as u16) << 8)
    }

}

enum RegFlag {
    Zero,
    Subtract,
    HalfCarry,
    Carry,
}

enum Register {
    A,
    B,
    C,
    D,
    E,
    F,
    H,
    L,
    AF,
    BC,
    DE,
    HL,
    SP,
    PC,
    Flag,
}

struct RegData {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    f: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16,
    flag: u8,
}

impl RegData {

    fn new() -> RegData {
        RegData {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: 0,
            h: 0,
            l: 0,
            sp: 0xFFFE,
            pc: 0x100,
            flag: 0,
        }
    }

    fn read(&self, reg: Register) -> u8 {
        match reg {
            Register::A => self.a,
            Register::B => self.b,
            Register::C => self.c,
            Register::D => self.d,
            Register::E => self.e,
            Register::F => self.f,
            Register::H => self.h,
            Register::L => self.l,
            Register::Flag => self.flag,
            _ => panic!("Register not available for 8-bit read"),
        }
    }

    fn read_u16(&self, reg: Register) -> u16 {
        match reg {
            Register::AF => (self.a as u16) << 8 | self.f as u16,
            Register::BC => (self.b as u16) << 8 | self.c as u16,
            Register::DE => (self.d as u16) << 8 | self.e as u16,
            Register::HL => (self.h as u16) << 8 | self.l as u16,
            Register::SP => self.sp,
            Register::PC => self.pc,
            _ => panic!("Register not available for 16-bit read"),
        }
    }

    fn write(&mut self, reg: Register, data: u8) {
        match reg {
            Register::A => self.a = data,
            Register::B => self.b = data,
            Register::C => self.c = data,
            Register::D => self.d = data,
            Register::E => self.e = data,
            Register::F => self.f = data,
            Register::H => self.h = data,
            Register::L => self.l = data,
            _ => panic!("Register not available for 8-bit write"),
        }
    }

    fn write_u16(&mut self, reg: Register, data: u16) {
        let (hi, lo) = ((data & 0xFF00 >> 8) as u8, (data & 0xFF) as u8);
        match reg {
            Register::AF => {
                self.a = hi;
                self.f = lo;
            },
            Register::BC => {
                self.b = hi;
                self.c = lo;
            },
            Register::DE => {
                self.d = hi;
                self.c = lo;
            },
            Register::HL => {
                self.h = hi;
                self.l = lo;
            },
            Register::SP => self.sp = data,
            Register::PC => self.pc = data,
            _ => panic!("Register not available for 16-bit write"),
        }
    }

    fn copy(&mut self, dst: Register, src: Register) {
        let data = self.read(src);
        self.write(dst, data);
    }

    fn copy_u16(&mut self, dst: Register, src: Register) {
        let data = self.read_u16(src);
        self.write_u16(dst, data);
    }

    fn set_flag(&mut self, flag: RegFlag, on: bool) {
        let bit = match flag {
            RegFlag::Zero => 0x80,
            RegFlag::Subtract => 0x40,
            RegFlag::HalfCarry => 0x20,
            RegFlag::Carry => 0x10,
        };
        if (on) {
            self.flag |= bit;
        } else {
            self.flag &= bit ^ 0xFF;
        }
    }

    fn advance_pc(&mut self) -> u16 {
        let pc = self.pc;
        self.pc += 1;
        pc
    }

}

static GB_FREQUENCY: u32 = 4194304;

struct Cpu {
    reg: RegData,
    ram: AddressSpace,
    freq: u32,
    clock: u64,
    cycle_block: u32,
}

impl Cpu {

    fn new() -> Cpu {
        Cpu::new_with_freq(GB_FREQUENCY)
    }

    fn new_with_freq(freq: u32) -> Cpu {
        Cpu {
            reg: RegData::new(),
            ram: AddressSpace::new(),
            freq: freq,
            clock: 0,
            cycle_block: 0,
        }
    }

    fn do_cycle(&mut self) {
        self.clock += 1;
        if self.cycle_block > 0 {
            self.cycle_block -= 1;
        } else {
            let instr = Instr::parse(&mut self.reg, &self.ram);
            match instr.opcode() {
                _ => panic!("Instruction not implemented!"),
            }
        }
    }

}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>extern crate cairo_sys;
extern crate cairo;
extern crate chrono;
extern crate futures;
extern crate mio;
extern crate pango;
extern crate pangocairo;
extern crate tokio_core;
extern crate tokio_timer;
extern crate xcb_util;
extern crate xcb;

use std::rc::Rc;

use futures::{Async, Future, Poll, Stream};
use mio::unix::EventedFd;

mod text;
use text::*;
mod widgets;
use widgets::*;
mod window;
use window::*;

fn main() {
    let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
    let conn = Rc::new(conn);

    let w = Window::new(conn.clone(), screen_idx as usize);

    use tokio_core::reactor::{Core, Handle, PollEvented};

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    struct XcbEventStream<'a> {
        conn: Rc<xcb::Connection>,
        poll: PollEvented<EventedFd<'a>>,
        would_block: bool,
    };

    impl<'a> XcbEventStream<'a> {
        fn new(conn: Rc<xcb::Connection>,
               conn_fd: &'a std::os::unix::io::RawFd,
               handle: &Handle)
               -> XcbEventStream<'a> {
            // XXX Lifetime of the connection?
            XcbEventStream {
                conn: conn,
                poll: PollEvented::new(EventedFd(conn_fd), &handle).unwrap(),
                would_block: true,
            }
        }
    }

    impl<'a> Stream for XcbEventStream<'a> {
        type Item = xcb::GenericEvent;
        type Error = ();

        fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
            if self.would_block {
                match self.poll.poll_read() {
                    Async::Ready(()) => self.would_block = false,
                    Async::NotReady => return Ok(Async::NotReady),
                }
            }

            match self.conn.poll_for_event() {
                Some(event) => Ok(Async::Ready(Some(event))),
                None => {
                    self.would_block = true;
                    self.poll.need_read();
                    Ok(Async::NotReady)
                }
            }
        }
    }

    let inactive_attr = Attributes {
        font: pango::FontDescription::from_string("Envy Code R 27"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(10.0, 10.0, 5.0, 5.0),
    };
    let active_attr = inactive_attr.with_bg_color(Some(Color::blue()));

    let conn_fd = unsafe { xcb::ffi::base::xcb_get_file_descriptor(conn.get_raw_conn()) };
    let stream = XcbEventStream::new(conn.clone(), &conn_fd, &handle);

    let widgets: Vec<Box<Widget>> = vec![
        Box::new(Pager::new(active_attr, inactive_attr.clone())) as Box<Widget>,
        Box::new(ActiveWindowTitle::new(inactive_attr.clone())) as Box<Widget>,
        Box::new(Clock::new(inactive_attr.clone())) as Box<Widget>,
    ];

    let widget_list = widgets::WidgetList::new(widgets);

    struct MainLoop<'a> {
        xcb_stream: XcbEventStream<'a>,
        widget_list: WidgetList,
        window: Window,
    }

    impl<'a> Future for MainLoop<'a> {
        type Item = ();
        type Error = ();

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.widget_list.poll() {
                Ok(Async::Ready(Some(texts))) => self.window.expose(texts),
                Err(e) => return Err(e),
                _ => {}
            }
            match self.xcb_stream.poll() {
                Ok(Async::Ready(Some(event))) => {
                    let r = event.response_type() & !0x80;
                    match r {
                        xcb::EXPOSE => self.window.expose(self.widget_list.texts()),
                        _ => {}
                    }
                },
                Err(e) => return Err(e),
                _ => {},
            }
            Ok(Async::NotReady)
        }
    }

    let fut = MainLoop {
        xcb_stream: stream,
        widget_list: widget_list,
        window: w,
    };

    core.run(fut).unwrap();
}
<commit_msg>Remove needless borrow.<commit_after>extern crate cairo_sys;
extern crate cairo;
extern crate chrono;
extern crate futures;
extern crate mio;
extern crate pango;
extern crate pangocairo;
extern crate tokio_core;
extern crate tokio_timer;
extern crate xcb_util;
extern crate xcb;

use std::rc::Rc;

use futures::{Async, Future, Poll, Stream};
use mio::unix::EventedFd;

mod text;
use text::*;
mod widgets;
use widgets::*;
mod window;
use window::*;

fn main() {
    let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
    let conn = Rc::new(conn);

    let w = Window::new(conn.clone(), screen_idx as usize);

    use tokio_core::reactor::{Core, Handle, PollEvented};

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    struct XcbEventStream<'a> {
        conn: Rc<xcb::Connection>,
        poll: PollEvented<EventedFd<'a>>,
        would_block: bool,
    };

    impl<'a> XcbEventStream<'a> {
        fn new(conn: Rc<xcb::Connection>,
               conn_fd: &'a std::os::unix::io::RawFd,
               handle: &Handle)
               -> XcbEventStream<'a> {
            // XXX Lifetime of the connection?
            XcbEventStream {
                conn: conn,
                poll: PollEvented::new(EventedFd(conn_fd), handle).unwrap(),
                would_block: true,
            }
        }
    }

    impl<'a> Stream for XcbEventStream<'a> {
        type Item = xcb::GenericEvent;
        type Error = ();

        fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
            if self.would_block {
                match self.poll.poll_read() {
                    Async::Ready(()) => self.would_block = false,
                    Async::NotReady => return Ok(Async::NotReady),
                }
            }

            match self.conn.poll_for_event() {
                Some(event) => Ok(Async::Ready(Some(event))),
                None => {
                    self.would_block = true;
                    self.poll.need_read();
                    Ok(Async::NotReady)
                }
            }
        }
    }

    let inactive_attr = Attributes {
        font: pango::FontDescription::from_string("Envy Code R 27"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(10.0, 10.0, 5.0, 5.0),
    };
    let active_attr = inactive_attr.with_bg_color(Some(Color::blue()));

    let conn_fd = unsafe { xcb::ffi::base::xcb_get_file_descriptor(conn.get_raw_conn()) };
    let stream = XcbEventStream::new(conn.clone(), &conn_fd, &handle);

    let widgets: Vec<Box<Widget>> = vec![
        Box::new(Pager::new(active_attr, inactive_attr.clone())) as Box<Widget>,
        Box::new(ActiveWindowTitle::new(inactive_attr.clone())) as Box<Widget>,
        Box::new(Clock::new(inactive_attr.clone())) as Box<Widget>,
    ];

    let widget_list = widgets::WidgetList::new(widgets);

    struct MainLoop<'a> {
        xcb_stream: XcbEventStream<'a>,
        widget_list: WidgetList,
        window: Window,
    }

    impl<'a> Future for MainLoop<'a> {
        type Item = ();
        type Error = ();

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.widget_list.poll() {
                Ok(Async::Ready(Some(texts))) => self.window.expose(texts),
                Err(e) => return Err(e),
                _ => {}
            }
            match self.xcb_stream.poll() {
                Ok(Async::Ready(Some(event))) => {
                    let r = event.response_type() & !0x80;
                    match r {
                        xcb::EXPOSE => self.window.expose(self.widget_list.texts()),
                        _ => {}
                    }
                },
                Err(e) => return Err(e),
                _ => {},
            }
            Ok(Async::NotReady)
        }
    }

    let fut = MainLoop {
        xcb_stream: stream,
        widget_list: widget_list,
        window: w,
    };

    core.run(fut).unwrap();
}
<|endoftext|>


<commit_before>extern crate image;
extern crate time;

extern crate rusttracer;

use std::path::Path;
use std::env;

use rusttracer::math::Vector3;
use rusttracer::{Scene, Color, Camera, MaterialTemplate, Renderer, SuperSampling};
use rusttracer::geometry::{Shape, Sphere, Plane};
use rusttracer::lights::PointLight;

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 2560;
const HEIGHT: u32 = 1440;
const BUFFER_SIZE: usize = (WIDTH * HEIGHT * 3) as usize;
const DEFAULT_NUMBER_OF_THREADS: u32 = 4;

fn main() {
    let num_threads = match env::var("NUM_THREADS") {
        Ok(threads) => threads.parse::<u32>().unwrap_or(DEFAULT_NUMBER_OF_THREADS),
        Err(_) => DEFAULT_NUMBER_OF_THREADS,
    };

    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };
    let template = MaterialTemplate::new(Color::blue() * 0.02,
                                         Color::black(),
                                         Color::black(),
                                         None,
                                         None);

    let floor_material = template.build_material(|material| {
                                                     material.ambient_color = Color::white() * 0.05;
                                                     material.diffuse_color = Color::white() * 0.3;
                                                 });
    let floor = Plane::new(Vector3::new(0.0, -5.0, 0.0),
                           Vector3::new(0.0, 1.0, 0.0),
                           floor_material);

    let back_material =
        template.build_material(|material| { material.diffuse_color = Color::white() * 0.8; });
    let back = Plane::new(Vector3::new(0.0, 0.0, 50.0),
                          Vector3::new(0.0, 0.0, -1.0),
                          back_material);

    let m1 = template.build_material(|material| { material.reflection_coefficient = Some(1.0); });
    let s1 = Sphere::new(Vector3::new(0.0, -4.0, 45.0), 1.0, m1);

    let l1 = PointLight::new(Vector3::new(0.0, 10.0, 45.0), Color::new(67, 249, 253), 0.4);
    let l2 = PointLight::new(Vector3::new(-15.0, 10.0, 45.0),
                             Color::new(92, 253, 67),
                             0.4);
    let l3 = PointLight::new(Vector3::new(15.0, 10.0, 45.0), Color::new(253, 115, 6), 0.4);

    let objects: Vec<&Shape> = vec![&s1, &floor, &back];
    let lights: Vec<&PointLight> = vec![&l1, &l2, &l3];
    let scene = Scene::new(&objects, &lights, Color::black());
    let camera = Camera::new(0.873,
                             WIDTH,
                             HEIGHT,
                             Vector3::new(-10.0, 5.0, 10.0),
                             s1.origin,
                             Vector3::new(0.0, 1.0, 0.0));

    if benchmark {
        for _ in 0..10 {
            let _ = renderer.render(MAX_DEPTH);
        }

        return;
    }

    let result: Vec<Color> = renderer.render(MAX_DEPTH);
    let mut buffer = vec![0x8C; BUFFER_SIZE];

    for (index, pixel) in result.iter().enumerate() {
        buffer[(index * 3) + 0] = pixel.r();
        buffer[(index * 3) + 1] = pixel.g();
        buffer[(index * 3) + 2] = pixel.b();
    }

    let timestamp = time::get_time().sec;
    let filename = format!("images/{}.png", timestamp);
    image::save_buffer(&Path::new(&filename),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<commit_msg>Unbreak build<commit_after>extern crate image;
extern crate time;

extern crate rusttracer;

use std::path::Path;
use std::env;

use rusttracer::math::Vector3;
use rusttracer::{Scene, Color, Camera, MaterialTemplate, Renderer, SuperSampling};
use rusttracer::geometry::{Shape, Sphere, Plane};
use rusttracer::lights::PointLight;

const MAX_DEPTH: u32 = 5;
const WIDTH: u32 = 2560;
const HEIGHT: u32 = 1440;
const BUFFER_SIZE: usize = (WIDTH * HEIGHT * 3) as usize;
const DEFAULT_NUMBER_OF_THREADS: u32 = 4;

fn main() {
    let num_threads = match env::var("NUM_THREADS") {
        Ok(threads) => threads.parse::<u32>().unwrap_or(DEFAULT_NUMBER_OF_THREADS),
        Err(_) => DEFAULT_NUMBER_OF_THREADS,
    };

    let benchmark = match env::var("BENCHMARK") {
        Ok(s) => s.parse::<bool>().unwrap_or(false),
        Err(_) => false,
    };
    let template = MaterialTemplate::new(Color::blue() * 0.02,
                                         Color::black(),
                                         Color::black(),
                                         None,
                                         None);

    let floor_material = template.build_material(|material| {
                                                     material.ambient_color = Color::white() * 0.05;
                                                     material.diffuse_color = Color::white() * 0.3;
                                                 });
    let floor = Plane::new(Vector3::new(0.0, -5.0, 0.0),
                           Vector3::new(0.0, 1.0, 0.0),
                           floor_material);

    let back_material =
        template.build_material(|material| { material.diffuse_color = Color::white() * 0.8; });
    let back = Plane::new(Vector3::new(0.0, 0.0, 50.0),
                          Vector3::new(0.0, 0.0, -1.0),
                          back_material);

    let m1 = template.build_material(|material| { material.reflection_coefficient = Some(1.0); });
    let s1 = Sphere::new(Vector3::new(0.0, -4.0, 45.0), 1.0, m1);

    let l1 = PointLight::new(Vector3::new(0.0, 10.0, 45.0), Color::new(67, 249, 253), 0.4);
    let l2 = PointLight::new(Vector3::new(-15.0, 10.0, 45.0),
                             Color::new(92, 253, 67),
                             0.4);
    let l3 = PointLight::new(Vector3::new(15.0, 10.0, 45.0), Color::new(253, 115, 6), 0.4);

    let objects: Vec<&Shape> = vec![&s1, &floor, &back];
    let lights: Vec<&PointLight> = vec![&l1, &l2, &l3];
    let scene = Scene::new(&objects, &lights, Color::black());
    let camera = Camera::new(0.873,
                             WIDTH,
                             HEIGHT,
                             Vector3::new(-10.0, 5.0, 10.0),
                             s1.origin,
                             Vector3::new(0.0, 1.0, 0.0));

    let renderer = Renderer::new(&scene, &camera, SuperSampling::On(2), num_threads);

    if benchmark {
        for _ in 0..10 {
            let _ = renderer.render(MAX_DEPTH);
        }

        return;
    }

    let result: Vec<Color> = renderer.render(MAX_DEPTH);
    let mut buffer = vec![0x8C; BUFFER_SIZE];

    for (index, pixel) in result.iter().enumerate() {
        buffer[(index * 3) + 0] = pixel.r();
        buffer[(index * 3) + 1] = pixel.g();
        buffer[(index * 3) + 2] = pixel.b();
    }

    let timestamp = time::get_time().sec;
    let filename = format!("images/{}.png", timestamp);
    image::save_buffer(&Path::new(&filename),
                       &buffer[..],
                       WIDTH,
                       HEIGHT,
                       image::RGB(8))
            .unwrap();
}
<|endoftext|>


<commit_before>fn main(expr: &str) -> i32 {
  let result = 0;
  for c in expr.chars() {
    match c {
      '0' ... '9' => println!("number"),
      ' ' => println!("space"),
      '+' => println!("plus"),
      _ => panic!("unsupported character")
    }
  }
  return result;
}

#[test]
fn it_adds() {
  let result = main("+1 2");
  assert_eq!(result, 3);
}
<commit_msg>Make it work for simple additions<commit_after>fn main(expr: &str) -> i32 {
  let mut result = 0;
  let mut stack:Vec<i32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<i32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand1 = stack.pop().expect("expected i32 values only in stack");
      let operand2 = stack.pop().expect("expected i32 values only in stack");
      result += match token {
        "+" => operand1 + operand2,
        _ => panic!("unsupported operator")
      }
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }
  return result;
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_operators() {
  main("1 2 =");
  // xxxFlorent: How to test the panic message is right?
}
<|endoftext|>


<commit_before>extern crate amy;
extern crate byteorder;
extern crate rand;
extern crate sha1;
extern crate url;
extern crate reqwest;
#[macro_use]
extern crate lazy_static;
extern crate net2;
extern crate serde;
extern crate serde_json;
extern crate tiny_http;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate toml;
extern crate signal;
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

mod bencode;
mod torrent;
mod util;
mod socket;
mod disk;
mod tracker;
mod control;
mod listener;
mod rpc;
mod throttle;
mod config;

use std::{time, env, thread};
use std::sync::atomic;
use std::io::Read;
use slog::Drain;

lazy_static! {
    pub static ref TC: atomic::AtomicUsize = {
        atomic::AtomicUsize::new(0)
    };

    pub static ref CONFIG: config::Config = {
        let args: Vec<_> = env::args().collect();
        if args.len() >= 2 {
            info!(LOG, "Using config file!");
            let mut s = String::new();
            let mut f = std::fs::File::open(&args[1]).expect("Config file could not be opened!");
            f.read_to_string(&mut s).expect("Config file could not be read!");
            let cf = toml::from_str(&s).expect("Config file could not be parsed!");
            config::Config::from_file(cf)
        } else {
            info!(LOG, "Using default config");
            Default::default()
        }
    };

    pub static ref PEER_ID: [u8; 20] = {
        use rand::{self, Rng};

        let mut pid = [0u8; 20];
        let prefix = b"-SN0001-";
        for i in 0..prefix.len() {
            pid[i] = prefix[i];
        }

        let mut rng = rand::thread_rng();
        for i in 8..19 {
            pid[i] = rng.gen::<u8>();
        }
        pid
    };

    pub static ref CONTROL: control::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "control"));
        control::start(log)
    };

    pub static ref DISK: disk::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "disk"));
        disk::start(log)
    };

    pub static ref TRACKER: tracker::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "tracker"));
        tracker::start(log)
    };

    pub static ref LISTENER: listener::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "listener"));
        listener::start(log)
    };

    pub static ref RPC: rpc::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "RPC"));
        rpc::start(log)
    };

    pub static ref LOG: slog::Logger = {
        let decorator = slog_term::TermDecorator::new().build();
        let drain = slog_term::FullFormat::new(decorator).build().fuse();
        let drain = slog_async::Async::new(drain).build().fuse();
        slog::Logger::root(drain, o!())
    };
}

fn main() {
    info!(LOG, "Initializing!");

    CONFIG.port;
    LISTENER.init();
    RPC.init();
    DISK.init();
    TRACKER.init();

    info!(LOG, "Initialized!");
    // Catch SIGINT, then shutdown
    let t = signal::trap::Trap::trap(&[2]);
    let mut i = time::Instant::now();
    loop {
        i += time::Duration::from_secs(1);
        if t.wait(i).is_some() {
            info!(LOG, "Shutting down!");
            CONTROL.ctrl_tx.lock().unwrap().send(control::Request::Shutdown).unwrap();
            while TC.load(atomic::Ordering::SeqCst) != 0 {
                thread::sleep(time::Duration::from_secs(1));
            }
            info!(LOG, "Shutdown complete!");
            break;
        }
        if TC.load(atomic::Ordering::SeqCst) == 0 {
            info!(LOG, "Shutdown complete!");
            break;
        }
    }
}
<commit_msg>Ensure config init succeeds<commit_after>extern crate amy;
extern crate byteorder;
extern crate rand;
extern crate sha1;
extern crate url;
extern crate reqwest;
#[macro_use]
extern crate lazy_static;
extern crate net2;
extern crate serde;
extern crate serde_json;
extern crate tiny_http;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate toml;
extern crate signal;
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

mod bencode;
mod torrent;
mod util;
mod socket;
mod disk;
mod tracker;
mod control;
mod listener;
mod rpc;
mod throttle;
mod config;

use std::{time, env, thread};
use std::sync::atomic;
use std::io::Read;
use slog::Drain;

lazy_static! {
    pub static ref TC: atomic::AtomicUsize = {
        atomic::AtomicUsize::new(0)
    };

    pub static ref CONFIG: config::Config = {
        let args: Vec<_> = env::args().collect();
        if args.len() >= 2 {
            info!(LOG, "Using config file!");
            let mut s = String::new();
            let contents = std::fs::File::open(&args[1]).and_then(|mut f| {
                f.read_to_string(&mut s).map(|_| s)
            });
            match contents {
                Ok(s) => {
                    match toml::from_str(&s) {
                        Ok(cf) => config::Config::from_file(cf),
                        Err(e) => {
                            error!(LOG, "Failed to parse config: {}. Falling back to default.", e);
                            Default::default()
                        }
                    }
                }
                Err(e) => {
                    error!(LOG, "Failed to open config: {}. Falling back to default.", e);
                    Default::default()
                }
            }
        } else {
            info!(LOG, "Using default config");
            Default::default()
        }
    };

    pub static ref PEER_ID: [u8; 20] = {
        use rand::{self, Rng};

        let mut pid = [0u8; 20];
        let prefix = b"-SN0001-";
        for i in 0..prefix.len() {
            pid[i] = prefix[i];
        }

        let mut rng = rand::thread_rng();
        for i in 8..19 {
            pid[i] = rng.gen::<u8>();
        }
        pid
    };

    pub static ref CONTROL: control::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "control"));
        control::start(log)
    };

    pub static ref DISK: disk::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "disk"));
        disk::start(log)
    };

    pub static ref TRACKER: tracker::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "tracker"));
        tracker::start(log)
    };

    pub static ref LISTENER: listener::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "listener"));
        listener::start(log)
    };

    pub static ref RPC: rpc::Handle = {
        TC.fetch_add(1, atomic::Ordering::SeqCst);
        let log = LOG.new(o!("thread" => "RPC"));
        rpc::start(log)
    };

    pub static ref LOG: slog::Logger = {
        let decorator = slog_term::TermDecorator::new().build();
        let drain = slog_term::FullFormat::new(decorator).build().fuse();
        let drain = slog_async::Async::new(drain).build().fuse();
        slog::Logger::root(drain, o!())
    };
}

fn main() {
    info!(LOG, "Initializing!");

    CONFIG.port;
    LISTENER.init();
    RPC.init();
    DISK.init();
    TRACKER.init();

    info!(LOG, "Initialized!");
    // Catch SIGINT, then shutdown
    let t = signal::trap::Trap::trap(&[2]);
    let mut i = time::Instant::now();
    loop {
        i += time::Duration::from_secs(1);
        if t.wait(i).is_some() {
            info!(LOG, "Shutting down!");
            CONTROL.ctrl_tx.lock().unwrap().send(control::Request::Shutdown).unwrap();
            while TC.load(atomic::Ordering::SeqCst) != 0 {
                thread::sleep(time::Duration::from_secs(1));
            }
            info!(LOG, "Shutdown complete!");
            break;
        }
        if TC.load(atomic::Ordering::SeqCst) == 0 {
            info!(LOG, "Shutdown complete!");
            break;
        }
    }
}
<|endoftext|>


<commit_before>extern crate notify;
extern crate libc;

use std::io;
use std::io::Write;
use libc::system;
use notify::{Event, RecommendedWatcher, Watcher};
use std::ffi::CString;
use std::string::String;
use std::sync::mpsc::{channel, Receiver, RecvError};
use std::{thread, time};

fn clear() {
    let s = CString::new("clear").unwrap();
    unsafe {
        system(s.as_ptr());
    }

}

fn invoke(cmd: &String) {
    let s = CString::new(cmd.clone()).unwrap();
    unsafe {
      system(s.as_ptr());
    }
}

fn wait(rx: &Receiver<Event>) -> Result<Event, RecvError> {
    let e = try!(rx.recv());

    thread::sleep(time::Duration::from_millis(250));

    loop {
        match rx.try_recv() {
            Ok(_) => continue,
            Err(_) => break,
        }
    }

    Ok(e)
}

fn main() {
    let cmd = std::env::args().nth(1).expect("Argument 1 needs to be a command");

    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = Watcher::new(tx)
        .expect("unable to create watcher");
    watcher.watch(".")
        .expect("unable to start watching directory");

    loop {
        //clear();
        let e = wait(&rx)
            .expect("error when waiting for filesystem changes");

        println!("{:?} {:?}", e.op, e.path);
        invoke(&cmd);
    }
}
<commit_msg>Ignore paths starting with a dot<commit_after>extern crate notify;
extern crate libc;

use std::env;
use libc::system;
use notify::{Event, RecommendedWatcher, Watcher};
use std::ffi::CString;
use std::path::{Path,PathBuf};
use std::string::String;
use std::sync::mpsc::{channel, Receiver, RecvError};
use std::{thread, time};

fn clear() {
    let s = CString::new("clear").unwrap();
    unsafe {
        system(s.as_ptr());
    }

}

fn ignored(relpath: &Path) -> bool {
    if relpath.to_str().unwrap().starts_with(".") {
        return true;
    }

    false
}

fn invoke(cmd: &String) {
    let s = CString::new(cmd.clone()).unwrap();
    unsafe {
      system(s.as_ptr());
    }
}

fn wait(rx: &Receiver<Event>, cwd: &PathBuf) -> Result<Event, RecvError> {
    loop {
        let e = try!(rx.recv());

        let ignored = match e.path {
            Some(ref path)  => {
                let stripped = path.strip_prefix(cwd).unwrap();
                ignored(stripped)
            },
            None        => false
        };

        if ignored {
            continue;
        }

        thread::sleep(time::Duration::from_millis(250));
        loop {
            match rx.try_recv() {
                Ok(_) => continue,
                Err(_) => break,
            }
        }

        return Ok(e);
    }
}

fn main() {
    let cmd = env::args().nth(1).expect("Argument 1 needs to be a command");
    let cwd = env::current_dir().unwrap();

    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = Watcher::new(tx)
        .expect("unable to create watcher");
    watcher.watch(".")
        .expect("unable to start watching directory");

    loop {
        clear();
        let e = wait(&rx, &cwd)
            .expect("error when waiting for filesystem changes");

        println!("{:?} {:?}", e.op, e.path);
        invoke(&cmd);
    }
}
<|endoftext|>


<commit_before>
mod curses;

use std::ffi::CString;

use curses::*;

enum DrawMe {
    Rec { width : i32, height : i32, x : i32, y : i32 },
    /*
    Character
    */
}

unsafe fn render_shape( s : &DrawMe ) {
    match s {
        &DrawMe::Rec { width, height, x, y } => render_rec( width, height, x, y ),
        _ => (),
    }
}

unsafe fn render_rec( w : i32, h : i32, x : i32, y : i32 ) {
    let dot = CString::new( "." ).unwrap();
    let h_line = CString::new( "-" ).unwrap();
    let v_line = CString::new( "|" ).unwrap();
    let plus = CString::new( "+" ).unwrap();

    let mut h2 = h + 2;
    while h2 > 0 {
        let d : &CString = if h2 == h + 2 {
            &h_line
        } else if h2 == 1 {
            &h_line
        } else {
            &dot
        };
        let mut w2 = w;

        let other_d : &CString = if h2 == h + 2 {
            &plus
        } else if h2 == 1 {
            &plus
        } else {
            &v_line
        };
        mvprintw( y + h2 + UserY, x + w2 + 1 + UserX, other_d.as_ptr() );
        while w2 > 0 {
            mvprintw( y + h2 + UserY, x + w2 + UserX, d.as_ptr() );
            w2 -= 1;
        }
        mvprintw( y + h2 + UserY, x + UserX, other_d.as_ptr() );
        h2 -= 1;
    }
}

static mut UserX : i32 = 0;
static mut UserY : i32 = 0;

fn main() {
    let mut x = 0;
    let mut y = 0;
    unsafe {
        initscr();
        cbreak();
        noecho();

        let mut c = getch();
        let mut shapes : Vec<DrawMe> = vec! [];

        // TODO need mode for entering rech, etc

        while c as u8 as char != 'q' {
            let c2 = c as u8 as char;

            match c2 {
                'r' => {
                    shapes.push( DrawMe::Rec { width: 0, height: 0, x: x - UserX, y: y - UserY } );
                },
                'j' => {
                    y+=1;
                },
                'k' => {
                    y-=1;
                },
                'l' => {
                    x+=1;
                },
                'h' => {
                    x-=1;
                },
                'J' => {
                    UserY += 1;
                },
                'K' => {
                    UserY -= 1;
                },
                'L' => {
                    UserX += 1;
                },
                'H' => {
                    UserX -= 1;
                },
                _ => (),
            }

            clear();

            for s in &shapes {
                render_shape( s );
            }

            cursor_move( y, x );
            refresh();

            c = getch();
        }

        endwin();
    }
}

<commit_msg>adding modes<commit_after>
mod curses;

use std::ffi::CString;

use curses::*;

enum DrawMe {
    Rec { width : i32, height : i32, x : i32, y : i32 },
    /*
    Character
    */
}

enum Mode { Normal, EnterRec, MoveRec }

unsafe fn render_shape( s : &DrawMe ) {
    match s {
        &DrawMe::Rec { width, height, x, y } => render_rec( width, height, x, y ),
        _ => (),
    }
}

unsafe fn render_rec( w : i32, h : i32, x : i32, y : i32 ) {
    let dot = CString::new( "." ).unwrap();
    let h_line = CString::new( "-" ).unwrap();
    let v_line = CString::new( "|" ).unwrap();
    let plus = CString::new( "+" ).unwrap();

    let mut h2 = h + 2;
    while h2 > 0 {
        let d : &CString = if h2 == h + 2 {
            &h_line
        } else if h2 == 1 {
            &h_line
        } else {
            &dot
        };
        let mut w2 = w;

        let other_d : &CString = if h2 == h + 2 {
            &plus
        } else if h2 == 1 {
            &plus
        } else {
            &v_line
        };
        mvprintw( y + h2 + UserY, x + w2 + 1 + UserX, other_d.as_ptr() );
        while w2 > 0 {
            mvprintw( y + h2 + UserY, x + w2 + UserX, d.as_ptr() );
            w2 -= 1;
        }
        mvprintw( y + h2 + UserY, x + UserX, other_d.as_ptr() );
        h2 -= 1;
    }
}

static mut UserX : i32 = 0;
static mut UserY : i32 = 0;

fn main() {
    let mut x = 0;
    let mut y = 0;
    unsafe {
        initscr();
        cbreak();
        noecho();

        let mut c = getch();
        let mut shapes : Vec<DrawMe> = vec! [];
        let mut mode : Mode = Mode::Normal;

        // TODO need mode for entering rech, etc

        while c as u8 as char != 'q' {
            let c2 = c as u8 as char;

            match c2 {
                'r' => {
                    shapes.push( DrawMe::Rec { width: 0, height: 0, x: x - UserX, y: y - UserY } );
                },
                'j' => {
                    y+=1;
                },
                'k' => {
                    y-=1;
                },
                'l' => {
                    x+=1;
                },
                'h' => {
                    x-=1;
                },
                'J' => {
                    UserY += 1;
                },
                'K' => {
                    UserY -= 1;
                },
                'L' => {
                    UserX += 1;
                },
                'H' => {
                    UserX -= 1;
                },
                _ => (),
            }

            clear();

            for s in &shapes {
                render_shape( s );
            }

            cursor_move( y, x );
            refresh();

            c = getch();
        }

        endwin();
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) ||
    c == '.'  || c == ':'              ||
    c == '%'  || is_hex_digit(c as u8) ||
    c == '\\' || is_pn_local_esc(c)
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        let mut percent_count = 0;
        let mut pn_local_esc_count = 0;
        val.char_indices().all(|(idx, c)| {
            if percent_count > 0 {
                percent_count = percent_count - 1;
                is_hex_digit(c as u8)
            } else if c == '%' {
                percent_count = 2;
                true
            } else if pn_local_esc_count > 0 {
                pn_local_esc_count = pn_local_esc_count - 1;
                is_pn_local_esc(c)
            } else if c == '\\' {
                pn_local_esc_count = 1;
                true
            } else if idx == 0 {
                is_pn_chars_u(c) || c == ':'
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':'
            } else {
                is_pn_chars(c) || c == ':' || c == '.'
            }
        }) && percent_count == 0 && pn_local_esc_count == 0
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(pn_local("hoge:%28 piyo") , IResult::Done(" piyo", "hoge:%28") );
    assert_eq!(pn_local("hoge:%2 piyo")  , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:%__ piyo") , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:\\* piyo") , IResult::Done(" piyo", "hoge:\\*") );
    assert_eq!(pn_local("%28\\* piyo")   , IResult::Done(" piyo", "%28\\*")   );
    assert_eq!(pn_local("%28\\ piyo")    , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<commit_msg>Implment WS, ANON<commit_after>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

fn is_ws(c: char) -> bool {
    let u = c as u32;
    u == 0x20 || u == 0x9 || u == 0xD || u == 0xA
}

fn is_anon(c: char) -> bool {
    c == '[' || c == ']' || is_ws(c)
}

/* [161s] WS */
named!(ws<&str, &str>, take_while_s!(is_ws));

/* [162s] ANON */
named!(anon<&str, &str>, verify!(
    take_while_s!(is_anon),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '['
            } else if idx == len - 1 {
                c == ']'
            } else {
                is_ws(c)
            }
        })
    }
));

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) ||
    c == '.'  || c == ':'              ||
    c == '%'  || is_hex_digit(c as u8) ||
    c == '\\' || is_pn_local_esc(c)
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        let mut percent_count = 0;
        let mut pn_local_esc_count = 0;
        val.char_indices().all(|(idx, c)| {
            if percent_count > 0 {
                percent_count = percent_count - 1;
                is_hex_digit(c as u8)
            } else if c == '%' {
                percent_count = 2;
                true
            } else if pn_local_esc_count > 0 {
                pn_local_esc_count = pn_local_esc_count - 1;
                is_pn_local_esc(c)
            } else if c == '\\' {
                pn_local_esc_count = 1;
                true
            } else if idx == 0 {
                is_pn_chars_u(c) || c == ':'
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':'
            } else {
                is_pn_chars(c) || c == ':' || c == '.'
            }
        }) && percent_count == 0 && pn_local_esc_count == 0
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(ws("   a")                , IResult::Done("a", "   ")          );
    assert_eq!(anon("[ ]a")              , IResult::Done("a", "[ ]")          );
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(pn_local("hoge:%28 piyo") , IResult::Done(" piyo", "hoge:%28") );
    assert_eq!(pn_local("hoge:%2 piyo")  , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:%__ piyo") , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:\\* piyo") , IResult::Done(" piyo", "hoge:\\*") );
    assert_eq!(pn_local("%28\\* piyo")   , IResult::Done(" piyo", "%28\\*")   );
    assert_eq!(pn_local("%28\\ piyo")    , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<|endoftext|>


<commit_before>// Generate an identity like so:
//
// ```bash
// openssl req -x509 -newkey rsa:4096 -nodes -keyout localhost.key -out localhost.crt -days 3650
// openssl pkcs12 -export -out identity.p12 -inkey localhost.key -in localhost.crt --password mypass
//
// ```

extern crate iron;
extern crate hyper_native_tls;

fn main() {
    // Avoid unused errors due to conditional compilation ('native-tls-example' feature is not default)
    use hyper_native_tls::NativeTlsServer;
    use iron::{Iron, Request, Response};
    use iron::status;
    use std::result::Result;

    let ssl = NativeTlsServer::new("identity.p12", "mypass").unwrap();

    match Iron::new(|_: &mut Request| {
        println!("Got an incoming connection!");
        Ok(Response::with((status::Ok, "Hello world!")))
    }).https("127.0.0.1:3000", ssl) {
        Result::Ok(listening) => println!("{:?}", listening),
        Result::Err(err) => panic!("{:?}", err),
    }
    // curl -vvvv https://127.0.0.1:3000/ -k
}<commit_msg>Send as HTML<commit_after>extern crate iron;
extern crate hyper_native_tls;

use iron::mime::{Mime, TopLevel, SubLevel};
use iron::headers::ContentType;

fn main() {
    // Avoid unused errors due to conditional compilation ('native-tls-example' feature is not default)
    use hyper_native_tls::NativeTlsServer;
    use iron::{Iron, Request, Response};
    use iron::status;
    use std::result::Result;

    let ssl = NativeTlsServer::new("identity.p12", "mypass").unwrap();

    match Iron::new(|_: &mut Request| {
        println!("Got an incoming connection!");
        let mut response = Response::with((status::Ok, "
Hello world!
"));
        response.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
        Ok(response)
    }).https("127.0.0.1:3000", ssl) {
        Result::Ok(listening) => println!("{:?}", listening),
        Result::Err(err) => panic!("{:?}", err),
    }
    // curl -vvvv https://127.0.0.1:3000/ -k
}<|endoftext|>