<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub setup:Setup,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Setup {
    pub elements:Vec<(String, String)>,
    pub pcbplotparams:Option<Sexp>,
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
            setup:Setup::new(),
        }
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
    pub fn has_net(&self, name:&'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true
            }
        }
        return false
    }
}

impl Setup {
    pub fn new() -> Setup {
        Setup { elements:vec![],pcbplotparams:Some(Sexp::List(vec![Sexp::String(String::from("pcbplotparams"))]))}
    }
    pub fn get(&self, s:&String) -> Option<&String> {
        for element in &self.elements {
            if element.0[..] == s[..] {
                return Some(&element.1)
            }
        }
        return None
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        let mut i = 0;
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
            // kludge to put setup at the right order in the file
            if i == 3 {
                try!(writeln!(f, "  {}", self.setup));
            }
            i+=1;
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} {} ", self.name, rustysexp::display_string(&self.desc)));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

impl fmt::Display for Setup {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(setup"));
        for ref k in &self.elements {
            try!(writeln!(f, "   ({} {})", k.0, k.1));
        }
        match self.pcbplotparams {
            None => writeln!(f, ")"),
            Some(ref s) => writeln!(f, " {})", s),
        }
    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse_setup(e:&Sexp) -> ERes<Setup> {
    let mut h = vec![];
    let mut pcbplotparams = None;
    for v in try!(e.slice_atom("setup")) {
        let n = v.list_name().unwrap().clone();
        match &n[..] {
            "pcbplotparams" => { pcbplotparams = Some(v.clone()); },
            x => {
                // TODO: this is a kludge, implement proper data type for Setup
                let v2 = v.slice_atom(x).unwrap();
                let mut s = String::new();
                let mut first = true;
                for z in v2 {
                    if !first { s.push_str(" ") };
                    first = false;
                    s.push_str(z.string().unwrap());
                }
                h.push((n.clone(), s));
            },
        }
    }
    let s = Setup { elements:h , pcbplotparams:pcbplotparams };
    Ok(s)
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            "setup" => layout.setup = try!(parse_setup(e)),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>update_element<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub setup:Setup,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Setup {
    pub elements:Vec<(String, String)>,
    pub pcbplotparams:Option<Sexp>,
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
            setup:Setup::new(),
        }
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
    pub fn has_net(&self, name:&'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true
            }
        }
        return false
    }
}

impl Setup {
    pub fn new() -> Setup {
        Setup { elements:vec![],pcbplotparams:Some(Sexp::List(vec![Sexp::String(String::from("pcbplotparams"))]))}
    }
    pub fn get(&self, s:&String) -> Option<&String> {
        for element in &self.elements {
            if element.0[..] == s[..] {
                return Some(&element.1)
            }
        }
        return None
    }

    pub fn update_element(&mut self, name:&String, value:String) {
        for element in &mut self.elements {
            if element.0[..] == name[..] {
                element.1 = value;
                return;

            }
        }
        self.elements.push((name.clone(), value));
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        let mut i = 0;
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
            // kludge to put setup at the right order in the file
            if i == 3 {
                try!(writeln!(f, "  {}", self.setup));
            }
            i+=1;
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} {} ", self.name, rustysexp::display_string(&self.desc)));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

impl fmt::Display for Setup {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(setup"));
        for ref k in &self.elements {
            try!(writeln!(f, "   ({} {})", k.0, k.1));
        }
        match self.pcbplotparams {
            None => writeln!(f, ")"),
            Some(ref s) => writeln!(f, " {})", s),
        }
    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse_setup(e:&Sexp) -> ERes<Setup> {
    let mut h = vec![];
    let mut pcbplotparams = None;
    for v in try!(e.slice_atom("setup")) {
        let n = v.list_name().unwrap().clone();
        match &n[..] {
            "pcbplotparams" => { pcbplotparams = Some(v.clone()); },
            x => {
                // TODO: this is a kludge, implement proper data type for Setup
                let v2 = v.slice_atom(x).unwrap();
                let mut s = String::new();
                let mut first = true;
                for z in v2 {
                    if !first { s.push_str(" ") };
                    first = false;
                    s.push_str(z.string().unwrap());
                }
                h.push((n.clone(), s));
            },
        }
    }
    let s = Setup { elements:h , pcbplotparams:pcbplotparams };
    Ok(s)
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            "setup" => layout.setup = try!(parse_setup(e)),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::view(view);
}

fn view(app: &App, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();

    // Clear the background.
    draw.background().color(BLACK);

    let win = app.window_rect();
    let t = app.time;

    // Decide on a number of points and a thickness.
    let n_points = 10;
    let half_thickness = 4.0;
    let hz = ((app.mouse.x + win.right()) / win.w()).powi(4) * 1000.0;

    // Create an iterator for each point in the polyline.
    let points = (0..n_points)
        .map(|i| {
            let x = map_range(i, 0, n_points-1, win.left(), win.right());
            let fract = i as f32 / n_points as f32;
            let amp = (t + fract * hz * TAU).sin();
            let y = map_range(amp, -1.0, 1.0, win.bottom() * 0.75, win.top() * 0.75);
            pt2(x, y)
        });

    // Get the miter vertices for the polyline and colour them.
    let vs = geom::line::join::miter::vertices(points, half_thickness)
        .enumerate()
        .flat_map(|(i, [nl, nr])| {
            let fract = i as f32 / n_points as f32;
            let r = (t + fract) % 1.0;
            let g = (t + 1.0 - fract) % 1.0;
            let b = (t + 0.5 + fract) % 1.0;
            let rgba = nannou::color::Rgba::new(r, g, b, 1.0);
            Some(geom::vertex::Rgba(nr, rgba))
                .into_iter()
                .chain(Some(geom::vertex::Rgba(nl, rgba)))
        });

    // Get the indices for triangulating the polyline.
    let is = geom::line::join::miter::triangle_indices(n_points);

    // Draw the polyline using a mesh.
    draw.mesh().indexed(vs, is);

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}
<commit_msg>Update simple_polyline example to use polyline draw API<commit_after>extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::view(view);
}

fn view(app: &App, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();

    // Clear the background.
    draw.background().color(BLACK);

    let win = app.window_rect();
    let t = app.time;

    // Decide on a number of points and a thickness.
    let n_points = 10;
    let half_thickness = 4.0;
    let hz = ((app.mouse.x + win.right()) / win.w()).powi(4) * 1000.0;
    let vertices = (0..n_points)
        // A sine wave mapped to the range of the window.
        .map(|i| {
            let x = map_range(i, 0, n_points-1, win.left(), win.right());
            let fract = i as f32 / n_points as f32;
            let amp = (t + fract * hz * TAU).sin();
            let y = map_range(amp, -1.0, 1.0, win.bottom() * 0.75, win.top() * 0.75);
            pt2(x, y)
        })
        .enumerate()
        // Colour each vertex uniquely based on its index.
        .map(|(i, p)| {
            let fract = i as f32 / n_points as f32;
            let r = (t + fract) % 1.0;
            let g = (t + 1.0 - fract) % 1.0;
            let b = (t + 0.5 + fract) % 1.0;
            let rgba = nannou::color::Rgba::new(r, g, b, 1.0);
            geom::vertex::Rgba(p, rgba)
        });

    // Draw the polyline.
    draw.polyline().vertices(half_thickness, vertices);

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}
<|endoftext|>


<commit_before>//! Example of how to implement `KV` for a struct
//! to conveniently log data associated with it.
#[macro_use]
extern crate slog;
use slog::*;

mod common;

struct Peer {
    host: String,
    port: u32,
}

impl Peer {
    fn new(host: String, port: u32) -> Self {
        Peer {
            host: host,
            port: port,
        }
    }
}

// `KV` can be implemented for a struct
#[cfg(not(feature = "opaque-keys"))]
impl KV for Peer {
    fn serialize(
        &self,
        _record: &Record,
        serializer: &mut Serializer,
    ) -> Result {

        serializer.emit_u32("peer-port", self.port)?;
        serializer.emit_str("peer-host", &self.host)?;
        Ok(())
    }
}
#[cfg(feature = "opaque-keys")]
impl KV for Peer {
    fn serialize(
        &self,
        _record: &Record,
        serializer: &mut Serializer,
    ) -> Result {

        serializer.emit_u32(Key::from("peer-port"), self.port)?;
        serializer.emit_str(Key::from("peer-host"), &self.host)?;
        Ok(())
    }
}

struct Server {
    _host: String,
    _port: u32,
    // One approach is to create new `Logger` with struct data
    // and embedded it into struct itself.  This works when struct is mostly
    // immutable.
    log: Logger,
}

impl Server {
    fn new(host: String, port: u32, log: Logger) -> Server {
        let log =
            log.new(o!("server-host" => host.clone(), "server-port" => port));
        Server {
            _host: host,
            _port: port,
            log: log,
        }
    }

    fn connection(&self, peer: &Peer) {
        // Another approach is to add struct to a logging message when it's
        // necessary. This might be necessary when struct data can change
        // between different logging statements (not the case here for `Peer`).
        info!(self.log, "new connection"; peer);
    }
}

struct PeerCounter {
    count: usize,
    log: Logger,
}

impl PeerCounter {
    fn new(log: Logger) -> Self {
        PeerCounter { count: 0, log: log }
    }

