<commit_before>//
//    Copyright (C) 2015  Rory McCann
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks<'a>(&'a mut self, weeks: T) -> &'a mut Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days<'a>(&'a mut self, days: T) -> &'a mut Duration<T> {
        self.days = days;
        self
    }
    fn set_hours<'a>(&'a mut self, hours: T) -> &'a mut Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes<'a>(&'a mut self, minutes: T) -> &'a mut Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds<'a>(&'a mut self, seconds: T) -> &'a mut Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing {
                try!(write!(f, "{:02}m", self.minutes));
            } else {
                try!(write!(f, "{}m", self.minutes));
            }
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing {
                try!(write!(f, "{:02}s", self.seconds));
            } else {
                try!(write!(f, "{}s", self.seconds));
            }
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration{ weeks: weeks, days: days, hours: hours, minutes: minutes, seconds: seconds }
}

// Converts a textual input to
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        Ok(min*60 + sec)
    } else {
        Err("Invalid input".to_string())
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m00s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m03s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr00m00s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy0hr00m00s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk0dy0hr00m00s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input".to_string()));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
}
<commit_msg>subseconds<commit_after>//
//    Copyright (C) 2015  Rory McCann
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks<'a>(&'a mut self, weeks: T) -> &'a mut Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days<'a>(&'a mut self, days: T) -> &'a mut Duration<T> {
        self.days = days;
        self
    }
    fn set_hours<'a>(&'a mut self, hours: T) -> &'a mut Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes<'a>(&'a mut self, minutes: T) -> &'a mut Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds<'a>(&'a mut self, seconds: T) -> &'a mut Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing {
                try!(write!(f, "{:02}m", self.minutes));
            } else {
                try!(write!(f, "{}m", self.minutes));
            }
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing {
                try!(write!(f, "{:02}s", self.seconds));
            } else {
                try!(write!(f, "{}s", self.seconds));
            }
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration{ weeks: weeks, days: days, hours: hours, minutes: minutes, seconds: seconds }
}

// Converts a textual input to
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        // Just numbers, interpret as seconds
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        // XmYs
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+):(?P<sec>[0-9][0-9])\s*$").unwrap().captures(&input) {
        // 0:00
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ms|msec|milliseconds?)\s*$").unwrap().captures(&input) {
        // Milliseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid milliseconds")));
        let sec = ms / 1_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(μs|μsec|microsec|microseconds?)\s*$").unwrap().captures(&input) {
        // Microseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ns|nsec|nanosec|nanoseconds?)\s*$").unwrap().captures(&input) {
        // Nanoseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000_000;
        Ok(sec)
    } else {
        Err("Invalid input".to_string())
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m00s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m03s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr00m00s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy0hr00m00s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk0dy0hr00m00s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input".to_string()));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
    assert_eq!(input2sec("2:20".to_string()), Ok(140));
    assert_eq!(input2sec("02:20".to_string()), Ok(140));
    assert_eq!(input2sec("100:00".to_string()), Ok(6000));

    // milliseconds
    assert_eq!(input2sec("2000ms".to_string()), Ok(2));
    assert_eq!(input2sec("2ms".to_string()), Ok(0));
    assert_eq!(input2sec("2000 milliseconds".to_string()), Ok(2));
    assert_eq!(input2sec("1500ms".to_string()), Ok(1));
    assert_eq!(input2sec("1100ms".to_string()), Ok(1));
    assert_eq!(input2sec("1999ms".to_string()), Ok(1));

    // microseconds
    assert_eq!(input2sec("2000000microsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000μsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000 μs".to_string()), Ok(2));

    // nanoseconds
    assert_eq!(input2sec("2000000000ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nanosec".to_string()), Ok(2));
}

<|endoftext|>


<commit_before>extern crate cli;
extern crate getopts;
extern crate hyper;

use std::os;
use std::io::fs;

fn main() {
    let opts = &[
        cli::helpopt(),
        cli::versionopt(),
        getopts::optflag("l", "list", "List installed fonts"),
        getopts::optopt("s", "search", "Search font", "FONTNAME"),
        getopts::optmulti("i", "install", "Install font(s)", "FONTNAME"),
        getopts::optmulti("d", "delete", "Delete font(s)", "FONTNAME"),
    ];

    let matches = cli::parse_args(opts);
    if matches.opt_present("help") {
        println!("{}", cli::usage_string(opts));
        return;
    }
    if matches.opt_present("version") {
        println!("{}", cli::version_string("0.0.1"));
        return;
    }
    if matches.opt_present("list") {
        list_installed_fonts();
    }
    if matches.opt_present("search") {
        search_font(&*matches.opt_str("search").unwrap());
    }
    if matches.opt_present("install") {
        install_font(&*matches.opt_str("install").unwrap());
    }
    if matches.opt_present("delete") {
        delete_font(&*matches.opt_str("delete").unwrap());
    }
}

fn get_font_dir() -> Path {
    match os::consts::SYSNAME {
        "linux" => {
            match os::homedir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "macos" => {
            match os::homedir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        _ => unreachable!(),
    }
}

fn get_font_path(name: &str) -> Path {
    get_font_dir().join(name)
}

fn list_installed_fonts() {
    let font_dir : Path = get_font_dir();
    let font_paths : Vec<Path> = fs::readdir(&font_dir).unwrap();
    for font in font_paths.iter() {
        println!("{}", font.filename_str().unwrap());
    }
}

fn search_font(name: &str) {
    let mut client = hyper::Client::new();
    let resp = client
        .get(&*format!("http://api.github.com/search/repositories?q={}+in:name&sort=stars&order=desc", name))
        .send().unwrap();
    println!("body={}", resp.status);
}

fn install_font(name: &str) {
    let font_path = get_font_path(name);
    fs::copy(&Path::new("foo.txt"), &font_path).unwrap();
}

fn delete_font(name: &str) {
    let font_path = get_font_path(name);
    fs::unlink(&font_path).unwrap();
}

<commit_msg>Add source option<commit_after>extern crate cli;
extern crate getopts;
extern crate hyper;

use std::os;
use std::io::fs;

fn main() {
    let opts = &[
        cli::helpopt(),
        cli::versionopt(),
        getopts::optflag("l", "list", "List installed fonts"),
        getopts::optopt("s", "search", "Search font", "FONTNAME"),
        getopts::optmulti("i", "install", "Install font(s) require a --source", "FONTNAME"),
        getopts::optmulti("d", "delete", "Delete font(s)", "FONTNAME"),
        getopts::optmulti("s", "source", "Source file to use", "FILENAME"),
    ];

    let matches = cli::parse_args(opts);
    if matches.opt_present("help") {
        println!("{}", cli::usage_string(opts));
        return;
    }
    if matches.opt_present("version") {
        println!("{}", cli::version_string("0.0.1"));
        return;
    }
    if matches.opt_present("list") {
        list_installed_fonts();
    }
    if matches.opt_present("search") {
        search_font(&*matches.opt_str("search").unwrap());
    }
    if matches.opt_present("install") {
        if matches.opt_present("source") {
            install_font(&*matches.opt_str("source").unwrap(), &*matches.opt_str("install").unwrap());
        } else {
            println!("{}", cli::usage_string(opts));
        }
    }
    if matches.opt_present("delete") {
        delete_font(&*matches.opt_str("delete").unwrap());
    }
}

fn get_font_dir() -> Path {
    match os::consts::SYSNAME {
        "linux" => {
            match os::homedir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "macos" => {
            match os::homedir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        _ => unreachable!(),
    }
}

fn get_font_path(name: &str) -> Path {
    get_font_dir().join(name)
}

fn list_installed_fonts() {
    let font_dir : Path = get_font_dir();
    let font_paths : Vec<Path> = fs::readdir(&font_dir).unwrap();
    for font in font_paths.iter() {
        println!("{}", font.filename_str().unwrap());
    }
}

fn search_font(name: &str) {
    let mut client = hyper::Client::new();
    let resp = client
        .get(&*format!("http://api.github.com/search/repositories?q={}+in:name&sort=stars&order=desc", name))
        .send().unwrap();
    println!("body={}", resp.status);
}

fn install_font(source: &str, name: &str) {
    let font_path = get_font_path(name);
    fs::copy(&Path::new(source), &font_path).unwrap();
}

fn delete_font(name: &str) {
    let font_path = get_font_path(name);
    fs::unlink(&font_path).unwrap();
}

<|endoftext|>


<commit_before>extern crate toml;
extern crate graphviz;

use graphviz as dot;
use std::collections::HashMap;
use std::io::{File};
use std::str;

fn main() {
    let (name, direct_deps) = read_cargo_toml("Cargo.toml");
    let mut nodes    = vec!(name).append(direct_deps.as_slice());
    let mut edges    = range(1, nodes.len()).map(|n| (0, n)).collect();
    let indirect_deps = read_cargo_lock("Cargo.lock");

    add_deps(&mut nodes, &mut edges, indirect_deps);

    let graph = Graph { nodes: nodes, edges: edges };
    let mut f    = File::create(&Path::new("Cargo.dot"));

    graph.render_to(&mut f);
}

fn read_cargo_toml(toml_file_name: &str) -> (String, Vec<String>) {
    let toml_str = File::open(&Path::new(toml_file_name)).read_to_string().unwrap();
    let toml     = toml::Parser::new(toml_str.as_slice()).parse().unwrap();
    let name     =
        toml.find(&"package".to_string()).unwrap().as_table().unwrap().find(&"name".to_string()).unwrap();
    (name.as_str().unwrap().to_string(), vec!("toml".to_string()))
}

fn read_cargo_lock(_lock_file_name: &str) -> (Vec<(&str, Vec<&str>)>) {
    vec!(("toml", vec!("boodl")))
}

fn add_deps(nodes: &mut Vec<String>, edges: &mut Vec<(uint, uint)>, deps: Vec<(&str, Vec<&str>)>) {
    for (crat, crate_deps) in deps.move_iter() {
        let idl = add_or_find(nodes, crat);
        for dep in crate_deps.move_iter() {
            let idr = add_or_find(nodes, dep);
            edges.push((idl, idr));
        }
    }
}

fn add_or_find<'a>(nodes: &mut Vec<String>, new: &'a str) -> uint {
    for i in range(0, nodes.len()) {
        let s = nodes.get(i);
        if s.as_slice() == new {
            return i
        }
    }
    nodes.push(new.to_string());
    nodes.len() - 1
}

type Nd = uint;
type Ed<'a> = &'a (uint, uint);
struct Graph { nodes: Vec<String>,
               edges: Vec<(uint,uint)>,
             }

impl Graph {
    fn render_to<W:Writer>(self, output: &mut W) {
        dot::render(&self, output).unwrap()
    }
}

impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3") }
    fn node_id(&'a self, n: &Nd) -> dot::Id {
        dot::Id::new(format!("N{:u}", *n))
    }
    fn node_label<'a>(&'a self, i: &Nd) -> dot::LabelText<'a> {
        dot::LabelStr(str::Slice(self.nodes[*i].as_slice()))
    }
}

impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph {
    fn nodes(&'a self) -> dot::Nodes<'a,Nd> {
        range(0, self.nodes.len()).collect()
    }
    fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> {
        self.edges.iter().collect()
    }
    fn source(&self, e: &Ed) -> Nd { let &(s,_) = *e; s }
    fn target(&self, e: &Ed) -> Nd { let &(_,t) = *e; t }
}
<commit_msg>Read direct dependencies and clean up<commit_after>extern crate toml;
extern crate graphviz;

use graphviz as dot;
use std::io::File;
use std::str;

fn main() {
    let (name, indirect_deps) = read_cargo_lock("Cargo.lock");
    let direct_deps           = read_cargo_toml("Cargo.toml");
    let mut nodes    = vec!(name).append(direct_deps.as_slice());
    let mut edges    = range(1, nodes.len()).map(|n| (0, n)).collect();

    add_deps(&mut nodes, &mut edges, indirect_deps);

    let graph = Graph { nodes: nodes, edges: edges };
    let mut f    = File::create(&Path::new("Cargo.dot"));

    graph.render_to(&mut f);
}

fn read_cargo_toml(toml_file_name: &str) -> (Vec<String>) {
    let toml_str = File::open(&Path::new(toml_file_name)).read_to_string().unwrap();
    let toml     = toml::Parser::new(toml_str.as_slice()).parse().unwrap();
    let deps: Vec<String> =
        toml.find(&"dependencies".to_string()).unwrap().as_table().unwrap().keys().map(|s| s.to_string()).collect();
    deps
}

fn read_cargo_lock(_lock_file_name: &str) -> (String, Vec<(&str, Vec<&str>)>) {
    ("cargo".to_string(), vec!())
}

fn add_deps(nodes: &mut Vec<String>, edges: &mut Vec<(uint, uint)>, deps: Vec<(&str, Vec<&str>)>) {
    for (crat, crate_deps) in deps.move_iter() {
        let idl = add_or_find(nodes, crat);
        for dep in crate_deps.move_iter() {
            let idr = add_or_find(nodes, dep);
            edges.push((idl, idr));
        }
    }
}

fn add_or_find<'a>(nodes: &mut Vec<String>, new: &'a str) -> uint {
    for i in range(0, nodes.len()) {
        let ref s = (*nodes)[i];
        if s.as_slice() == new {
            return i
        }
    }
    nodes.push(new.to_string());
    nodes.len() - 1
}

type Nd = uint;
type Ed<'a> = &'a (uint, uint);
struct Graph { nodes: Vec<String>,
               edges: Vec<(uint,uint)>,
             }

impl Graph {
    fn render_to<W:Writer>(self, output: &mut W) {
        dot::render(&self, output).unwrap()
    }
}

impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3") }
    fn node_id(&'a self, n: &Nd) -> dot::Id {
        dot::Id::new(format!("N{:u}", *n))
    }
    fn node_label<'a>(&'a self, i: &Nd) -> dot::LabelText<'a> {
        dot::LabelStr(str::Slice(self.nodes[*i].as_slice()))
    }
}

impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph {
    fn nodes(&'a self) -> dot::Nodes<'a,Nd> {
        range(0, self.nodes.len()).collect()
    }
    fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> {
        self.edges.iter().collect()
    }
    fn source(&self, e: &Ed) -> Nd { let &(s,_) = *e; s }
    fn target(&self, e: &Ed) -> Nd { let &(_,t) = *e; t }
}
<|endoftext|>


<commit_before>extern crate zas;

use zas::config::Config;

#[cfg(not(test))]
fn main() {
    let config = Config::new();

    let dns_server = zas::dns::server::Server::create(&config);
    let http_server = zas::http::server::Server::create(&config);

    dns_server.thread.join().unwrap();
    http_server.thread.join().unwrap();
}
<commit_msg>refactor: Remove unnused warning<commit_after>extern crate zas;

#[cfg(not(test))]
use zas::config::Config;

#[cfg(not(test))]
fn main() {
    let config = Config::new();

    let dns_server = zas::dns::server::Server::create(&config);
    let http_server = zas::http::server::Server::create(&config);

    dns_server.thread.join().unwrap();
    http_server.thread.join().unwrap();
}
<|endoftext|>


<commit_before>extern crate tempfile;
extern crate rustyline;

mod lexer;
mod parser;
mod evaluator;
mod error;
mod constants;
mod function;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use tempfile::NamedTempFile;
use constants::VERSION;
use lexer::lexer;
use parser::Parser;
use evaluator::Evaluator;
use error::{ParserError, EvaluatorError};

fn prelude() {
    println!("bspl {}", VERSION);
    println!("Bit-Shift-Print Loop");
    println!("Type 'help', 'license', or 'version' for more information.");
}

fn error_message(width: usize, msg: &'static str) {
    println!("{caret:>width$}\n.. {}", msg, caret = "^", width = width);
}

fn display_results(results: Vec<String>) {
    let mut result_iter = results.iter();
    while let Some(result) = result_iter.next() {
        println!(".. {}", result);
    }

    if let Some(final_result) = results.last() {
        let parsed_final_result = final_result.parse::<i32>();
        if parsed_final_result.is_ok() {
            let parsed_final_result = parsed_final_result.unwrap();
            println!(".. Dec: {}", parsed_final_result);
            println!(".. Hex: 0x{:x}", parsed_final_result);
            println!(".. Bin: 0b{:b}", parsed_final_result);
        }
    }
}

fn repl() {
    let mut repl = Editor::<()>::new();
    let prompt = "=> ";
    let tmp_file = NamedTempFile::new().unwrap();
    let _ = repl.load_history(tmp_file.path());

    let mut parser = Parser::default();
    let evaluator = Evaluator::default();

    loop {
        match repl.readline(prompt) {
            Ok(line) => {
                repl.add_history_entry(&line);
                match parser.parse(lexer(&line)) {
                    Ok(parsed_tokens) => {
                        match evaluator.evaluate(parsed_tokens) {
                            Ok(result) => {
                                display_results(result);
                            }
                            Err(EvaluatorError::MissingArgument(position)) => {
                                error_message(position + prompt.len() + 1, "Missing Argument");
                            }
                            Err(EvaluatorError::TooManyArguments) => {
                                error_message(prompt.len() + 1, "Too Many Arguments");
                            }
                            Err(EvaluatorError::NegativeShift(position)) => {
                                error_message(position + prompt.len() + 1, "Negative Shift");
                            }
                            Err(EvaluatorError::OverflowShift(position)) => {
                                error_message(position + prompt.len() + 1, "Overflow Shift");
                            }
                            Err(EvaluatorError::KeywordError(position)) => {
                                error_message(position + prompt.len() + 1, "Cannot use Keyword");
                            }
                            Err(EvaluatorError::UnknownKeyword(position)) => {
                                error_message(position + prompt.len() + 1, "Unknown Keyword");
                            }
                            Err(EvaluatorError::Exit) => break,
                        }
                    }
                    Err(ParserError::RadixError(position)) => {
                        error_message(position + prompt.len() + 1, "Radix Error");
                    }
                    Err(ParserError::UnknownOperator(position)) => {
                        error_message(position + prompt.len() + 1, "Unknown Operator");
                    }
                    Err(ParserError::MissingOpeningBracket(position)) => {
                        error_message(position + prompt.len() + 1, "Missing Opening Bracket");
                    }
                    Err(ParserError::MissingClosingBracket(position)) => {
                        error_message(position + prompt.len() + 1, "Missing Closing Bracket");
                    }
                    Err(ParserError::InvalidSyntax(position)) => {
                        error_message(position + prompt.len() + 1, "Invalid Syntax");
                    }
                }
            }
            Err(ReadlineError::Eof) => break,
            Err(ReadlineError::Interrupted) => {
                println!("Type 'exit' or press Ctrl-D to leave bspl");
                continue;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }

        }
        repl.save_history(tmp_file.path()).unwrap();
    }
}

pub fn main() {
    prelude();
    repl();
}
<commit_msg>Add prompt_len constant to measure repl output<commit_after>extern crate tempfile;
extern crate rustyline;

mod lexer;
mod parser;
mod evaluator;
mod error;
mod constants;
mod function;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use tempfile::NamedTempFile;
use constants::VERSION;
use lexer::lexer;
use parser::Parser;
use evaluator::Evaluator;
use error::{ParserError, EvaluatorError};

fn prelude() {
    println!("bspl {}", VERSION);
    println!("Bit-Shift-Print Loop");
    println!("Type 'help', 'license', or 'version' for more information.");
}

fn error_message(width: usize, msg: &'static str) {
    println!("{caret:>width$}\n.. {}", msg, caret = "^", width = width);
}

fn display_results(results: Vec<String>) {
    let mut result_iter = results.iter();
    while let Some(result) = result_iter.next() {
        println!(".. {}", result);
    }

    if let Some(final_result) = results.last() {
        let parsed_final_result = final_result.parse::<i32>();
        if parsed_final_result.is_ok() {
            let parsed_final_result = parsed_final_result.unwrap();
            println!(".. Dec: {}", parsed_final_result);
            println!(".. Hex: 0x{:x}", parsed_final_result);
            println!(".. Bin: 0b{:b}", parsed_final_result);
        }
    }
}

fn repl() {
    let mut repl = Editor::<()>::new();
    let prompt = "=> ";
    let prompt_len = prompt.len() + 1;
    let tmp_file = NamedTempFile::new().unwrap();
    let _ = repl.load_history(tmp_file.path());

    let mut parser = Parser::default();
    let evaluator = Evaluator::default();

    loop {
        match repl.readline(prompt) {
            Ok(line) => {
                repl.add_history_entry(&line);
                match parser.parse(lexer(&line)) {
                    Ok(parsed_tokens) => {
                        match evaluator.evaluate(parsed_tokens) {
                            Ok(result) => {
                                display_results(result);
                            }
                            Err(EvaluatorError::MissingArgument(position)) => {
                                error_message(position + prompt_len, "Missing Argument");
                            }
                            Err(EvaluatorError::TooManyArguments) => {
                                error_message(prompt_len, "Too Many Arguments");
                            }
                            Err(EvaluatorError::NegativeShift(position)) => {
                                error_message(position + prompt_len, "Negative Shift");
                            }
                            Err(EvaluatorError::OverflowShift(position)) => {
                                error_message(position + prompt_len, "Overflow Shift");
                            }
                            Err(EvaluatorError::KeywordError(position)) => {
                                error_message(position + prompt_len, "Cannot use Keyword");
                            }
                            Err(EvaluatorError::UnknownKeyword(position)) => {
                                error_message(position + prompt_len, "Unknown Keyword");
                            }
                            Err(EvaluatorError::Exit) => break,
                        }
                    }
                    Err(ParserError::RadixError(position)) => {
                        error_message(position + prompt_len, "Radix Error");
                    }
                    Err(ParserError::UnknownOperator(position)) => {
                        error_message(position + prompt_len, "Unknown Operator");
                    }
                    Err(ParserError::MissingOpeningBracket(position)) => {
                        error_message(position + prompt_len, "Missing Opening Bracket");
                    }
                    Err(ParserError::MissingClosingBracket(position)) => {
                        error_message(position + prompt_len, "Missing Closing Bracket");
                    }
                    Err(ParserError::InvalidSyntax(position)) => {
                        error_message(position + prompt_len, "Invalid Syntax");
                    }
                }
            }
            Err(ReadlineError::Eof) => break,
            Err(ReadlineError::Interrupted) => {
                println!("Type 'exit' or press Ctrl-D to leave bspl");
                continue;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }

        }
        repl.save_history(tmp_file.path()).unwrap();
    }
}

pub fn main() {
    prelude();
    repl();
}
<|endoftext|>


<commit_before>extern crate asnom;

extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;

extern crate byteorder;

#[macro_use]
extern crate log;

mod protocol;

use protocol::LdapProto;

use std::default::Default;
use futures::Future;
use tokio_core::reactor::{Core, Handle};
use tokio_proto::TcpClient;
use tokio_proto::multiplex::Multiplex;
use tokio_service::Service;

use asnom::structures::*;
use asnom::common::TagClass::*;

pub fn main() {
    let mut core = Core::new().unwrap();

    let addr = "127.0.0.1:389".parse().unwrap();

    let handle = core.handle();

    let client = TcpClient::new(LdapProto).connect(&addr, &handle);

    let req = Tag::Sequence(Sequence {
        id: 0,
        class: Application,
        inner: vec![
               Tag::Integer(Integer {
                   inner: 3,
                   .. Default::default()
               }),
               Tag::OctetString(OctetString {
                   inner: String::from("cn=root,dc=plabs").into_bytes(),
                   .. Default::default()
               }),
               Tag::OctetString(OctetString {
                   id: 0,
                   class: Context,
                   inner: String::from("asdf").into_bytes(),
               })
        ],
    });

    let response = client.and_then(|c| c.call(req)
                    .and_then(move |response| {
                        println!("CLIENT: {:?}", response);
                        Ok(())
                    }));

    let a = core.run(
        response
    ).unwrap();
}
<commit_msg>That wasn't supposed to be there..<commit_after><|endoftext|>


<commit_before>// TODO
// impl ToGeojson for ....
// generic number instead of f64 for position?

extern crate serialize;

use std::collections::TreeMap;
use std::option::{None, Option, Some};
use serialize::json::ToJson;
use serialize::json;

/// Pos (alias for Positions)
///
/// [GeoJSON Format Specification § 2.1.1](http://geojson.org/geojson-spec.html#positions)
pub struct Pos(pub Vec<f64>);

impl ToJson for Pos {
    fn to_json(&self) -> json::Json {
        let &Pos(ref nums) = self;
        nums.to_json()
    }
}

impl Clone for Pos {
    fn clone(&self) -> Pos {
        let &Pos(ref nums) = self;
        Pos(nums.clone())
    }
}

/// Point
///
/// [GeoJSON Format Specification § 2.1.2](http://geojson.org/geojson-spec.html#point)
pub struct Point {
    pub coordinates: Pos,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiPoint
///
/// [GeoJSON Format Specification § 2.1.3](http://geojson.org/geojson-spec.html#multipoint)
pub struct MultiPoint {
    pub points: Vec<Point>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Pos> =
            self.points.iter().map(|p| p.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// LineString
///
/// [GeoJSON Format Specification § 2.1.4](http://geojson.org/geojson-spec.html#linestring)
pub struct LineString {
    pub coordinates: Vec<Pos>,
}

impl ToJson for LineString {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "LineString".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiLineString
///
/// [GeoJSON Format Specification § 2.1.5](http://geojson.org/geojson-spec.html#multilinestring)
pub struct MultiLineString {
    pub line_strings: Vec<LineString>,
}

impl ToJson for MultiLineString {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Pos>> =
            self.line_strings.iter().map(|l| l.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiLineString".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Polygon
///
/// [GeoJSON Format Specification § 2.1.6](http://geojson.org/geojson-spec.html#polygon)
pub struct Polygon {
    pub exterior: Vec<Pos>,
    pub holes: Option<Vec<Vec<Pos>>>,
}

impl Polygon {
    fn coordinates(&self) -> Vec<Vec<Pos>> {
        match self.holes {
            None => vec![self.exterior.clone()],
            Some(ref holes) => {
                let mut coordinates = holes.clone();
                coordinates.insert(0, self.exterior.clone());
                coordinates
            }
        }
    }
}

impl ToJson for Polygon {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Polygon".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates().to_json());
        d.to_json()
    }
}

/// MultiPolygon
///
/// [GeoJSON Format Specification § 2.1.7](http://geojson.org/geojson-spec.html#multipolygon)
pub struct MultiPolygon {
    pub polygons: Vec<Polygon>,
}

impl ToJson for MultiPolygon {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Vec<Pos>>> =
            self.polygons.iter().map(|p| p.coordinates()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPolygon".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Geometry
pub enum Geometry {
    Point(Point),
    MultiPoint(MultiPoint),
    LineString(LineString),
    MultiLineString(MultiLineString),
    Polygon(Polygon),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl ToJson for Geometry {
    fn to_json(&self) -> json::Json {
        match *self {
            Geometry::Point(ref geom) => geom.to_json(),
            Geometry::MultiPoint(ref geom) => geom.to_json(),
            Geometry::LineString(ref geom) => geom.to_json(),
            Geometry::MultiLineString(ref geom) => geom.to_json(),
            Geometry::Polygon(ref geom) => geom.to_json(),
            Geometry::MultiPolygon(ref geom) => geom.to_json(),
            Geometry::GeometryCollection(ref geom) => geom.to_json(),
        }
    }
}

/// GeometryCollection
///
/// [GeoJSON Format Specification § 2.1.8](http://geojson.org/geojson-spec.html#geometry-collection)
pub struct GeometryCollection {
    geometries: Vec<Geometry>,
}

impl ToJson for GeometryCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "GeometryCollection".to_string().to_json());
        d.insert("geometries".to_string(), self.geometries.to_json());
        d.to_json()
    }
}

/// Feature
///
/// [GeoJSON Format Specification § 2.2](http://geojson.org/geojson-spec.html#feature-objects)
pub struct Feature {
    geometry: Geometry,
    properties: json::Json,
}

impl ToJson for Feature {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Feature".to_string().to_json());
        d.insert("geometry".to_string(), self.geometry.to_json());
        d.insert("properties".to_string(), self.properties.to_json());
        d.to_json()
    }
}

/// FeatureCollection
///
/// [GeoJSON Format Specification § 2.3](http://geojson.org/geojson-spec.html#feature-collection-objects)
pub struct FeatureCollection {
    features: Vec<Feature>,
}

impl ToJson for FeatureCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "FeatureCollection".to_string().to_json());
        d.insert("features".to_string(), self.features.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {coordinates: Pos(vec![1., 2., 3.])};

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<commit_msg>Remove unneeded imports<commit_after>// TODO
// impl ToGeojson for ....
// generic number instead of f64 for position?

extern crate serialize;

use std::collections::TreeMap;
use serialize::json::ToJson;
use serialize::json;

/// Pos (alias for Positions)
///
/// [GeoJSON Format Specification § 2.1.1](http://geojson.org/geojson-spec.html#positions)
pub struct Pos(pub Vec<f64>);

impl ToJson for Pos {
    fn to_json(&self) -> json::Json {
        let &Pos(ref nums) = self;
        nums.to_json()
    }
}

impl Clone for Pos {
    fn clone(&self) -> Pos {
        let &Pos(ref nums) = self;
        Pos(nums.clone())
    }
}

/// Point
///
/// [GeoJSON Format Specification § 2.1.2](http://geojson.org/geojson-spec.html#point)
pub struct Point {
    pub coordinates: Pos,
}

impl ToJson for Point {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Point".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiPoint
///
/// [GeoJSON Format Specification § 2.1.3](http://geojson.org/geojson-spec.html#multipoint)
pub struct MultiPoint {
    pub points: Vec<Point>,
}

impl ToJson for MultiPoint {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Pos> =
            self.points.iter().map(|p| p.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPoint".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// LineString
///
/// [GeoJSON Format Specification § 2.1.4](http://geojson.org/geojson-spec.html#linestring)
pub struct LineString {
    pub coordinates: Vec<Pos>,
}

impl ToJson for LineString {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "LineString".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates.to_json());
        d.to_json()
    }
}

/// MultiLineString
///
/// [GeoJSON Format Specification § 2.1.5](http://geojson.org/geojson-spec.html#multilinestring)
pub struct MultiLineString {
    pub line_strings: Vec<LineString>,
}

impl ToJson for MultiLineString {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Pos>> =
            self.line_strings.iter().map(|l| l.coordinates.clone()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiLineString".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Polygon
///
/// [GeoJSON Format Specification § 2.1.6](http://geojson.org/geojson-spec.html#polygon)
pub struct Polygon {
    pub exterior: Vec<Pos>,
    pub holes: Option<Vec<Vec<Pos>>>,
}

impl Polygon {
    fn coordinates(&self) -> Vec<Vec<Pos>> {
        match self.holes {
            None => vec![self.exterior.clone()],
            Some(ref holes) => {
                let mut coordinates = holes.clone();
                coordinates.insert(0, self.exterior.clone());
                coordinates
            }
        }
    }
}

impl ToJson for Polygon {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Polygon".to_string().to_json());
        d.insert("coordinates".to_string(), self.coordinates().to_json());
        d.to_json()
    }
}

/// MultiPolygon
///
/// [GeoJSON Format Specification § 2.1.7](http://geojson.org/geojson-spec.html#multipolygon)
pub struct MultiPolygon {
    pub polygons: Vec<Polygon>,
}

impl ToJson for MultiPolygon {
    fn to_json(&self) -> json::Json {
        let coordinates: Vec<Vec<Vec<Pos>>> =
            self.polygons.iter().map(|p| p.coordinates()).collect();
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "MultiPolygon".to_string().to_json());
        d.insert("coordinates".to_string(), coordinates.to_json());
        d.to_json()
    }
}

/// Geometry
pub enum Geometry {
    Point(Point),
    MultiPoint(MultiPoint),
    LineString(LineString),
    MultiLineString(MultiLineString),
    Polygon(Polygon),
    MultiPolygon(MultiPolygon),
    GeometryCollection(GeometryCollection),
}

impl ToJson for Geometry {
    fn to_json(&self) -> json::Json {
        match *self {
            Geometry::Point(ref geom) => geom.to_json(),
            Geometry::MultiPoint(ref geom) => geom.to_json(),
            Geometry::LineString(ref geom) => geom.to_json(),
            Geometry::MultiLineString(ref geom) => geom.to_json(),
            Geometry::Polygon(ref geom) => geom.to_json(),
            Geometry::MultiPolygon(ref geom) => geom.to_json(),
            Geometry::GeometryCollection(ref geom) => geom.to_json(),
        }
    }
}

/// GeometryCollection
///
/// [GeoJSON Format Specification § 2.1.8](http://geojson.org/geojson-spec.html#geometry-collection)
pub struct GeometryCollection {
    geometries: Vec<Geometry>,
}

impl ToJson for GeometryCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "GeometryCollection".to_string().to_json());
        d.insert("geometries".to_string(), self.geometries.to_json());
        d.to_json()
    }
}

/// Feature
///
/// [GeoJSON Format Specification § 2.2](http://geojson.org/geojson-spec.html#feature-objects)
pub struct Feature {
    geometry: Geometry,
    properties: json::Json,
}

impl ToJson for Feature {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "Feature".to_string().to_json());
        d.insert("geometry".to_string(), self.geometry.to_json());
        d.insert("properties".to_string(), self.properties.to_json());
        d.to_json()
    }
}

/// FeatureCollection
///
/// [GeoJSON Format Specification § 2.3](http://geojson.org/geojson-spec.html#feature-collection-objects)
pub struct FeatureCollection {
    features: Vec<Feature>,
}

impl ToJson for FeatureCollection {
    fn to_json(&self) -> json::Json {
        let mut d = TreeMap::new();
        d.insert("type".to_string(), "FeatureCollection".to_string().to_json());
        d.insert("features".to_string(), self.features.to_json());
        d.to_json()
    }
}

fn main() {
    let point = Point {coordinates: Pos(vec![1., 2., 3.])};

    let j: json::Json = point.to_json();
    let s: String = j.to_pretty_str();

    println!("{}", s);
}
<|endoftext|>


<commit_before>mod ast {
  use std::collections::HashMap;

  // Type
  pub enum Type {
    Assign(String, int),
    Print(String),
    Block
  }

  pub struct Node {
    t: Type,
    children: Vec<Node>
  }

  // Context
  pub struct Context {
    pub symbol_table: HashMap<String, int>
  }

  impl Context {
    pub fn new() -> Context {
      Context {
        symbol_table: HashMap::new()
      }
    }

    fn set(&mut self, s: &String, i: int) {
      self.symbol_table.insert(s.clone(), i);
    }

    fn get(&mut self, s: &String) -> int {
      match self.symbol_table.get(s) {
        Some(i) => *i,
        None => 0
      }
    }
  }

  // Constructors
  pub fn block(cs: Vec<Node>) -> Node {
    Node {
      t: Type::Block,
      children: cs
    }
  }

  pub fn assign(s: &str, i: int) -> Node {
    Node {
      t: Type::Assign(s.to_string(), i),
      children: vec!()
    }
  }

  pub fn print(s: &str) -> Node {
    Node {
      t: Type::Print(s.to_string()),
      children: vec!()
    }
  }

  // Evaluate
  pub fn eval(cxt: &mut Context, n: &Node) {
    match n.t {
      Type::Assign(ref s, i) => cxt.set(s, i),
      Type::Print(ref s) => println!("{} = {}", s, cxt.get(s)),
      Type::Block => for n in n.children.iter() { eval(cxt, n); }
    }
  }
}

fn main() {
  let program =
    ast::block(vec!(
      ast::assign("x", 5),
      ast::assign("y", 7),
      ast::print("x"),
      ast::print("y"),
      ast::assign("x", 6),
      ast::print("x")));
  ast::eval(&mut ast::Context::new(), &program);
}
<commit_msg>Refactored AST so nodes are fully contained in the enum<commit_after>mod ast {
  pub struct Program {
    pub top: Statement
  }

  pub enum Statement {
    Block(Vec<Statement>),
    Assign(String, int),
    Print(String)
  }

  // Evaluate
  pub mod eval {
    use std::collections::HashMap;
    use ast::{Program, Statement};

    struct Context {
      pub symbol_table: HashMap<String, int>
    }

    impl Context {
      pub fn new() -> Context {
        Context {
          symbol_table: HashMap::new()
        }
      }

      fn set(&mut self, s: &String, i: int) {
        self.symbol_table.insert(s.clone(), i);
      }

      fn get(&self, s: &String) -> int {
        match self.symbol_table.get(s) {
          Some(i) => *i,
          None => 0
        }
      }
    }

    pub fn eval_program(p: &Program) {
      eval_statement(&mut Context::new(), &p.top)
    }

    pub fn eval_statement(cxt: &mut Context, s: &Statement) {
      match *s {
        Statement::Block(ref c) => {
          for s in c.iter() {
            eval_statement(cxt, s);
          }
        },
        Statement::Assign(ref s, i) => cxt.set(s, i),
        Statement::Print(ref s) => println!("{} = {}", s, cxt.get(s)),
      }
    }
  }
}

fn main() {
  let program = ast::Program {
    top: ast::Statement::Block(vec!(
      ast::Statement::Assign("x".to_string(), 5),
      ast::Statement::Assign("y".to_string(), 7),
      ast::Statement::Print("x".to_string()),
      ast::Statement::Print("y".to_string()),
      ast::Statement::Assign("x".to_string(), 6),
      ast::Statement::Print("x".to_string())))
  };
  ast::eval::eval_program(&program);
}
<|endoftext|>


<commit_before>// SPDX-FileCopyrightText: 2019 Tuomas Siipola
// SPDX-License-Identifier: GPL-3.0-or-later

use sdl2::surface::Surface;

mod direction;
mod font;
mod game;
mod map;
mod menu;
mod snake;
mod state;
mod tile;

use crate::font::Font;
use crate::menu::Menu;
use crate::state::{Action, State};

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem
        .window("Natrix", 320, 240)
        .position_centered()
        .build()
        .unwrap();

    let mut canvas = window.into_canvas().build().unwrap();
    let texture_creator = canvas.texture_creator();

    let tiles = texture_creator
        .create_texture_from_surface(Surface::load_bmp("data/images/tiles.bmp").unwrap())
        .unwrap();

    let logo = texture_creator
        .create_texture_from_surface(Surface::load_bmp("data/images/logo.bmp").unwrap())
        .unwrap();

    let font = Font::load_bmp(&texture_creator, "data/images/NeoSans.bmp");

    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut current_state: Box<State> = Box::new(Menu::new());

    loop {
        match current_state.update(event_pump.poll_iter(), &mut canvas, &font, &tiles, &logo) {
            Action::Quit => break,
            Action::Change(next_state) => current_state = next_state,
            Action::None => {}
        }
    }
}
<commit_msg>Force software rendering<commit_after>// SPDX-FileCopyrightText: 2019 Tuomas Siipola
// SPDX-License-Identifier: GPL-3.0-or-later