    // A hybrid approach with `Logger` with parent logging-context embedded into
    // a `struct` and a helper function adding mutable fields.
    fn log_info(&self, msg: &str, kv: BorrowedKV) {
        info!(self.log, "{}", msg; "current-count" => self.count, kv);
    }

    fn count(&mut self, peer: &Peer) {
        self.count += 1;
        self.log_info("counted peer", b!(peer));
    }
}

fn main() {
    let log = Logger::root(
        Fuse(common::PrintlnDrain),
        o!("build-id" => "7.3.3-abcdef"),
    );

    let server = Server::new("localhost".into(), 12345, log.clone());

    let peer = Peer::new("1.2.3.4".into(), 999);
    server.connection(&peer);
    let mut counter = PeerCounter::new(log);
    counter.count(&peer);
}
<commit_msg>Fix example relying on feature that does not exist anymore<commit_after>//! Example of how to implement `KV` for a struct
//! to conveniently log data associated with it.
#[macro_use]
extern crate slog;
use slog::*;

mod common;

struct Peer {
    host: String,
    port: u32,
}

impl Peer {
    fn new(host: String, port: u32) -> Self {
        Peer {
            host: host,
            port: port,
        }
    }
}

// `KV` can be implemented for a struct
impl KV for Peer {
    fn serialize(&self, _record: &Record, serializer: &mut Serializer) -> Result {
        serializer.emit_u32(Key::from("peer-port"), self.port)?;
        serializer.emit_str(Key::from("peer-host"), &self.host)?;
        Ok(())
    }
}

struct Server {
    _host: String,
    _port: u32,
    // One approach is to create new `Logger` with struct data
    // and embedded it into struct itself.  This works when struct is mostly
    // immutable.
    log: Logger,
}

impl Server {
    fn new(host: String, port: u32, log: Logger) -> Server {
        let log = log.new(o!("server-host" => host.clone(), "server-port" => port));
        Server {
            _host: host,
            _port: port,
            log: log,
        }
    }

    fn connection(&self, peer: &Peer) {
        // Another approach is to add struct to a logging message when it's
        // necessary. This might be necessary when struct data can change
        // between different logging statements (not the case here for `Peer`).
        info!(self.log, "new connection"; peer);
    }
}

struct PeerCounter {
    count: usize,
    log: Logger,
}

impl PeerCounter {
    fn new(log: Logger) -> Self {
        PeerCounter { count: 0, log: log }
    }

    // A hybrid approach with `Logger` with parent logging-context embedded into
    // a `struct` and a helper function adding mutable fields.
    fn log_info(&self, msg: &str, kv: BorrowedKV) {
        info!(self.log, "{}", msg; "current-count" => self.count, kv);
    }