use sdl2::surface::Surface;

mod direction;
mod font;
mod game;
mod map;
mod menu;
mod snake;
mod state;
mod tile;

use crate::font::Font;
use crate::menu::Menu;
use crate::state::{Action, State};

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem
        .window("Natrix", 320, 240)
        .position_centered()
        .build()
        .unwrap();

    let mut canvas = window.into_canvas().software().build().unwrap();
    let texture_creator = canvas.texture_creator();

    let tiles = texture_creator
        .create_texture_from_surface(Surface::load_bmp("data/images/tiles.bmp").unwrap())
        .unwrap();

    let logo = texture_creator
        .create_texture_from_surface(Surface::load_bmp("data/images/logo.bmp").unwrap())
        .unwrap();

    let font = Font::load_bmp(&texture_creator, "data/images/NeoSans.bmp");

    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut current_state: Box<State> = Box::new(Menu::new());

    loop {
        match current_state.update(event_pump.poll_iter(), &mut canvas, &font, &tiles, &logo) {
            Action::Quit => break,
            Action::Change(next_state) => current_state = next_state,
            Action::None => {}
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate iron;
// extern crate mount;
// extern crate router;
// extern crate staticfile;

use std::env;
use std::fs::File;
use std::path::PathBuf;
use std::error::Error;
use std::fmt::{self, Debug};

use iron::{Iron, IronResult, IronError, Request, Response, status};

#[derive(Debug)]
struct StringError(String);

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for StringError {
    fn description(&self) -> &str { &*self.0 }
}

fn main() {
    env_logger::init().unwrap();

    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let port = matches
        .value_of("port")
        .unwrap_or("8000")
        .parse::<u16>()
        .unwrap();
    println!("current dir: {:?}", env::current_dir());

    let addr = format!("0.0.0.0:{}", port);
    println!("Server running on http://{:?}", addr);
    Iron::new(move |req: &mut Request| {
        println!("Url: {:?}", req.url.path());
        let mut path = root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        match File::open(path) {
            Ok(f) => {
                let metadata = f.metadata().unwrap();
                let content = if metadata.is_dir() { "Is directory" } else { "Is normal file" };
                Ok(Response::with((status::Ok, content)))
            },
            Err(e) => {
                Ok(Response::with((status::NotFound, e.description().to_string())))
            }
        }
    }).http(addr).unwrap();
}
<commit_msg>Basic useable<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
extern crate iron;

use std::env;
use std::fs::{self, File};
use std::path::{PathBuf};
use std::error::Error;
use std::os::unix::ffi::OsStrExt;

use iron::headers;
use iron::{Iron, Request, Response, Set, status};

fn main() {
    env_logger::init().unwrap();

    let default_port = "8000";
    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .default_value(default_port)
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let port = matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .unwrap();

    println!("current dir: {:?}", env::current_dir());
    let addr = format!("0.0.0.0:{}", port);
    println!("Server running on http://{:?}", addr);

    Iron::new(move |req: &mut Request| {
        println!("Url: {:?}", req.url.path());
        let mut path = root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        match File::open(&path) {
            Ok(f) => {
                let mut resp = Response::with(status::Ok);
                let metadata = f.metadata().unwrap();
                if metadata.is_dir() {
                    resp.headers.set(headers::ContentType::html());
                    let mut files = Vec::new();
                    for entry in fs::read_dir(&path).unwrap() {
                        let entry = entry.unwrap();
                        let file_name = entry.file_name().into_string().unwrap();
                        let link = req.url.path().join("/");
                        files.push(format!(
                            "
{}
",
                            link, file_name, file_name
                        ));
                    }
                    resp = resp.set(format!("{}", files.join("\n")));
                } else {
                    resp.headers.set(headers::ContentDisposition {
                        disposition: headers::DispositionType::Attachment,
                        parameters: vec![headers::DispositionParam::Filename(
                            headers::Charset::Ext("utf-8".to_owned()), // The character set for the bytes of the filename
                            None, // The optional language tag (see `language-tag` crate)
                            path.file_name().unwrap().as_bytes().to_vec() // the actual bytes of the filename
                        )]
                    });
                    resp = resp.set(path);
                    let mime: iron::mime::Mime = "application/octet-stream".parse().unwrap();
                    resp.headers.set(headers::ContentType(mime));
                };
                Ok(resp)
            },
            Err(e) => {
                Ok(Response::with((status::NotFound, e.description().to_string())))
            }
        }
    }).http(addr).unwrap();
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

extern crate rand;
extern crate serde;
extern crate serde_yaml;

use std::fs::File;
use std::io::Read;
use std::io;
use std::env;

#[derive(Default, Serialize, Deserialize)]
struct CPU {
    v: [u8; 16],
    i: u16,
    dt: u8,
    st: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
}

// #[derive(Default)]
struct Computer {
    ram: [u8; 4096],
    cpu: CPU,
}

impl Default for Computer {
     fn default() -> Computer {
         Computer {
             ram: [0u8; 4096],
             cpu: Default::default(),
         }
     }
}

fn combine(arr: &[u8]) -> u16 {
    let mut val: u16 = 0;
    for v in arr {
        val <<= 4;
        val += *v as u16;
    }
    val
}

impl Computer {
    fn ld_i_addr(&mut self, inst: &[u8; 4]) {
        let addr = combine(&inst[1..]);
        self.cpu.i = addr;
    }

    fn rnd_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let random_byte = rand::random::<u8>();
        let byte: u8 = kk & random_byte;
        self.cpu.v[inst[1] as usize] = byte;
    }

    fn se_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let vx = self.cpu.v[inst[1] as usize];
        if kk == vx {
            self.cpu.pc += 2;
        }
    }
}

// cargo run -- ./games/TANK

fn main() {
    let mut computer: Computer = Default::default();
    computer.cpu.pc = 0x200;
    let mut f = File::open(env::args().nth(1).unwrap()).unwrap();

    {
        let end: usize = 0x200 + f.metadata().unwrap().len() as usize;
        let mut slice = &mut computer.ram[0x200..end];
        f.read_exact(slice);
    }

    loop {
        let mut should_inc = true;

        let inst: [u8; 4] = {
            let inst0 = computer.ram[computer.cpu.pc as usize];
            let inst1 = computer.ram[(computer.cpu.pc + 1) as usize];

            let tet0 = inst0 >> 4;
            let tet1 = 0x0f & inst0;
            let tet2 = inst1 >> 4;
            let tet3 = 0x0f & inst1;

            [tet0, tet1, tet2, tet3]
        };

        print!("inst ");
        for x in &inst {
            print!("{:x}", x);
        }
        println!();

        match inst[0] {
            0x3 => computer.se_vx_byte(&inst),
            0xa => computer.ld_i_addr(&inst),
            0xc => computer.rnd_vx_byte(&inst),
            _ => panic!("unimplemented instruction: {:x}", inst[0])
        }

        if should_inc {
            computer.cpu.pc += 2;
        }

        let serialized = serde_yaml::to_string(&computer.cpu).unwrap();
        println!("{}", serialized);

        // step on newline
        let mut input = String::new();
        io::stdin().read_line(&mut input);
    }
}

#[test]
fn combine_test1() {
    let inst = [0x1, 0x2, 0x3];
    let combo = combine(&inst);
    assert!(0x123 == combo);
}

#[test]
fn combine_test2() {
    let inst = [0x3];
    let combo = combine(&inst);
    assert!(0x3 == combo);
}

#[test]
fn combine_test3() {
    let inst = [0x1, 0x2, 0x3, 0x4];
    let combo = combine(&inst);
    assert!(0x1234 == combo);
}
<commit_msg>Add Debug impl for CPU<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

extern crate rand;
extern crate serde;
extern crate serde_yaml;

use std::fs::File;
use std::io::Read;
use std::io;
use std::env;
use std::fmt;

#[derive(Default, Serialize, Deserialize)]
struct CPU {
    v: [u8; 16],
    i: u16,
    dt: u8,
    st: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
}

impl fmt::Debug for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "v : ");
        for v in &self.v {
            write!(f, "{:x}, ", v);
        }
        write!(f, "\n");

        write!(f, "i : {:x}\n", self.i);
        write!(f, "dt: {:x}\n", self.dt);
        write!(f, "st: {:x}\n", self.st);
        write!(f, "pc: {:x}\n", self.pc);
        write!(f, "sp: {:x}\n", self.sp);

        write!(f, "sk: ");
        for s in &self.stack {
            write!(f, "{:x}, ", s);
        }
        write!(f, "")
    }
}