    fn count(&mut self, peer: &Peer) {
        self.count += 1;
        self.log_info("counted peer", b!(peer));
    }
}

fn main() {
    let log = Logger::root(Fuse(common::PrintlnDrain), o!("build-id" => "7.3.3-abcdef"));

    let server = Server::new("localhost".into(), 12345, log.clone());

    let peer = Peer::new("1.2.3.4".into(), 999);
    server.connection(&peer);
    let mut counter = PeerCounter::new(log);
    counter.count(&peer);
}
<|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate rusqlite;
extern crate time;

use self::rusqlite::Connection;

use std::path::Path;

use common::{ImageBlob, Material, Mesh, SceneNode, Scene, Shader, Vertex8f32};

fn create_vertex8f32(px: f64,
                     py: f64,
                     pz: f64,
                     nx: f64,
                     ny: f64,
                     nz: f64,
                     tu: f64,
                     tv: f64)
                     -> Vertex8f32 {
    let position: [f32; 3] = [px as f32, py as f32, pz as f32];
    let normal: [f32; 3] = [nx as f32, ny as f32, nz as f32];
    let texcoord: [f32; 2] = [tu as f32, tv as f32];
    Vertex8f32 {
        position: position,
        normal: normal,
        texcoord: texcoord,
    }
}

pub fn load_db(filename: &str) -> Scene {
    println!("Loading {}", filename);

    let path: &Path = Path::new(filename);
    let conn = Connection::open(path).unwrap();

    // Load vertices
    let mut vertex_stmt = conn.prepare("SELECT px, py, pz, nx, ny, nz, tu, tv FROM vertex")
        .unwrap();
    let vertex_iter = vertex_stmt.query_map(&[], |row| {
            create_vertex8f32(row.get(0),
                              row.get(1),
                              row.get(2),
                              row.get(3),
                              row.get(4),
                              row.get(5),
                              row.get(6),
                              row.get(7))
        })
        .unwrap();

    let mut vertices: Vec<Vertex8f32> = Vec::new();

    for vertex in vertex_iter {
        vertices.push(vertex.unwrap());
    }

    let mut meshes: Vec<Mesh> = Vec::new();

    // Load scene nodes
    let mut scene_node_stmt =
        conn.prepare("SELECT name, material_id, start_position, end_position FROM scene_node")
            .unwrap();
    let scene_node_iter = scene_node_stmt.query_map(&[], |row| {
            let material_id: i32 = row.get(1);
            SceneNode {
                name: row.get(0),
                material_id: material_id - 1, // index starts at 1 in database, not 0
                start_position: row.get(2),
                end_position: row.get(3),
            }
        })
        .unwrap();

    for scene_node in scene_node_iter {
        let sn = scene_node.unwrap();
        let mut new_vertices: Vec<Vertex8f32> = Vec::new();

        for i in sn.start_position as usize..(sn.end_position) as usize {
            new_vertices.push(vertices[i]);

        }
        let mesh = Mesh {
            name: sn.name,
            material_id: sn.material_id,
            vertices: new_vertices,
        };
        meshes.push(mesh);
    }

    println!("Loaded {} vertices in {} meshes",
             vertices.len(),
             meshes.len());

    // Free up some memory
    vertices.clear();

    // Load materials
    let mut material_stmt =
        conn.prepare("SELECT name, diffuse_r, diffuse_g, diffuse_b, diffuse_texname FROM material")
            .unwrap();
    let material_iter = material_stmt.query_map(&[], |row| {
            let diffuse_r: f64 = row.get(1);
            let diffuse_g: f64 = row.get(2);
            let diffuse_b: f64 = row.get(3);
            Material {
                name: row.get(0),
                diffuse: [diffuse_r as f32, diffuse_g as f32, diffuse_b as f32],
                diffuse_texname: row.get(4),
            }
        })
        .unwrap();

    let mut materials: Vec<Material> = Vec::new();

    for material in material_iter {
        materials.push(material.unwrap());
    }

    // Load textures
    let mut texture_stmt = conn.prepare("SELECT name, image FROM texture")
        .unwrap();
    let texture_iter = texture_stmt.query_map(&[], |row| {
            ImageBlob {
                name: row.get(0),
                image: row.get(1),
            }
        })
        .unwrap();

    let mut textures: Vec<ImageBlob> = Vec::new();

    for texture in texture_iter {
        textures.push(texture.unwrap());
    }

    // Load shaders
    let mut shader_stmt =
        conn.prepare("SELECT name, vertex_source_140, fragment_source_140 FROM shader")
            .unwrap();
    let shader_iter = shader_stmt.query_map(&[], |row| {
            Shader {
                name: row.get(0),
                vertex_source_140: row.get(1),
                fragment_source_140: row.get(2),
            }
        })
        .unwrap();

    let mut shaders: Vec<Shader> = Vec::new();

    for shader in shader_iter {
        shaders.push(shader.unwrap());
    }

    return Scene {
        materials: materials,
        // scene_nodes: scene_nodes,
        // vertices: vertices,
        meshes: meshes,
        shaders: shaders,
        images: textures,
    };
}
<commit_msg>re-ordered loader so material_ids/material_indexes can be bounds-checked<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate rusqlite;
extern crate time;

use self::rusqlite::Connection;

use std::path::Path;

use common::{ImageBlob, Material, Mesh, SceneNode, Scene, Shader, Vertex8f32};

fn create_vertex8f32(px: f64,
                     py: f64,
                     pz: f64,
                     nx: f64,
                     ny: f64,
                     nz: f64,
                     tu: f64,
                     tv: f64)
                     -> Vertex8f32 {
    let position: [f32; 3] = [px as f32, py as f32, pz as f32];
    let normal: [f32; 3] = [nx as f32, ny as f32, nz as f32];
    let texcoord: [f32; 2] = [tu as f32, tv as f32];
    Vertex8f32 {
        position: position,
        normal: normal,
        texcoord: texcoord,
    }
}

pub fn load_db(filename: &str) -> Scene {
    println!("Loading {}", filename);

    let path: &Path = Path::new(filename);
    let conn = Connection::open(path).unwrap();

    // Load vertices
    let mut vertex_stmt = conn.prepare("SELECT px, py, pz, nx, ny, nz, tu, tv FROM vertex")
        .unwrap();
    let vertex_iter = vertex_stmt.query_map(&[], |row| {
            create_vertex8f32(row.get(0),
                              row.get(1),
                              row.get(2),
                              row.get(3),
                              row.get(4),
                              row.get(5),
                              row.get(6),
                              row.get(7))
        })
        .unwrap();

    let mut vertices: Vec<Vertex8f32> = Vec::new();

    for vertex in vertex_iter {
        vertices.push(vertex.unwrap());
    }

    // Load materials
    let mut material_stmt =
        conn.prepare("SELECT name, diffuse_r, diffuse_g, diffuse_b, diffuse_texname FROM material")
            .unwrap();
    let material_iter = material_stmt.query_map(&[], |row| {
            let diffuse_r: f64 = row.get(1);
            let diffuse_g: f64 = row.get(2);
            let diffuse_b: f64 = row.get(3);
            Material {
                name: row.get(0),
                diffuse: [diffuse_r as f32, diffuse_g as f32, diffuse_b as f32],
                diffuse_texname: row.get(4),
            }
        })
        .unwrap();

    let mut materials: Vec<Material> = Vec::new();

    for material in material_iter {
        materials.push(material.unwrap());
    }

    let mut meshes: Vec<Mesh> = Vec::new();

    // Load scene nodes
    let mut scene_node_stmt =
        conn.prepare("SELECT name, material_id, start_position, end_position FROM scene_node")
            .unwrap();
    let scene_node_iter = scene_node_stmt.query_map(&[], |row| {
            let material_id: i32 = row.get(1);
            let material_index: usize = material_id as usize - 1 as usize;
            SceneNode {
                name: row.get(0),
                material_index: material_index, // index starts at 1 in database, not 0
                start_position: row.get(2),
                end_position: row.get(3),
            }
        })
        .unwrap();

    for scene_node in scene_node_iter {
        let sn = scene_node.unwrap();
        let mut new_vertices: Vec<Vertex8f32> = Vec::new();

        for i in sn.start_position as usize..(sn.end_position) as usize {
            new_vertices.push(vertices[i]);

        }

        if sn.material_index >= materials.len() || sn.material_index < 0 {
            panic!("Material index {} out of bounds", sn.material_index);
        }

        let mesh = Mesh {
            name: sn.name,
            material_index: sn.material_index,
            vertices: new_vertices,
        };
        meshes.push(mesh);
    }

    println!("Loaded {} vertices in {} meshes",
             vertices.len(),
             meshes.len());

    // Free up some memory
    vertices.clear();

    // Load textures
    let mut texture_stmt = conn.prepare("SELECT name, image FROM texture")
        .unwrap();
    let texture_iter = texture_stmt.query_map(&[], |row| {
            ImageBlob {
                name: row.get(0),
                image: row.get(1),
            }
        })
        .unwrap();

    let mut textures: Vec<ImageBlob> = Vec::new();

    for texture in texture_iter {
        textures.push(texture.unwrap());
    }

    // Load shaders
    let mut shader_stmt =
        conn.prepare("SELECT name, vertex_source_140, fragment_source_140 FROM shader")
            .unwrap();
    let shader_iter = shader_stmt.query_map(&[], |row| {
            Shader {
                name: row.get(0),
                vertex_source_140: row.get(1),
                fragment_source_140: row.get(2),
            }
        })
        .unwrap();

    let mut shaders: Vec<Shader> = Vec::new();

    for shader in shader_iter {
        shaders.push(shader.unwrap());
    }

    return Scene {
        materials: materials,
        // scene_nodes: scene_nodes,
        // vertices: vertices,
        meshes: meshes,
        shaders: shaders,
        images: textures,
    };
}
<|endoftext|>


<commit_before>//! Defines useful macros for glium usage.

/// Returns an implementation-defined type which implements the `Uniform` trait.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// let uniforms = uniform! {
///     color: [1.0, 1.0, 0.0, 1.0],
///     some_value: 12i32
/// };
/// # }
/// ```
#[macro_export]
macro_rules! uniform {
    () => {
        $crate::uniforms::EmptyUniforms
    };

    ($field:ident: $value:expr) => {
        $crate::uniforms::UniformsStorage::new(stringify!($field), $value)
    };

    ($field1:ident: $value1:expr, $($field:ident: $value:expr),+) => {
        {
            let uniforms = $crate::uniforms::UniformsStorage::new(stringify!($field1), $value1);
            $(
                let uniforms = uniforms.add(stringify!($field), $value);
            )+
            uniforms
        }
    };

    ($($field:ident: $value:expr),*,) => {
        uniform!($($field: $value),*)
    };
}

/// Implements the `glium::vertex::Vertex` trait for the given type.
///
/// The parameters must be the name of the struct and the names of its fields.
///
/// ## Example
///
/// ```
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// #[derive(Copy, Clone)]
/// struct Vertex {
///     position: [f32; 3],
///     tex_coords: [f32; 2],
/// }
///
/// implement_vertex!(Vertex, position, tex_coords);
/// # }
/// ```
///
#[macro_export]
macro_rules! implement_vertex {
    ($struct_name:ident, $($field_name:ident),+) => (
        impl $crate::vertex::Vertex for $struct_name {
            fn build_bindings() -> $crate::vertex::VertexFormat {
                use std::borrow::Cow;

                vec![
                    $(
                        (
                            Cow::Borrowed(stringify!($field_name)),
                            {
                                let dummy: &$struct_name = unsafe { ::std::mem::transmute(0usize) };
                                let dummy_field = &dummy.$field_name;
                                let dummy_field: usize = unsafe { ::std::mem::transmute(dummy_field) };
                                dummy_field
                            },
                            {
                                fn attr_type_of_val<T: $crate::vertex::Attribute>(_: &T)
                                    -> $crate::vertex::AttributeType
                                {
                                    <T as $crate::vertex::Attribute>::get_type()
                                }
                                let dummy: &$struct_name = unsafe { ::std::mem::transmute(0usize) };
                                attr_type_of_val(&dummy.$field_name)
                            },
                        )
                    ),+
                ]
            }
        }
    );

    ($struct_name:ident, $($field_name:ident),+,) => (
        implement_vertex!($struct_name, $($field_name),+);
    );
}

/// Builds a program depending on the GLSL version supported by the backend.
///
/// This is implemented with successive calls to `is_glsl_version_supported()`.
///
/// ## Example
///
/// ```ignore       // TODO: no_run instead
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// # let display: glium::Display = unsafe { std::mem::uninitialized() };
/// let program = program!(&display,
///     300 => {
///         vertex: r#"
///             #version 300
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 300
///
///             out vec4 color;
///             fn main() {
///                 color = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
///     110 => {
///         vertex: r#"
///             #version 110
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 110
///
///             fn main() {
///                 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
///     300 es => {
///         vertex: r#"
///             #version 110
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 110
///
///             fn main() {
///                 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
/// );
/// # }
/// ```
///
#[macro_export]
macro_rules! program {
    ($facade:expr,) => (
        panic!("No version found");     // TODO: handle better
    );

    ($facade:expr,,$($rest:tt)*) => (
        program!($facade,$($rest)*)
    );

    ($facade:expr, $num:tt => $($rest:tt)*) => (
        {
            let context = $crate::backend::Facade::get_context($facade);
            let version = program!(_parse_num_gl $num);
            program!(_inner, context, version, $($rest)*)
        }
    );

    ($facade:expr, $num:tt es => $($rest:tt)*) => (
        {
            let context = $crate::backend::Facade::get_context($facade);
            let version = program!(_parse_num_gles $num);
            program!(_inner, context, version, $($rest)*)
        }
    );

    (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+}$($rest:tt)*) => (
        if $context.is_glsl_version_supported(&$vers) {
            let _vertex_shader: &str = "";
            let _tessellation_control_shader: Option<&str> = None;
            let _tessellation_evaluation_shader: Option<&str> = None;
            let _geometry_shader: Option<&str> = None;
            let _fragment_shader: &str = "";

            $(
                program!(_program_ty $ty, $src, _vertex_shader, _tessellation_control_shader,
                         _tessellation_evaluation_shader, _geometry_shader, _fragment_shader);
            )+

            let input = $crate::program::ProgramCreationInput::SourceCode {
                vertex_shader: _vertex_shader,
                tessellation_control_shader: _tessellation_control_shader,
                tessellation_evaluation_shader: _tessellation_evaluation_shader,
                geometry_shader: _geometry_shader,
                fragment_shader: _fragment_shader,
                transform_feedback_varyings: None,
            };

            $crate::program::Program::new($context, input)

        } else {
            program!($context, $($rest)*)
        }
    );

    (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+,}$($rest:tt)*) => (
        program!(_inner, $context, $vers, {$($ty:$src),+} $($rest)*);
    );

    (_program_ty vertex, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $vs = $src;
    );

    (_program_ty tessellation_control, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $tcs = Some($src);
    );

    (_program_ty tessellation_evaluation, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $tes = Some($src);
    );

    (_program_ty geometry, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $gs = Some($src);
    );

    (_program_ty fragment, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $fs = $src;
    );