// #[derive(Default)]
struct Computer {
    ram: [u8; 4096],
    cpu: CPU,
}

impl Default for Computer {
     fn default() -> Computer {
         Computer {
             ram: [0u8; 4096],
             cpu: Default::default(),
         }
     }
}

fn combine(arr: &[u8]) -> u16 {
    let mut val: u16 = 0;
    for v in arr {
        val <<= 4;
        val += *v as u16;
    }
    val
}

impl Computer {
    fn ld_i_addr(&mut self, inst: &[u8; 4]) {
        let addr = combine(&inst[1..]);
        self.cpu.i = addr;
    }

    fn rnd_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let random_byte = rand::random::<u8>();
        let byte: u8 = kk & random_byte;
        self.cpu.v[inst[1] as usize] = byte;
    }

    fn se_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let vx = self.cpu.v[inst[1] as usize];
        if kk == vx {
            self.cpu.pc += 2;
        }
    }
}

// cargo run -- ./games/TANK

fn main() {
    let mut computer: Computer = Default::default();
    computer.cpu.pc = 0x200;
    let mut f = File::open(env::args().nth(1).unwrap()).unwrap();

    {
        let end: usize = 0x200 + f.metadata().unwrap().len() as usize;
        let mut slice = &mut computer.ram[0x200..end];
        f.read_exact(slice);
    }

    loop {
        let mut should_inc = true;

        let inst: [u8; 4] = {
            let inst0 = computer.ram[computer.cpu.pc as usize];
            let inst1 = computer.ram[(computer.cpu.pc + 1) as usize];

            let tet0 = inst0 >> 4;
            let tet1 = 0x0f & inst0;
            let tet2 = inst1 >> 4;
            let tet3 = 0x0f & inst1;

            [tet0, tet1, tet2, tet3]
        };

        print!("inst: ");
        for x in &inst {
            print!("{:x}", x);
        }

        let mut inst_name = "";

        match inst[0] {
            0x3 => {
                inst_name = "set_vx_byte";
                computer.se_vx_byte(&inst);
            },
            0xa => {
                inst_name = "ld_i_addr";
                computer.ld_i_addr(&inst);
            },
            0xc => {
                inst_name = "rnd_vx_byte";
                computer.rnd_vx_byte(&inst);
            },
            _ => panic!("unimplemented instruction: {:x}", inst[0])
        }

        println!(" ({})", inst_name);

        if should_inc {
            computer.cpu.pc += 2;
        }

        println!("{:?}", computer.cpu);

        // step on newline
        let mut input = String::new();
        io::stdin().read_line(&mut input);
    }
}

#[test]
fn combine_test1() {
    let inst = [0x1, 0x2, 0x3];
    let combo = combine(&inst);
    assert!(0x123 == combo);
}

#[test]
fn combine_test2() {
    let inst = [0x3];
    let combo = combine(&inst);
    assert!(0x3 == combo);
}

#[test]
fn combine_test3() {
    let inst = [0x1, 0x2, 0x3, 0x4];
    let combo = combine(&inst);
    assert!(0x1234 == combo);
}
<|endoftext|>


<commit_before>extern crate r2d2;
extern crate r2d2_postgres;
extern crate openssl;
#[macro_use] extern crate nickel;
extern crate nickel_postgres;
extern crate uuid;
extern crate serde_json;
extern crate cas;
extern crate crypto;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate cookie;
extern crate core;
extern crate url;

use std::env;
use std::io::Read;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel::{Nickel, HttpRouter, QueryString};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};
use uuid::Uuid;
use nickel::status::StatusCode;
use nickel::extensions::response::Redirect;
use serde_json::Value;
use cas::{CasClient, ServiceResponse, VerifyError};
use crypto::hmac::Hmac;
use crypto::sha2::Sha512Trunc224;
use crypto::mac::{Mac, MacResult};
use hyper::header::Headers;
use hyper::header::{Cookie, SetCookie};
use time::{now, Tm, strptime, Duration};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE, FromBase64Error };
use cookie::Cookie as CookiePair;
use std::string::ToString;
use std::str::FromStr;
use std::str::from_utf8;
use std::str::Utf8Error;
use std::fmt;
use core::fmt::Debug;
use url::form_urlencoded::parse;

macro_rules! try_or_return {
    ( $op:expr, $error:expr ) => {
        match $op {
            Some(v) => v,
            None => return $error
        }
    }
}

macro_rules! try_or {
    ( $op:expr, $error:expr ) => {
        match $op {
            Ok(v) => v,
            Err(e) => {
                println!("error: {:?}", e);
                return $error;
            }
        }
    }
}

fn create_tables(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS services (
                key UUID PRIMARY KEY,
                name VARCHAR NOT NULL
                )",
            &[]
        );

    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS users (
                key SERIAL PRIMARY KEY,
                caseid VARCHAR UNIQUE NOT NULL,
                slackid VARCHAR UNIQUE
                )",
            &[]
        );

    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS permissions (
                key UUID REFERENCES services,
                username integer REFERENCES users,
                permissions JSONB,
                PRIMARY KEY (key, username)
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let hmac_secret = env::var("SECRET").expect("No SECRET found");

    let postgres_url = env::var("DATABASE_URL")
        .expect("Failed to get DATABASE_URL");

    let dbpool = PostgresMiddleware::new(&*postgres_url,
                                         SslMode::None,
                                         5,
                                         Box::new(NopErrorHandler)).unwrap();

    create_tables(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);
    app.get("/register", middleware! { |request, response|
        let conn = request.db_conn();

        let name = try_or_return!(request.query().get("service_name"),
            response.error(
                StatusCode::BadRequest, "No service_name specified"));

        let key = Uuid::new_v4();

        let r = conn.execute(
            "INSERT INTO services (key, name) VALUES ($1, $2)",
            &[&key, &name]
            );
        println!("{:?}", r);

        key.to_hyphenated_string()
    });

    app.post("/adduser", middleware! { |request, response|
        let conn = request.db_conn();

        let mut body = vec![];
        try_or!(request.origin.read_to_end(&mut body),
                       response.error(StatusCode::InternalServerError,
                                      "Failed"));

        let permissions = try_or!(String::from_utf8(body),
            response.error(StatusCode::InternalServerError, "Failed"));

        let data: Value = try_or_return!(
            serde_json::from_str(&permissions).ok(),
            response.error(StatusCode::InternalServerError, "Failed"));

        let q = request.query();

        let caseid = try_or_return!(q.get("caseid"),
            response.error(StatusCode::BadRequest, "No username specified"));
        let key = try_or_return!(q.get("key").map(|s| Uuid::parse_str(s).ok()),
            response.error(StatusCode::BadRequest, "No key specified"));

        let user_rows = try_or!(conn.query(
                "INSERT INTO users (caseid) VALUES ($1)
                    ON CONFLICT (caseid) DO UPDATE SET caseid=users.caseid
                    RETURNING key",
                &[&caseid]
                ), response.error(StatusCode::InternalServerError,
                                  "Server Error")
            );
        if user_rows.len() != 1 {
            return response.error(StatusCode::InternalServerError,
                                  "Server Error");
        }

        let user = user_rows.get(0);
        let user_key: i32 = user.get(0);

        let r = try_or!(conn.execute(
            "INSERT INTO permissions (key, username, permissions)
                VALUES ($1, $2, $3)
                ON CONFLICT (key, username) DO UPDATE SET
                permissions=excluded.permissions",
                &[&key, &user_key, &data]
            ),
            response.error(StatusCode::InternalServerError, "Server error"));
        println!("{:?}", r);
        format!("You posted {}", permissions)
    });

    app.get("/getperms", middleware! { |request, response|
        let conn = request.db_conn();
        let q = request.query();
        let key = try_or_return!(q.get("key").map(|s| Uuid::parse_str(s).ok()),
            response.error(StatusCode::BadRequest, "No key specified"));

        let caseid = q.get("caseid").unwrap_or("");
        let slackid = q.get("slackid").unwrap_or("");

        let r = try_or!(conn.query(
                "SELECT permissions FROM permissions
                    INNER JOIN users
                    ON (permissions.username = users.key)
                    WHERE (caseid=$1 or slackid=$2) and permissions.key=$3",
                &[&caseid, &slackid, &key]
                ), response.error(StatusCode::InternalServerError,
                                  "Server Error")
            );
        println!("{:?}", r);

        if r.len() < 1 {
            return response.error(StatusCode::NotFound, "User not found");
        }
        let row = r.get(0);
        let s: Value = row.get(0);

        format!("{:?}", s)
    });

    let secret = hmac_secret.clone();
    app.get("/login", middleware! { |request, mut response|
        let base_url = env::var("BASE_URL")
            .unwrap_or("https://login.case.edu".to_string());
        let login_path = env::var("LOGIN_PATH")
            .unwrap_or("/cas/login".to_string());
        let logout_path = env::var("LOGOUT_PATH")
            .unwrap_or("/cas/logout".to_string());
        let verify_path = env::var("VERIFY_PATH")
            .unwrap_or("/cas/serviceValidate".to_string());
        let service_url = env::var("URL")
            .unwrap_or("http://hacsoc-auth.case.edu/login".to_string());

        let cas = try_or!(CasClient::new(&base_url, &login_path, &logout_path,
                                         &verify_path, &service_url),
                          response.error(StatusCode::InternalServerError,
                                         "Server Error"));
        match cas.verify_from_request(&request.origin) {
            Ok(ServiceResponse::Success(v)) => {
                set_auth_cookie(&secret, &v, response.headers_mut());
                return response.redirect("/setslackid");
            }
            Ok(ServiceResponse::Failure(e)) => format!("error: {:?}", e),
            Err(VerifyError::NoTicketFound) =>
                return response.redirect(cas.get_login_url()),
            Err(_) => return response.error(StatusCode::InternalServerError,
                                            "Server Error"),
        }
    });

    let secret = hmac_secret.clone();
    app.get("/setslackid", middleware! { |request, response|
        if verify_auth_cookie(&secret, &request.origin.headers) {
            let data = "";
            return response.render("assets/slackform.html", &data);
        } else {
            return response.redirect("/login");
        }
    });

    let secret = hmac_secret.clone();
    app.post("/setslackid", middleware! { |request, response|
        if verify_auth_cookie(&secret, &request.origin.headers) {
            let token = match get_auth_token_from_headers(
                &request.origin.headers) {
                Some(v) => v,
                None => return response.redirect("/login")
            };
            let caseid = token.username;
            let conn = request.db_conn();
            let mut s: Vec<u8> = Vec::new();
            let _r = try_or!(request.origin.read_to_end(&mut s),
                             response.error(StatusCode::InternalServerError,
                                            "Server Error"));
            let data = parse(&s[..]);
            let mut slackid = "".to_string();
            for (name, value) in data {
                if name == "slackid" {
                    slackid = value.to_string();
                    break;
                }
            }

            let r = try_or!(conn.execute("INSERT INTO users (caseid, slackid)
                                    VALUES ($1, $2)
                                    ON CONFLICT (caseid) DO UPDATE SET
                                    slackid=excluded.slackid",
                                    &[&caseid, &slackid]
                                ),
                                response.error(StatusCode::InternalServerError,
                                               "Server Error"));
            println!("{}", r);
            format!("Inserted: {}, {}", caseid, slackid)
        } else {
            return response.redirect("/login");
        }
    });

    let listen = match env::var("LISTEN") {
        Ok(s) => s,
        Err(_) => "127.0.0.1:8080".to_string()
    };

    app.listen(&listen[..]);
}