    (_parse_num_gl $num:expr) => (
        if $num == 100 {
            $crate::Version($crate::Api::GlEs, 1, 0)
        } else {
            $crate::Version($crate::Api::Gl, $num / 100, ($num % 100) / 10)
        }
    );

    (_parse_num_gles $num:expr) => ($crate::Version($crate::Api::GlEs, $num / 100, ($num % 100) / 10));
}

#[cfg(test)]
mod tests {
    #[test]
    fn trailing_comma_impl_uniforms() {
        let u = uniform!{ a: 5, b: 6, };
    }

    #[test]
    fn trailing_comma_impl_vertex() {
        #[derive(Copy, Clone)]
        struct Foo {
            pos: [f32; 2],
        }

        implement_vertex!(Foo, pos,);
    }
}
<commit_msg>Added a macro for assert_no_error<commit_after>//! Defines useful macros for glium usage.

#[macro_export]
macro_rules! assert_no_error {
    ($display: expr) => {
        {
            let message = format!("{}:{}", file!(), line!());
            $display.assert_no_error(Some(&message[..]));
        }
    };
    ($display: expr, $msg: expr) => {
        {
            let message = format!("{}:{}  {}", file!(), line!(), $msg);
            $display.assert_no_error(Some(&message[..]));
        }
    };
    ($display: expr, $fmt: expr, $($arg:tt)+) => {
        {
            let message = format!(concat!("{}:{} ", $fmt), file!(), line!(), $($arg)+);
            $display.assert_no_error(Some(&message[..]));
        }
    }
}

/// Returns an implementation-defined type which implements the `Uniform` trait.
///
/// ## Example
///
/// ```rust
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// let uniforms = uniform! {
///     color: [1.0, 1.0, 0.0, 1.0],
///     some_value: 12i32
/// };
/// # }
/// ```
#[macro_export]
macro_rules! uniform {
    () => {
        $crate::uniforms::EmptyUniforms
    };

    ($field:ident: $value:expr) => {
        $crate::uniforms::UniformsStorage::new(stringify!($field), $value)
    };

    ($field1:ident: $value1:expr, $($field:ident: $value:expr),+) => {
        {
            let uniforms = $crate::uniforms::UniformsStorage::new(stringify!($field1), $value1);
            $(
                let uniforms = uniforms.add(stringify!($field), $value);
            )+
            uniforms
        }
    };

    ($($field:ident: $value:expr),*,) => {
        uniform!($($field: $value),*)
    };
}

/// Implements the `glium::vertex::Vertex` trait for the given type.
///
/// The parameters must be the name of the struct and the names of its fields.
///
/// ## Example
///
/// ```
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// #[derive(Copy, Clone)]
/// struct Vertex {
///     position: [f32; 3],
///     tex_coords: [f32; 2],
/// }
///
/// implement_vertex!(Vertex, position, tex_coords);
/// # }
/// ```
///
#[macro_export]
macro_rules! implement_vertex {
    ($struct_name:ident, $($field_name:ident),+) => (
        impl $crate::vertex::Vertex for $struct_name {
            fn build_bindings() -> $crate::vertex::VertexFormat {
                use std::borrow::Cow;

                vec![
                    $(
                        (
                            Cow::Borrowed(stringify!($field_name)),
                            {
                                let dummy: &$struct_name = unsafe { ::std::mem::transmute(0usize) };
                                let dummy_field = &dummy.$field_name;
                                let dummy_field: usize = unsafe { ::std::mem::transmute(dummy_field) };
                                dummy_field
                            },
                            {
                                fn attr_type_of_val<T: $crate::vertex::Attribute>(_: &T)
                                    -> $crate::vertex::AttributeType
                                {
                                    <T as $crate::vertex::Attribute>::get_type()
                                }
                                let dummy: &$struct_name = unsafe { ::std::mem::transmute(0usize) };
                                attr_type_of_val(&dummy.$field_name)
                            },
                        )
                    ),+
                ]
            }
        }
    );

    ($struct_name:ident, $($field_name:ident),+,) => (
        implement_vertex!($struct_name, $($field_name),+);
    );
}

/// Builds a program depending on the GLSL version supported by the backend.
///
/// This is implemented with successive calls to `is_glsl_version_supported()`.
///
/// ## Example
///
/// ```ignore       // TODO: no_run instead
/// # #[macro_use]
/// # extern crate glium;
/// # fn main() {
/// # let display: glium::Display = unsafe { std::mem::uninitialized() };
/// let program = program!(&display,
///     300 => {
///         vertex: r#"
///             #version 300
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 300
///
///             out vec4 color;
///             fn main() {
///                 color = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
///     110 => {
///         vertex: r#"
///             #version 110
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 110
///
///             fn main() {
///                 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
///     300 es => {
///         vertex: r#"
///             #version 110
///
///             fn main() {
///                 gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
///             }
///         "#,
///         fragment: r#"
///             #version 110
///
///             fn main() {
///                 gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
///             }
///         "#,
///     },
/// );
/// # }
/// ```
///
#[macro_export]
macro_rules! program {
    ($facade:expr,) => (
        panic!("No version found");     // TODO: handle better
    );

    ($facade:expr,,$($rest:tt)*) => (
        program!($facade,$($rest)*)
    );

    ($facade:expr, $num:tt => $($rest:tt)*) => (
        {
            let context = $crate::backend::Facade::get_context($facade);
            let version = program!(_parse_num_gl $num);
            program!(_inner, context, version, $($rest)*)
        }
    );

    ($facade:expr, $num:tt es => $($rest:tt)*) => (
        {
            let context = $crate::backend::Facade::get_context($facade);
            let version = program!(_parse_num_gles $num);
            program!(_inner, context, version, $($rest)*)
        }
    );

    (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+}$($rest:tt)*) => (
        if $context.is_glsl_version_supported(&$vers) {
            let _vertex_shader: &str = "";
            let _tessellation_control_shader: Option<&str> = None;
            let _tessellation_evaluation_shader: Option<&str> = None;
            let _geometry_shader: Option<&str> = None;
            let _fragment_shader: &str = "";

            $(
                program!(_program_ty $ty, $src, _vertex_shader, _tessellation_control_shader,
                         _tessellation_evaluation_shader, _geometry_shader, _fragment_shader);
            )+

            let input = $crate::program::ProgramCreationInput::SourceCode {
                vertex_shader: _vertex_shader,
                tessellation_control_shader: _tessellation_control_shader,
                tessellation_evaluation_shader: _tessellation_evaluation_shader,
                geometry_shader: _geometry_shader,
                fragment_shader: _fragment_shader,
                transform_feedback_varyings: None,
            };

            $crate::program::Program::new($context, input)

        } else {
            program!($context, $($rest)*)
        }
    );

    (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+,}$($rest:tt)*) => (
        program!(_inner, $context, $vers, {$($ty:$src),+} $($rest)*);
    );

    (_program_ty vertex, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $vs = $src;
    );

    (_program_ty tessellation_control, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $tcs = Some($src);
    );

    (_program_ty tessellation_evaluation, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $tes = Some($src);
    );

    (_program_ty geometry, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $gs = Some($src);
    );

    (_program_ty fragment, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident) => (
        let $fs = $src;
    );

    (_parse_num_gl $num:expr) => (
        if $num == 100 {
            $crate::Version($crate::Api::GlEs, 1, 0)
        } else {
            $crate::Version($crate::Api::Gl, $num / 100, ($num % 100) / 10)
        }
    );

    (_parse_num_gles $num:expr) => ($crate::Version($crate::Api::GlEs, $num / 100, ($num % 100) / 10));
}

#[cfg(test)]
mod tests {
    #[test]
    fn trailing_comma_impl_uniforms() {
        let u = uniform!{ a: 5, b: 6, };
    }

    #[test]
    fn trailing_comma_impl_vertex() {
        #[derive(Copy, Clone)]
        struct Foo {
            pos: [f32; 2],
        }

        implement_vertex!(Foo, pos,);
    }
    #[test]
    fn assert_no_error_macro() {
        struct Dummy;
        impl Dummy {
            fn assert_no_error(&self, _: Option<&str>) { }
        }

        assert_no_error!(Dummy);

        assert_no_error!(Dummy, "hi");

        assert_no_error!(Dummy, "{} {}", 1, 2);
    }
}
<|endoftext|>


<commit_before>use std::fs::{self, File};
use std::collections::HashMap;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use liquid::Value;
use walkdir::{WalkDir, DirEntry, WalkDirIterator};
use document::Document;
use error::{ErrorKind, Result};
use config::Config;
use chrono::{UTC, FixedOffset};
use chrono::offset::TimeZone;
use rss::{Channel, Rss};
use glob::Pattern;

fn ignore_filter(entry: &DirEntry, source: &Path, ignore: &[Pattern]) -> bool {
    if compare_paths(entry.path(), source) {
        return true;
    }
    let path = entry.path().strip_prefix(&source).unwrap_or(entry.path());
    let file_name = entry.file_name().to_str().unwrap_or("");
    if file_name.starts_with('_') || file_name.starts_with('.') {
        return false;
    }
    !ignore.iter().any(|p| p.matches_path(path))
}

fn compare_paths(a: &Path, b: &Path) -> bool {
    match (fs::canonicalize(a), fs::canonicalize(b)) {
        (Ok(p), Ok(p2)) => p == p2,
        _ => false,
    }
}

/// The primary build function that transforms a directory into a site
pub fn build(config: &Config) -> Result<()> {
    trace!("Build configuration: {:?}", config);

    // join("") makes sure path has a trailing slash
    let source = PathBuf::from(&config.source).join("");
    let source = source.as_path();
    let dest = PathBuf::from(&config.dest).join("");
    let dest = dest.as_path();

    let template_extensions: Vec<&OsStr> = config.template_extensions
        .iter()
        .map(OsStr::new)
        .collect();

    let layouts = source.join(&config.layouts);
    let layouts = layouts.as_path();
    let mut layouts_cache = HashMap::new();
    let posts_path = source.join(&config.posts);
    let posts_path = posts_path.as_path();

    debug!("Layouts directory: {:?}", layouts);
    debug!("Posts directory: {:?}", posts_path);
    debug!("Draft mode enabled: {}", config.include_drafts);
    if config.include_drafts {
        debug!("Draft directory: {:?}", config.drafts);
    }

    let mut documents = vec![];

    let walker = WalkDir::new(&source)
        .into_iter()
        .filter_entry(|e| {
            (ignore_filter(e, source, &config.ignore) || compare_paths(e.path(), posts_path)) &&
            !compare_paths(e.path(), dest)
        })
        .filter_map(|e| e.ok());

    for entry in walker {
        let entry_path = entry.path();
        let extension = &entry_path.extension().unwrap_or(OsStr::new(""));
        if template_extensions.contains(extension) {
            // if the document is in the posts folder it's considered a post
            let is_post =
                entry_path.parent().map(|p| compare_paths(p, posts_path)).unwrap_or(false);

            let new_path = entry_path.strip_prefix(source).expect("Entry not in source folder");

            let doc = try!(Document::parse(&entry_path, new_path, is_post, &config.post_path));
            if !doc.is_draft || config.include_drafts {
                documents.push(doc);
            }
        }
    }

    if config.include_drafts {
        let drafts = source.join(&config.drafts);
        let drafts = drafts.as_path();

        let walker = WalkDir::new(drafts)
            .into_iter()
            .filter_entry(|e| {
                (ignore_filter(e, source, &config.ignore) || compare_paths(e.path(), drafts)) &&
                !compare_paths(e.path(), dest)
            })
            .filter_map(|e| e.ok());

        for entry in walker {
            let entry_path = entry.path();
            let extension = &entry_path.extension().unwrap_or(OsStr::new(""));
            let new_path = posts_path
                .join(entry_path.strip_prefix(drafts).expect("Draft not in draft folder!"));
            let new_path = new_path.strip_prefix(source).expect("Entry not in source folder");
            if template_extensions.contains(extension) {
                let doc = try!(Document::parse(&entry_path, new_path, true, &config.post_path));
                documents.push(doc);
            }
        }
    }

    // January 1, 1970 0:00:00 UTC, the beginning of time
    let default_date = UTC.timestamp(0, 0).with_timezone(&FixedOffset::east(0));

    let (mut posts, documents): (Vec<Document>, Vec<Document>) = documents.into_iter()
        .partition(|x| x.is_post);

    // sort documents by date, if there's no date (none was provided or it couldn't be read) then
    // fall back to the default date
    posts.sort_by(|a, b| b.date.unwrap_or(default_date).cmp(&a.date.unwrap_or(default_date)));

    // collect all posts attributes to pass them to other posts for rendering
    let simple_posts_data: Vec<Value> = posts.iter()
        .map(|x| Value::Object(x.attributes.clone()))
        .collect();

    trace!("Generating posts");
    for mut post in &mut posts {
        trace!("Generating {}", post.path);

        let mut context = post.get_render_context(&simple_posts_data);

        try!(post.render_excerpt(&mut context, &source, &config.excerpt_separator));
        let post_html = try!(post.render(&mut context, &source, &layouts, &mut layouts_cache));
        try!(create_document_file(&post_html, &post.path, dest));
    }

    // check if we should create an RSS file and create it!
    if let &Some(ref path) = &config.rss {
        try!(create_rss(path, dest, &config, &posts));
    }

    // during post rendering additional attributes such as content were
    // added to posts. collect them so that non-post documents can access them
    let posts_data: Vec<Value> = posts.into_iter()
        .map(|x| Value::Object(x.attributes))
        .collect();

    trace!("Generating other documents");
    for mut doc in documents {
        trace!("Generating {}", doc.path);

        let mut context = doc.get_render_context(&posts_data);
        let doc_html = try!(doc.render(&mut context, &source, &layouts, &mut layouts_cache));
        try!(create_document_file(&doc_html, &doc.path, dest));
    }

    // copy all remaining files in the source to the destination
    if !compare_paths(source, dest) {
        info!("Copying remaining assets");
        let source_str = try!(source.to_str()
            .ok_or(format!("Cannot convert pathname {:?} to UTF-8", source)));

        let walker = WalkDir::new(&source)
            .into_iter()
            .filter_entry(|e| {
                ignore_filter(e, source, &config.ignore) &&
                !template_extensions.contains(&e.path()
                    .extension()
                    .unwrap_or(OsStr::new(""))) && !compare_paths(e.path(), dest)
            })
            .filter_map(|e| e.ok());

        for entry in walker {
            let entry_path = try!(entry.path()
                .to_str()
                .ok_or(format!("Cannot convert pathname {:?} to UTF-8", entry.path())));

            let relative = try!(entry_path.split(source_str)
                .last()
                .ok_or(format!("Empty path")));

            if try!(entry.metadata()).is_dir() {
                try!(fs::create_dir_all(&dest.join(relative)));
                debug!("Created new directory {:?}", dest.join(relative));
            } else {
                if let Some(parent) = Path::new(relative).parent() {
                    try!(fs::create_dir_all(&dest.join(parent)));
                }

                try!(fs::copy(entry.path(), &dest.join(relative))
                    .map_err(|e| format!("Could not copy {:?}: {}", entry.path(), e)));
                debug!("Copied {:?} to {:?}", entry.path(), dest.join(relative));
            }
        }
    }

    Ok(())
}

// creates a new RSS file with the contents of the site blog
fn create_rss(path: &str, dest: &Path, config: &Config, posts: &[Document]) -> Result<()> {
    match (&config.name, &config.description, &config.link) {
        // these three fields are mandatory in the RSS standard
        (&Some(ref name), &Some(ref description), &Some(ref link)) => {
            trace!("Generating RSS data");

            let items = posts.iter()
                .map(|doc| doc.to_rss(link))
                .collect();

            let channel = Channel {
                title: name.to_owned(),
                link: link.to_owned(),
                description: description.to_owned(),
                items: items,
                ..Default::default()
            };

            let rss = Rss(channel);
            let rss_string = rss.to_string();
            trace!("RSS data: {}", rss_string);

            let rss_path = dest.join(path);

            let mut rss_file = try!(File::create(&rss_path));
            try!(rss_file.write_all(&rss_string.into_bytes()));

            info!("Created RSS file at {}", rss_path.display());
            Ok(())
        }
        _ => Err(ErrorKind::ConfigFileMissingFields.into()),
    }
}

fn create_document_file<T: AsRef<Path>>(content: &str, path: T, dest: &Path) -> Result<()> {
    // construct target path
    let file_path_buf = dest.join(path);
    let file_path = file_path_buf.as_path();

    // create target directories if any exist
    if let Some(parent) = file_path.parent() {
        try!(fs::create_dir_all(parent)
            .map_err(|e| format!("Could not create {:?}: {}", parent, e)));
    }

    let mut file = try!(File::create(&file_path)
        .map_err(|e| format!("Could not create {:?}: {}", file_path, e)));

    try!(file.write_all(&content.as_bytes()));
    info!("Created {}", file_path.display());
    Ok(())
}
<commit_msg>Path only in build()<commit_after>use std::fs::{self, File};
use std::collections::HashMap;
use std::io::Write;
use std::path::Path;
use std::ffi::OsStr;
use liquid::Value;
use walkdir::{WalkDir, DirEntry, WalkDirIterator};
use document::Document;
use error::{ErrorKind, Result};
use config::Config;
use chrono::{UTC, FixedOffset};
use chrono::offset::TimeZone;
use rss::{Channel, Rss};
use glob::Pattern;

fn ignore_filter(entry: &DirEntry, source: &Path, ignore: &[Pattern]) -> bool {
    if compare_paths(entry.path(), source) {
        return true;
    }
    let path = entry.path().strip_prefix(&source).unwrap_or(entry.path());
    let file_name = entry.file_name().to_str().unwrap_or("");
    if file_name.starts_with('_') || file_name.starts_with('.') {
        return false;
    }
    !ignore.iter().any(|p| p.matches_path(path))
}

fn compare_paths(a: &Path, b: &Path) -> bool {
    match (fs::canonicalize(a), fs::canonicalize(b)) {
        (Ok(p), Ok(p2)) => p == p2,
        _ => false,
    }
}