struct AuthToken {
    time: Tm,
    username: String,
    hmac: MacResult,
}

impl Debug for AuthToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AuthToken {{ time: {:?}, username: {}, hmac: {:?} }}",
               self.time, self.username, self.hmac.code().to_base64(URL_SAFE))
    }
}

impl AuthToken {
    fn new(hmac_secret: &str, username: &str) -> AuthToken {
        AuthToken::new_with_time(hmac_secret, username, now().to_utc())
    }

    fn new_with_time(hmac_secret: &str, username: &str, t: Tm) -> AuthToken {
        let mut hmac = Hmac::new(Sha512Trunc224::new(), hmac_secret.as_bytes());
        let text = format!("{}.{}", username, t.rfc3339());
        hmac.input(text.as_bytes());

        AuthToken {
            time: t,
            username: username.to_string(),
            hmac: hmac.result(),
        }

    }

    fn verify_token(good: &AuthToken, unknown: &AuthToken) -> bool {
        let mut is_good = true;

        is_good = is_good && (good.hmac == unknown.hmac);

        let timeout = Duration::minutes(5);

        is_good = is_good && (unknown.time >= (now().to_utc() - timeout));

        is_good
    }

}

impl ToString for AuthToken {
    fn to_string(&self) -> String {
        let text = format!("{}.{}", self.username, self.time.to_timespec().sec)
            .as_bytes()
            .to_base64(URL_SAFE);

        format!("{}.{}", text, self.hmac.code().to_base64(URL_SAFE))
    }
}

#[derive(Debug)]
enum TokenError {
    Base64(FromBase64Error),
    FirstDotNotFound,
    Utf8(Utf8Error),
    SecondDotNotFound,
}

impl From<FromBase64Error> for TokenError {
    fn from(e: FromBase64Error) -> TokenError {
        TokenError::Base64(e)
    }
}

impl From<Utf8Error> for TokenError {
    fn from(e: Utf8Error) -> TokenError {
        TokenError::Utf8(e)
    }
}

impl FromStr for AuthToken {
    type Err = TokenError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let parts: Vec<&str> = s.split('.').collect();
        if parts.len() != 2 {
            return Err(TokenError::FirstDotNotFound);
        }

        let hmacpart = try!(parts.get(1).unwrap().from_base64());
        let hmac = MacResult::new_from_owned(hmacpart);

        let user = try!(parts.get(0).unwrap().from_base64());
        let userparts: Vec<&str> = try!(from_utf8(&user)).split('.').collect();
        if userparts.len() != 2 {
            return Err(TokenError::SecondDotNotFound);
        }

        let username = userparts.get(0).unwrap();
        let t = strptime(userparts.get(1).unwrap(), "%s").unwrap().to_utc();

        Ok(AuthToken {
            time: t,
            username: username.to_string(),
            hmac: hmac,
        })
    }
}

fn set_auth_cookie(hmac_secret: &str, username: &str, headers: &mut Headers) {
    let token = AuthToken::new(hmac_secret, username);
    let c_pair = CookiePair::new("auth_token".to_string(), token.to_string());

    match headers.get_mut::<SetCookie>() {
        Some(c) => {
            c.push(c_pair);
            return;
        },
        None => {}
    };
    headers.set::<SetCookie>(SetCookie(vec![c_pair]));
}

fn verify_auth_cookie(hmac_secret: &str, headers: &Headers) -> bool {
    let to_verify = match get_auth_token_from_headers(headers) {
        Some(v) => v,
        None => return false
    };
    let good = AuthToken::new_with_time(hmac_secret, &to_verify.username,
                                        to_verify.time);

    AuthToken::verify_token(&good, &to_verify)
}

fn get_auth_token_from_headers(headers: &Headers) -> Option<AuthToken> {
    let cookies = match headers.get::<Cookie>() {
        Some(c) => c,
        None => return None
    };

    let mut auth_string = "".to_string();

    for c in cookies.iter() {
        if c.name == "auth_token" {
            auth_string = c.value.clone();
            break;
        }
    }

    match AuthToken::from_str(&auth_string) {
        Ok(v) => Some(v),
        Err(_) => None
    }
}
<commit_msg>Better finished message<commit_after>extern crate r2d2;
extern crate r2d2_postgres;
extern crate openssl;
#[macro_use] extern crate nickel;
extern crate nickel_postgres;
extern crate uuid;
extern crate serde_json;
extern crate cas;
extern crate crypto;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate cookie;
extern crate core;
extern crate url;

use std::env;
use std::io::Read;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel::{Nickel, HttpRouter, QueryString};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};
use uuid::Uuid;
use nickel::status::StatusCode;
use nickel::extensions::response::Redirect;
use serde_json::Value;
use cas::{CasClient, ServiceResponse, VerifyError};
use crypto::hmac::Hmac;
use crypto::sha2::Sha512Trunc224;
use crypto::mac::{Mac, MacResult};
use hyper::header::Headers;
use hyper::header::{Cookie, SetCookie};
use time::{now, Tm, strptime, Duration};
use rustc_serialize::base64::{ToBase64, FromBase64, URL_SAFE, FromBase64Error };
use cookie::Cookie as CookiePair;
use std::string::ToString;
use std::str::FromStr;
use std::str::from_utf8;
use std::str::Utf8Error;
use std::fmt;
use core::fmt::Debug;
use url::form_urlencoded::parse;

macro_rules! try_or_return {
    ( $op:expr, $error:expr ) => {
        match $op {
            Some(v) => v,
            None => return $error
        }
    }
}

macro_rules! try_or {
    ( $op:expr, $error:expr ) => {
        match $op {
            Ok(v) => v,
            Err(e) => {
                println!("error: {:?}", e);
                return $error;
            }
        }
    }
}