/// The primary build function that transforms a directory into a site
pub fn build(config: &Config) -> Result<()> {
    trace!("Build configuration: {:?}", config);

    let source = Path::new(&config.source);
    let dest = Path::new(&config.dest);

    let template_extensions: Vec<&OsStr> = config.template_extensions
        .iter()
        .map(OsStr::new)
        .collect();

    let layouts = source.join(&config.layouts);
    let mut layouts_cache = HashMap::new();
    let posts_path = source.join(&config.posts);

    debug!("Layouts directory: {:?}", layouts);
    debug!("Posts directory: {:?}", posts_path);
    debug!("Draft mode enabled: {}", config.include_drafts);
    if config.include_drafts {
        debug!("Draft directory: {:?}", config.drafts);
    }

    let mut documents = vec![];

    let walker = WalkDir::new(&source)
        .into_iter()
        .filter_entry(|e| {
            (ignore_filter(e, &source, &config.ignore) || compare_paths(e.path(), &posts_path)) &&
            !compare_paths(e.path(), dest)
        })
        .filter_map(|e| e.ok());

    for entry in walker {
        let entry_path = entry.path();
        let extension = &entry_path.extension().unwrap_or(OsStr::new(""));
        if template_extensions.contains(extension) {
            // if the document is in the posts folder it's considered a post
            let is_post =
                entry_path.parent().map(|p| compare_paths(p, &posts_path)).unwrap_or(false);

            let new_path = entry_path.strip_prefix(source).expect("Entry not in source folder");

            let doc = try!(Document::parse(&entry_path, new_path, is_post, &config.post_path));
            if !doc.is_draft || config.include_drafts {
                documents.push(doc);
            }
        }
    }

    if config.include_drafts {
        let drafts = source.join(&config.drafts);

        let walker = WalkDir::new(&drafts)
            .into_iter()
            .filter_entry(|e| {
                (ignore_filter(e, source, &config.ignore) || compare_paths(e.path(), &drafts)) &&
                !compare_paths(e.path(), dest)
            })
            .filter_map(|e| e.ok());

        for entry in walker {
            let entry_path = entry.path();
            let extension = &entry_path.extension().unwrap_or(OsStr::new(""));
            let new_path = posts_path
                .join(entry_path.strip_prefix(&drafts).expect("Draft not in draft folder!"));
            let new_path = new_path.strip_prefix(source).expect("Entry not in source folder");
            if template_extensions.contains(extension) {
                let doc = try!(Document::parse(&entry_path, new_path, true, &config.post_path));
                documents.push(doc);
            }
        }
    }

    // January 1, 1970 0:00:00 UTC, the beginning of time
    let default_date = UTC.timestamp(0, 0).with_timezone(&FixedOffset::east(0));

    let (mut posts, documents): (Vec<Document>, Vec<Document>) = documents.into_iter()
        .partition(|x| x.is_post);

    // sort documents by date, if there's no date (none was provided or it couldn't be read) then
    // fall back to the default date
    posts.sort_by(|a, b| b.date.unwrap_or(default_date).cmp(&a.date.unwrap_or(default_date)));

    // collect all posts attributes to pass them to other posts for rendering
    let simple_posts_data: Vec<Value> = posts.iter()
        .map(|x| Value::Object(x.attributes.clone()))
        .collect();

    trace!("Generating posts");
    for mut post in &mut posts {
        trace!("Generating {}", post.path);

        let mut context = post.get_render_context(&simple_posts_data);

        try!(post.render_excerpt(&mut context, &source, &config.excerpt_separator));
        let post_html = try!(post.render(&mut context, &source, &layouts, &mut layouts_cache));
        try!(create_document_file(&post_html, &post.path, dest));
    }

    // check if we should create an RSS file and create it!
    if let &Some(ref path) = &config.rss {
        try!(create_rss(path, dest, &config, &posts));
    }

    // during post rendering additional attributes such as content were
    // added to posts. collect them so that non-post documents can access them
    let posts_data: Vec<Value> = posts.into_iter()
        .map(|x| Value::Object(x.attributes))
        .collect();

    trace!("Generating other documents");
    for mut doc in documents {
        trace!("Generating {}", doc.path);

        let mut context = doc.get_render_context(&posts_data);
        let doc_html = try!(doc.render(&mut context, &source, &layouts, &mut layouts_cache));
        try!(create_document_file(&doc_html, &doc.path, dest));
    }

    // copy all remaining files in the source to the destination
    if !compare_paths(source, dest) {
        info!("Copying remaining assets");
        let source_str = try!(source.to_str()
            .ok_or(format!("Cannot convert pathname {:?} to UTF-8", source)));

        let walker = WalkDir::new(&source)
            .into_iter()
            .filter_entry(|e| {
                ignore_filter(e, source, &config.ignore) &&
                !template_extensions.contains(&e.path()
                    .extension()
                    .unwrap_or(OsStr::new(""))) && !compare_paths(e.path(), dest)
            })
            .filter_map(|e| e.ok());

        for entry in walker {
            let entry_path = try!(entry.path()
                .to_str()
                .ok_or(format!("Cannot convert pathname {:?} to UTF-8", entry.path())));

            let relative = try!(entry_path.split(source_str)
                .last()
                .ok_or(format!("Empty path")));

            if try!(entry.metadata()).is_dir() {
                try!(fs::create_dir_all(&dest.join(relative)));
                debug!("Created new directory {:?}", dest.join(relative));
            } else {
                if let Some(parent) = Path::new(relative).parent() {
                    try!(fs::create_dir_all(&dest.join(parent)));
                }

                try!(fs::copy(entry.path(), &dest.join(relative))
                    .map_err(|e| format!("Could not copy {:?}: {}", entry.path(), e)));
                debug!("Copied {:?} to {:?}", entry.path(), dest.join(relative));
            }
        }
    }

    Ok(())
}

// creates a new RSS file with the contents of the site blog
fn create_rss(path: &str, dest: &Path, config: &Config, posts: &[Document]) -> Result<()> {
    match (&config.name, &config.description, &config.link) {
        // these three fields are mandatory in the RSS standard
        (&Some(ref name), &Some(ref description), &Some(ref link)) => {
            trace!("Generating RSS data");

            let items = posts.iter()
                .map(|doc| doc.to_rss(link))
                .collect();

            let channel = Channel {
                title: name.to_owned(),
                link: link.to_owned(),
                description: description.to_owned(),
                items: items,
                ..Default::default()
            };

            let rss = Rss(channel);
            let rss_string = rss.to_string();
            trace!("RSS data: {}", rss_string);

            let rss_path = dest.join(path);

            let mut rss_file = try!(File::create(&rss_path));
            try!(rss_file.write_all(&rss_string.into_bytes()));

            info!("Created RSS file at {}", rss_path.display());
            Ok(())
        }
        _ => Err(ErrorKind::ConfigFileMissingFields.into()),
    }
}

fn create_document_file<T: AsRef<Path>, R: AsRef<Path>>(content: &str,
                                                        path: T,
                                                        dest: R)
                                                        -> Result<()> {
    // construct target path
    let file_path = dest.as_ref().join(path);

    // create target directories if any exist
    if let Some(parent) = file_path.parent() {
        try!(fs::create_dir_all(parent)
            .map_err(|e| format!("Could not create {:?}: {}", parent, e)));
    }

    let mut file = try!(File::create(&file_path)
        .map_err(|e| format!("Could not create {:?}: {}", file_path, e)));

    try!(file.write_all(&content.as_bytes()));
    info!("Created {}", file_path.display());
    Ok(())
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::collections::VecDeque;
use std::cmp::Ordering::Equal;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};

struct WordVecBuilder {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(": ".fmt(fmt));
        self.count.fmt(fmt)
    }
}

impl WordVecBuilder {
    fn new(word: String, num_words: usize) -> WordVecBuilder {
        WordVecBuilder {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(mut self, word_freqs: &Vec<f32>) -> WordVec {
        let count = self.count as f32;
        for i in 0..word_freqs.len() {
            self.vec[i] = self.vec[i] / count;
        }

        WordVec {
            word: self.word,
            count: self.count,
            vec: self.vec,
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
        self.count += 1;
    }
}

impl WordVec {

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| (x*x - y*y).abs().sqrt())
                .fold(0.0, |x, y| x + y)
    }

}

impl<'a> Add for &'a WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: repeat(0.0).take(self.vec.len()).collect(),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] + other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub for &'a WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: repeat(0.0).take(self.vec.len()).collect(),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] - other.vec[i];
        }

        newvec
    }
}

pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_width: u32,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVecBuilder>,
}

pub struct WordAcceptor<'a> {
    window: VecDeque<String>,
    focus: usize,
    builder: &'a mut LanguageModelBuilder,
}

impl<'a> LanguageModelBuilder {
    pub fn new(words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVecBuilder::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_width: 21,
            words: words,
            word_vecs: word_vecs,
        }
    }

    pub fn build(self) -> LanguageModel {
        let total_words = self.word_vecs.iter().fold(0.0, |a, b| a + b.count as f32);
        let word_freqs = self.word_vecs.iter()
                                       .map(|v| v.count as f32 / total_words)
                                       .collect::<Vec<_>>();
        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs.into_iter()
                                     .map(|b| b.normalize(&word_freqs))
                                     .collect(),
        }
    }

    pub fn new_file(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            window: VecDeque::new(),
            focus: 0,
            builder: self,
        }
    }

    fn add_word(&mut self, from: &str, to: &str) {
        let from_idx = self.words[from];
        let from_vec = &mut self.word_vecs[from_idx];
        let to_idx = self.words[to];
        from_vec.inc(to_idx);
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: String) {
        let allow_word = self.builder.words.contains_key(&word);

        if allow_word {
            self.window.push_back(word);
            if (self.window.len() > 21) {
                self.window.pop_front();
            }
            if (self.window.len() == 21) {
                for i in (0..21).filter(|a| *a != 10) {
                    self.builder.add_word(&self.window[10], &self.window[i]);
                }
            }
        }
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        if let Some(i) = self.words.get(word) {
            Some(&self.word_vecs[*i])
        } else {
            None
        }
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w|
            if w.word != word.word { Some((w.distance(word), w)) } else { None }
        ).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Equal));
        vec_refs.into_iter().map(|x| x.1).collect()
    }
}<commit_msg>Fix word count<commit_after>use std::ops::{Add, Sub};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::collections::VecDeque;
use std::cmp::Ordering::Equal;
use std::iter::repeat;
use std::fmt::{Debug, Formatter, Error};

struct WordVecBuilder {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Vec<f32>,
}

impl Debug for WordVec {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        try!(self.word.fmt(fmt));
        try!(": ".fmt(fmt));
        self.count.fmt(fmt)
    }
}

impl WordVecBuilder {
    fn new(word: String, num_words: usize) -> WordVecBuilder {
        WordVecBuilder {
            word: word,
            count: 0,
            vec: repeat(0.0).take(num_words).collect(),
        }
    }

    fn normalize(mut self, word_freqs: &Vec<f32>) -> WordVec {
        let count = self.count as f32;
        for i in 0..word_freqs.len() {
            self.vec[i] = self.vec[i] / count;
        }

        WordVec {
            word: self.word,
            count: self.count,
            vec: self.vec,
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }
}

impl WordVec {

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| (x*x - y*y).abs().sqrt())
                .fold(0.0, |x, y| x + y)
    }

}

impl<'a> Add for &'a WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: repeat(0.0).take(self.vec.len()).collect(),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] + other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub for &'a WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        debug_assert!(self.vec.len() == other.vec.len());
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: repeat(0.0).take(self.vec.len()).collect(),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] - other.vec[i];
        }

        newvec
    }
}

pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    window_width: u32,
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVecBuilder>,
}

pub struct WordAcceptor<'a> {
    window: VecDeque<String>,
    focus: usize,
    builder: &'a mut LanguageModelBuilder,
}

impl<'a> LanguageModelBuilder {
    pub fn new(words: Vec<String>) -> LanguageModelBuilder {

        let word_vecs = words.iter()
                             .map(|s| WordVecBuilder::new(s.clone(), words.len()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            window_width: 21,
            words: words,
            word_vecs: word_vecs,
        }
    }

    pub fn build(self) -> LanguageModel {
        let total_words = self.word_vecs.iter().fold(0.0, |a, b| a + b.count as f32);
        let word_freqs = self.word_vecs.iter()
                                       .map(|v| v.count as f32 / total_words)
                                       .collect::<Vec<_>>();
        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs.into_iter()
                                     .map(|b| b.normalize(&word_freqs))
                                     .collect(),
        }
    }

    pub fn new_file(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            window: VecDeque::new(),
            focus: 0,
            builder: self,
        }
    }

    fn get_vec(&mut self, word: &str) -> &mut WordVecBuilder {
        let i = self.words[word];
        &mut self.word_vecs[i]
    }

    fn add_word(&mut self, from: &str, to: &str) {
        let to_idx = self.words[to];
        let from_vec = self.get_vec(from);
        from_vec.inc(to_idx);
    }

    fn word_seen(&mut self, word: &str) {
        self.get_vec(word).count += 1;
    }
}

impl<'a> WordAcceptor<'a> {
    pub fn add_word(&mut self, word: String) {
        let allow_word = self.builder.words.contains_key(&word);

        if allow_word {
            self.window.push_back(word);
            if (self.window.len() > 21) {
                self.window.pop_front();
            }
            if (self.window.len() == 21) {
                self.builder.word_seen(&self.window[10]);
                for i in (0..21).filter(|a| *a != 10) {
                    self.builder.add_word(&self.window[10], &self.window[i]);
                }
            }
        }
    }
}

impl LanguageModel {
    pub fn get(&self, word: &str) -> Option<&WordVec> {
        if let Some(i) = self.words.get(word) {
            Some(&self.word_vecs[*i])
        } else {
            None
        }
    }

    pub fn nearest_words(&self, word: &WordVec) -> Vec<&WordVec> {
        let mut vec_refs = self.word_vecs.iter().filter_map(|w|
            if w.word != word.word { Some((w.distance(word), w)) } else { None }
        ).collect::<Vec<_>>();
        vec_refs.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Equal));
        vec_refs.into_iter().map(|x| x.1).collect()
    }
}<|endoftext|>


<commit_before>pub const TILE_SIZE: u32 = 40;
pub const DEF_WINDOW_WIDTH: u32 = 800;
pub const DEF_WINDOW_HEIGHT: u32 = 600;

pub const WALL_LAYER_IND: i32 = 1;
pub const FLOOR_LAYER_IND: i32 = 2;

pub const PLAYER_TEXTURE_Y: u32 = 0;
pub const WALL_TEXTURE_Y: u32 = PLAYER_TEXTURE_Y + TILE_SIZE;
pub const FLOOR_TEXTURE_Y: u32 = WALL_TEXTURE_Y + TILE_SIZE;
pub const ENEMY_TEXTURE_Y: u32 = FLOOR_TEXTURE_Y + TILE_SIZE;

#[derive(Debug)]
pub enum TileType {
    None,
    Wall(u32),
    Floor(u32),
}

impl Default for TileType {
    fn default() -> TileType {
        TileType::None
    }
}

pub fn global_pos(tile: (i32, i32)) -> (i32, i32) {
    (tile.0*(TILE_SIZE) as i32,
     tile.1*(TILE_SIZE) as i32)
}

pub fn get_fov(tiles: &::std::collections::HashMap<(i32, i32), &::tile_engine::Tile<TileType>>, start_pos: (i32, i32)) -> ::std::collections::HashSet<(i32, i32)> {
    use std::collections::{HashSet, VecDeque};
    enum FovType {
        EastAxis,
        NorthEastQuadrant,
        NorthAxis,
        NorthWestQuadrant,
        WestAxis,
        SouthWestQuadrant,
        SouthAxis,
        SouthEastQuadrant,
    }

    let mut lighted = HashSet::<(i32, i32)>::new();
    let mut queue = VecDeque::<(i32, i32, FovType)>::new();
    lighted.insert(global_pos(start_pos));
    let mut shadows = Vec::<(f64, f64)>::new();
    queue.push_back((start_pos.0 + 1, start_pos.1, FovType::EastAxis));
    queue.push_back((start_pos.0, start_pos.1 - 1, FovType::NorthAxis));
    queue.push_back((start_pos.0 - 1, start_pos.1, FovType::WestAxis));
    queue.push_back((start_pos.0, start_pos.1 + 1, FovType::SouthAxis));
    while !queue.is_empty() {
        let mut pos = queue.pop_front().unwrap();
        if !tiles.contains_key(&global_pos((pos.0, pos.1))) {
            // TODO: count shadow
        }
        // TODO: check shadow
        lighted.insert(global_pos((pos.0, pos.1)));
        match pos.2 {
            FovType::EastAxis => {
                queue.push_back((pos.0, pos.1 + 1, FovType::SouthEastQuadrant));
                queue.push_back((pos.0 + 1, pos.1, FovType::EastAxis));
                queue.push_back((pos.0, pos.1 - 1, FovType::NorthEastQuadrant));
            },
            FovType::NorthEastQuadrant => {
                queue.push_back((pos.0 + 1, pos.1, FovType::NorthEastQuadrant));
                queue.push_back((pos.0, pos.1 - 1, FovType::NorthEastQuadrant));
            },
            FovType::NorthAxis => {
                queue.push_back((pos.0 + 1, pos.1, FovType::NorthEastQuadrant));
                queue.push_back((pos.0, pos.1 - 1, FovType::NorthAxis));
                queue.push_back((pos.0 - 1, pos.1, FovType::NorthWestQuadrant));
            },
            FovType::NorthWestQuadrant => {
                queue.push_back((pos.0, pos.1 - 1, FovType::NorthWestQuadrant));
                queue.push_back((pos.0 - 1, pos.1, FovType::NorthWestQuadrant));
            },
            FovType::WestAxis => {
                queue.push_back((pos.0, pos.1 - 1, FovType::NorthWestQuadrant));
                queue.push_back((pos.0 - 1, pos.1, FovType::WestAxis));
                queue.push_back((pos.0, pos.1 + 1, FovType::SouthWestQuadrant));
            },
            FovType::SouthWestQuadrant => {
                queue.push_back((pos.0 - 1, pos.1, FovType::SouthWestQuadrant));
                queue.push_back((pos.0, pos.1 + 1, FovType::SouthWestQuadrant));
            },
            FovType::SouthAxis => {
                queue.push_back((pos.0 - 1, pos.1, FovType::SouthWestQuadrant));
                queue.push_back((pos.0, pos.1 + 1, FovType::SouthAxis));
                queue.push_back((pos.0 + 1, pos.1, FovType::SouthEastQuadrant));
            }
            FovType::SouthEastQuadrant => {
                queue.push_back((pos.0, pos.1 + 1, FovType::SouthEastQuadrant));
                queue.push_back((pos.0 + 1, pos.1, FovType::SouthEastQuadrant));
            },
        }
    }
    lighted
}
<commit_msg>optimized BFS<commit_after>pub const TILE_SIZE: u32 = 40;
pub const DEF_WINDOW_WIDTH: u32 = 800;
pub const DEF_WINDOW_HEIGHT: u32 = 600;