fn create_tables(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS services (
                key UUID PRIMARY KEY,
                name VARCHAR NOT NULL
                )",
            &[]
        );

    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS users (
                key SERIAL PRIMARY KEY,
                caseid VARCHAR UNIQUE NOT NULL,
                slackid VARCHAR UNIQUE
                )",
            &[]
        );

    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS permissions (
                key UUID REFERENCES services,
                username integer REFERENCES users,
                permissions JSONB,
                PRIMARY KEY (key, username)
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let hmac_secret = env::var("SECRET").expect("No SECRET found");

    let postgres_url = env::var("DATABASE_URL")
        .expect("Failed to get DATABASE_URL");

    let dbpool = PostgresMiddleware::new(&*postgres_url,
                                         SslMode::None,
                                         5,
                                         Box::new(NopErrorHandler)).unwrap();

    create_tables(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);
    app.get("/register", middleware! { |request, response|
        let conn = request.db_conn();

        let name = try_or_return!(request.query().get("service_name"),
            response.error(
                StatusCode::BadRequest, "No service_name specified"));

        let key = Uuid::new_v4();

        let r = conn.execute(
            "INSERT INTO services (key, name) VALUES ($1, $2)",
            &[&key, &name]
            );
        println!("{:?}", r);

        key.to_hyphenated_string()
    });

    app.post("/adduser", middleware! { |request, response|
        let conn = request.db_conn();

        let mut body = vec![];
        try_or!(request.origin.read_to_end(&mut body),
                       response.error(StatusCode::InternalServerError,
                                      "Failed"));

        let permissions = try_or!(String::from_utf8(body),
            response.error(StatusCode::InternalServerError, "Failed"));

        let data: Value = try_or_return!(
            serde_json::from_str(&permissions).ok(),
            response.error(StatusCode::InternalServerError, "Failed"));

        let q = request.query();

        let caseid = try_or_return!(q.get("caseid"),
            response.error(StatusCode::BadRequest, "No username specified"));
        let key = try_or_return!(q.get("key").map(|s| Uuid::parse_str(s).ok()),
            response.error(StatusCode::BadRequest, "No key specified"));

        let user_rows = try_or!(conn.query(
                "INSERT INTO users (caseid) VALUES ($1)
                    ON CONFLICT (caseid) DO UPDATE SET caseid=users.caseid
                    RETURNING key",
                &[&caseid]
                ), response.error(StatusCode::InternalServerError,
                                  "Server Error")
            );
        if user_rows.len() != 1 {
            return response.error(StatusCode::InternalServerError,
                                  "Server Error");
        }

        let user = user_rows.get(0);
        let user_key: i32 = user.get(0);

        let r = try_or!(conn.execute(
            "INSERT INTO permissions (key, username, permissions)
                VALUES ($1, $2, $3)
                ON CONFLICT (key, username) DO UPDATE SET
                permissions=excluded.permissions",
                &[&key, &user_key, &data]
            ),
            response.error(StatusCode::InternalServerError, "Server error"));
        println!("{:?}", r);
        format!("You posted {}", permissions)
    });

    app.get("/getperms", middleware! { |request, response|
        let conn = request.db_conn();
        let q = request.query();
        let key = try_or_return!(q.get("key").map(|s| Uuid::parse_str(s).ok()),
            response.error(StatusCode::BadRequest, "No key specified"));

        let caseid = q.get("caseid").unwrap_or("");
        let slackid = q.get("slackid").unwrap_or("");

        let r = try_or!(conn.query(
                "SELECT permissions FROM permissions
                    INNER JOIN users
                    ON (permissions.username = users.key)
                    WHERE (caseid=$1 or slackid=$2) and permissions.key=$3",
                &[&caseid, &slackid, &key]
                ), response.error(StatusCode::InternalServerError,
                                  "Server Error")
            );
        println!("{:?}", r);

        if r.len() < 1 {
            return response.error(StatusCode::NotFound, "User not found");
        }
        let row = r.get(0);
        let s: Value = row.get(0);

        format!("{:?}", s)
    });

    let secret = hmac_secret.clone();
    app.get("/login", middleware! { |request, mut response|
        let base_url = env::var("BASE_URL")
            .unwrap_or("https://login.case.edu".to_string());
        let login_path = env::var("LOGIN_PATH")
            .unwrap_or("/cas/login".to_string());
        let logout_path = env::var("LOGOUT_PATH")
            .unwrap_or("/cas/logout".to_string());
        let verify_path = env::var("VERIFY_PATH")
            .unwrap_or("/cas/serviceValidate".to_string());
        let service_url = env::var("URL")
            .unwrap_or("http://hacsoc-auth.case.edu/login".to_string());

        let cas = try_or!(CasClient::new(&base_url, &login_path, &logout_path,
                                         &verify_path, &service_url),
                          response.error(StatusCode::InternalServerError,
                                         "Server Error"));
        match cas.verify_from_request(&request.origin) {
            Ok(ServiceResponse::Success(v)) => {
                set_auth_cookie(&secret, &v, response.headers_mut());
                return response.redirect("/setslackid");
            }
            Ok(ServiceResponse::Failure(e)) => format!("error: {:?}", e),
            Err(VerifyError::NoTicketFound) =>
                return response.redirect(cas.get_login_url()),
            Err(_) => return response.error(StatusCode::InternalServerError,
                                            "Server Error"),
        }
    });

    let secret = hmac_secret.clone();
    app.get("/setslackid", middleware! { |request, response|
        if verify_auth_cookie(&secret, &request.origin.headers) {
            let data = "";
            return response.render("assets/slackform.html", &data);
        } else {
            return response.redirect("/login");
        }
    });

    let secret = hmac_secret.clone();
    app.post("/setslackid", middleware! { |request, response|
        if verify_auth_cookie(&secret, &request.origin.headers) {
            let token = match get_auth_token_from_headers(
                &request.origin.headers) {
                Some(v) => v,
                None => return response.redirect("/login")
            };
            let caseid = token.username;
            let conn = request.db_conn();
            let mut s: Vec<u8> = Vec::new();
            let _r = try_or!(request.origin.read_to_end(&mut s),
                             response.error(StatusCode::InternalServerError,
                                            "Server Error"));
            let data = parse(&s[..]);
            let mut slackid = "".to_string();
            for (name, value) in data {
                if name == "slackid" {
                    slackid = value.to_string();
                    break;
                }
            }

            let r = try_or!(conn.execute("INSERT INTO users (caseid, slackid)
                                    VALUES ($1, $2)
                                    ON CONFLICT (caseid) DO UPDATE SET
                                    slackid=excluded.slackid",
                                    &[&caseid, &slackid]
                                ),
                                response.error(StatusCode::InternalServerError,
                                               "Server Error"));
            println!("{}", r);
            format!("You have successfully associated the slack id {} with the case id {}",
                    slackid, caseid)
        } else {
            return response.redirect("/login");
        }
    });

    let listen = match env::var("LISTEN") {
        Ok(s) => s,
        Err(_) => "127.0.0.1:8080".to_string()
    };

    app.listen(&listen[..]);
}

struct AuthToken {
    time: Tm,
    username: String,
    hmac: MacResult,
}

impl Debug for AuthToken {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "AuthToken {{ time: {:?}, username: {}, hmac: {:?} }}",
               self.time, self.username, self.hmac.code().to_base64(URL_SAFE))
    }
}

impl AuthToken {
    fn new(hmac_secret: &str, username: &str) -> AuthToken {
        AuthToken::new_with_time(hmac_secret, username, now().to_utc())
    }

    fn new_with_time(hmac_secret: &str, username: &str, t: Tm) -> AuthToken {
        let mut hmac = Hmac::new(Sha512Trunc224::new(), hmac_secret.as_bytes());
        let text = format!("{}.{}", username, t.rfc3339());
        hmac.input(text.as_bytes());

        AuthToken {
            time: t,
            username: username.to_string(),
            hmac: hmac.result(),
        }

    }

    fn verify_token(good: &AuthToken, unknown: &AuthToken) -> bool {
        let mut is_good = true;

        is_good = is_good && (good.hmac == unknown.hmac);

        let timeout = Duration::minutes(5);

        is_good = is_good && (unknown.time >= (now().to_utc() - timeout));

        is_good
    }

}

impl ToString for AuthToken {
    fn to_string(&self) -> String {
        let text = format!("{}.{}", self.username, self.time.to_timespec().sec)
            .as_bytes()
            .to_base64(URL_SAFE);

        format!("{}.{}", text, self.hmac.code().to_base64(URL_SAFE))
    }
}

#[derive(Debug)]
enum TokenError {
    Base64(FromBase64Error),
    FirstDotNotFound,
    Utf8(Utf8Error),
    SecondDotNotFound,
}

impl From<FromBase64Error> for TokenError {
    fn from(e: FromBase64Error) -> TokenError {
        TokenError::Base64(e)
    }
}

impl From<Utf8Error> for TokenError {
    fn from(e: Utf8Error) -> TokenError {
        TokenError::Utf8(e)
    }
}

impl FromStr for AuthToken {
    type Err = TokenError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let parts: Vec<&str> = s.split('.').collect();
        if parts.len() != 2 {
            return Err(TokenError::FirstDotNotFound);
        }

        let hmacpart = try!(parts.get(1).unwrap().from_base64());
        let hmac = MacResult::new_from_owned(hmacpart);

        let user = try!(parts.get(0).unwrap().from_base64());
        let userparts: Vec<&str> = try!(from_utf8(&user)).split('.').collect();
        if userparts.len() != 2 {
            return Err(TokenError::SecondDotNotFound);
        }

        let username = userparts.get(0).unwrap();
        let t = strptime(userparts.get(1).unwrap(), "%s").unwrap().to_utc();

        Ok(AuthToken {
            time: t,
            username: username.to_string(),
            hmac: hmac,
        })
    }
}

fn set_auth_cookie(hmac_secret: &str, username: &str, headers: &mut Headers) {
    let token = AuthToken::new(hmac_secret, username);
    let c_pair = CookiePair::new("auth_token".to_string(), token.to_string());

    match headers.get_mut::<SetCookie>() {
        Some(c) => {
            c.push(c_pair);
            return;
        },
        None => {}
    };
    headers.set::<SetCookie>(SetCookie(vec![c_pair]));
}

fn verify_auth_cookie(hmac_secret: &str, headers: &Headers) -> bool {
    let to_verify = match get_auth_token_from_headers(headers) {
        Some(v) => v,
        None => return false
    };
    let good = AuthToken::new_with_time(hmac_secret, &to_verify.username,
                                        to_verify.time);

    AuthToken::verify_token(&good, &to_verify)
}

fn get_auth_token_from_headers(headers: &Headers) -> Option<AuthToken> {
    let cookies = match headers.get::<Cookie>() {
        Some(c) => c,
        None => return None
    };

    let mut auth_string = "".to_string();

    for c in cookies.iter() {
        if c.name == "auth_token" {
            auth_string = c.value.clone();
            break;
        }
    }

    match AuthToken::from_str(&auth_string) {
        Ok(v) => Some(v),
        Err(_) => None
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: GPL-2.0-only
//

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

extern crate updatehub;

#[macro_use]
extern crate log;
extern crate stderrlog;

use updatehub::build_info;
use updatehub::firmware::Metadata as FirmwareMetadata;
use updatehub::runtime_settings::RuntimeSettings;
use updatehub::settings::Settings;

mod cmdline;
use cmdline::CmdLine;

fn main() {
    let cmdline = CmdLine::parse_args();

    stderrlog::new().quiet(cmdline.quiet)
                    .verbosity(if cmdline.debug { 3 } else { 2 })
                    .init()
                    .expect("Failed to initialize the logger.");

    info!("Starting UpdateHub Agent {}", build_info::version());

    let settings = Settings::new().load().expect("Failed to load settings.");
    let runtime_settings = RuntimeSettings::new().load(&settings.storage.runtime_settings)
                                                 .expect("Failed to load runtime settings.");
    let firmware_metadata =
        FirmwareMetadata::new(&settings.firmware.metadata_path).expect("Failed to load the firmware metadata.");
}
<commit_msg>main: Stop renaming Firmware::Metadata as FirmwareMetadata<commit_after>// Copyright (C) 2017, 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: GPL-2.0-only
//

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]

extern crate updatehub;

#[macro_use]
extern crate log;
extern crate stderrlog;

use updatehub::build_info;
use updatehub::firmware::Metadata;
use updatehub::runtime_settings::RuntimeSettings;
use updatehub::settings::Settings;

mod cmdline;
use cmdline::CmdLine;

fn main() {
    let cmdline = CmdLine::parse_args();

    stderrlog::new().quiet(cmdline.quiet)
                    .verbosity(if cmdline.debug { 3 } else { 2 })
                    .init()
                    .expect("Failed to initialize the logger.");

    info!("Starting UpdateHub Agent {}", build_info::version());

    let settings = Settings::new().load().expect("Failed to load settings.");
    let runtime_settings = RuntimeSettings::new().load(&settings.storage.runtime_settings)
                                                 .expect("Failed to load runtime settings.");
    let firmware = Metadata::new(&settings.firmware.metadata_path).expect("Failed to load the firmware metadata.");
}
<|endoftext|>