pub const WALL_LAYER_IND: i32 = 1;
pub const FLOOR_LAYER_IND: i32 = 2;

pub const PLAYER_TEXTURE_Y: u32 = 0;
pub const WALL_TEXTURE_Y: u32 = PLAYER_TEXTURE_Y + TILE_SIZE;
pub const FLOOR_TEXTURE_Y: u32 = WALL_TEXTURE_Y + TILE_SIZE;
pub const ENEMY_TEXTURE_Y: u32 = FLOOR_TEXTURE_Y + TILE_SIZE;

#[derive(Debug)]
pub enum TileType {
    None,
    Wall(u32),
    Floor(u32),
}

impl Default for TileType {
    fn default() -> TileType {
        TileType::None
    }
}

pub fn global_pos(tile: (i32, i32)) -> (i32, i32) {
    (tile.0*(TILE_SIZE) as i32,
     tile.1*(TILE_SIZE) as i32)
}

pub fn get_fov(tiles: &::std::collections::HashMap<(i32, i32), &::tile_engine::Tile<TileType>>, start_pos: (i32, i32)) -> ::std::collections::HashSet<(i32, i32)> {
    use std::collections::{HashSet, VecDeque};
    enum FovType {
        EastAxis,
        NorthEastQuadrant,
        NorthAxis,
        NorthWestQuadrant,
        WestAxis,
        SouthWestQuadrant,
        SouthAxis,
        SouthEastQuadrant,
    }

    let mut lighted = HashSet::<(i32, i32)>::new();
    let mut queued = HashSet::<(i32, i32)>::new();
    let mut queue = VecDeque::<(i32, i32, FovType)>::new();
    let mut push_queue = |q: &mut VecDeque<(i32, i32, FovType)>,
                          pos: (i32, i32, FovType),
                          queued: &mut HashSet<(i32, i32)> | {
        if queued.contains(&(pos.0, pos.1)) {
            return;
        }
        queued.insert((pos.0, pos.1));
        q.push_back(pos);
    };
    lighted.insert(global_pos(start_pos));
    let mut shadows = Vec::<(f64, f64)>::new();
    push_queue(&mut queue, (start_pos.0 + 1, start_pos.1, FovType::EastAxis), &mut queued);
    push_queue(&mut queue, (start_pos.0, start_pos.1 - 1, FovType::NorthAxis), &mut queued);
    push_queue(&mut queue, (start_pos.0 - 1, start_pos.1, FovType::WestAxis), &mut queued);
    push_queue(&mut queue, (start_pos.0, start_pos.1 + 1, FovType::SouthAxis), &mut queued);
    while !queue.is_empty() {
        let mut pos = queue.pop_front().unwrap();
        if !tiles.contains_key(&global_pos((pos.0, pos.1))) {
            // TODO: count shadow
            continue;
        }
        // TODO: check shadow
        lighted.insert(global_pos((pos.0, pos.1)));
        match pos.2 {
            FovType::EastAxis => {
                push_queue(&mut queue, (pos.0, pos.1 + 1, FovType::SouthEastQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0 + 1, pos.1, FovType::EastAxis), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 - 1, FovType::NorthEastQuadrant), &mut queued);
            },
            FovType::NorthEastQuadrant => {
                push_queue(&mut queue, (pos.0 + 1, pos.1, FovType::NorthEastQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 - 1, FovType::NorthEastQuadrant), &mut queued);
            },
            FovType::NorthAxis => {
                push_queue(&mut queue, (pos.0 + 1, pos.1, FovType::NorthEastQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 - 1, FovType::NorthAxis), &mut queued);
                push_queue(&mut queue, (pos.0 - 1, pos.1, FovType::NorthWestQuadrant), &mut queued);
            },
            FovType::NorthWestQuadrant => {
                push_queue(&mut queue, (pos.0, pos.1 - 1, FovType::NorthWestQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0 - 1, pos.1, FovType::NorthWestQuadrant), &mut queued);
            },
            FovType::WestAxis => {
                push_queue(&mut queue, (pos.0, pos.1 - 1, FovType::NorthWestQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0 - 1, pos.1, FovType::WestAxis), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 + 1, FovType::SouthWestQuadrant), &mut queued);
            },
            FovType::SouthWestQuadrant => {
                push_queue(&mut queue, (pos.0 - 1, pos.1, FovType::SouthWestQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 + 1, FovType::SouthWestQuadrant), &mut queued);
            },
            FovType::SouthAxis => {
                push_queue(&mut queue, (pos.0 - 1, pos.1, FovType::SouthWestQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0, pos.1 + 1, FovType::SouthAxis), &mut queued);
                push_queue(&mut queue, (pos.0 + 1, pos.1, FovType::SouthEastQuadrant), &mut queued);
            }
            FovType::SouthEastQuadrant => {
                push_queue(&mut queue, (pos.0, pos.1 + 1, FovType::SouthEastQuadrant), &mut queued);
                push_queue(&mut queue, (pos.0 + 1, pos.1, FovType::SouthEastQuadrant), &mut queued);
            },
        }
    }
    lighted
}
<|endoftext|>


<commit_before>use std;

#[derive(Clone, Debug)]
pub struct AppInfo {
    name: String,
    author: String,
    safe_name: String,
    safe_author: String,
}

impl AppInfo {
    pub fn new(name: &str, author: &str) -> Self {
        AppInfo {
            name: name.into(),
            author: author.into(),
            safe_name: name.into(), // TODO
            safe_author: author.into(), // TODO
        }
    }
    pub fn safe_name(&self) -> &str {
        &self.safe_name
    }
    pub fn safe_author(&self) -> &str {
        &self.safe_author
    }
    pub fn get_name(&self) -> &str {
        &self.name
    }
    pub fn get_author(&self) -> &str {
        &self.author
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum AppDirType {
    UserConfig,
    UserData,
    UserCache,
    SharedData,
    SharedConfig,
}

impl AppDirType {
    pub fn is_shared(&self) -> bool {
        use AppDirType::*;
        match *self {
            SharedData | SharedConfig => true,
            _ => false,
        }
    }
}

pub enum AppDirError {
    Io(std::io::Error),
    // NotFound(PathBuf),
    NotSupported,
}

impl From<std::io::Error> for AppDirError {
    fn from(e: std::io::Error) -> Self {
        AppDirError::Io(e)
    }
}

pub type AppDirResult<T> = Result<T, AppDirError>;<commit_msg>Derive debug for AppDirError The test couldn't be built since the format couldn't use {:?} on AppDirError. One might also consider rewriting the test instead.<commit_after>use std;

#[derive(Clone, Debug)]
pub struct AppInfo {
    name: String,
    author: String,
    safe_name: String,
    safe_author: String,
}

impl AppInfo {
    pub fn new(name: &str, author: &str) -> Self {
        AppInfo {
            name: name.into(),
            author: author.into(),
            safe_name: name.into(), // TODO
            safe_author: author.into(), // TODO
        }
    }
    pub fn safe_name(&self) -> &str {
        &self.safe_name
    }
    pub fn safe_author(&self) -> &str {
        &self.safe_author
    }
    pub fn get_name(&self) -> &str {
        &self.name
    }
    pub fn get_author(&self) -> &str {
        &self.author
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum AppDirType {
    UserConfig,
    UserData,
    UserCache,
    SharedData,
    SharedConfig,
}

impl AppDirType {
    pub fn is_shared(&self) -> bool {
        use AppDirType::*;
        match *self {
            SharedData | SharedConfig => true,
            _ => false,
        }
    }
}

#[derive(Debug)]
pub enum AppDirError {
    Io(std::io::Error),
    // NotFound(PathBuf),
    NotSupported,
}

impl From<std::io::Error> for AppDirError {
    fn from(e: std::io::Error) -> Self {
        AppDirError::Io(e)
    }
}

pub type AppDirResult<T> = Result<T, AppDirError>;<|endoftext|>