<commit_before>#![feature(plugin_registrar)]
#![feature(quote)]
#![feature(phase)]

#[phase(plugin)]
extern crate regex_macros;

extern crate regex;
extern crate rustc;
extern crate syntax;

use std::io::Reader;
use std::io::process::Command;
use std::path::Path;
use syntax::parse::token;
use syntax::ast::{ TokenTree };
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacItem};
use syntax::codemap::Span;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("cmake", macro_handler);
}

// main handler for the macro
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult> {
    // getting the arguments from the macro
    let (srcPath, libname) = match parse_macro_arguments(ecx, token_tree) {
        Ok(t) => t,
        Err(msg) => {
            ecx.span_err(span, msg.as_slice());
            return DummyResult::any(span)
        }
    };

    // absolute path
    let srcPath = ::std::os::make_absolute(&srcPath);

    // creating the build directory
    let buildDirectory = srcPath.join("cmake-build");

    // creating the directory if it doesn't exist
    if !buildDirectory.exists() {
        match ::std::io::fs::mkdir_recursive(&buildDirectory, ::std::io::UserRWX) {
            Ok(_) => (),
            Err(err) => {
                ecx.span_err(span, format!("{}", err).as_slice());
                return DummyResult::any(span)
            }
        }
    }

    // getting the libraries output directory
    let outputDir = match ::std::os::homedir() {
        Some(d) => d.join(".cmake-rs-builds").join(ecx.ecfg.crate_id.name.clone()),
        None => {
            ecx.span_err(span, format!("unable to get your home directory").as_slice());
            return DummyResult::any(span)
        }
    };
    if !outputDir.exists() {
        match ::std::io::fs::mkdir_recursive(&outputDir, ::std::io::UserRWX) {
            Ok(_) => (),
            Err(err) => {
                ecx.span_err(span, format!("{}", err).as_slice());
                return DummyResult::any(span)
            }
        }
    }

    // invoking CMake
    let cmakeProcess = match Command::new("cmake")
                                .cwd(&buildDirectory)
                                .arg(format!("-DCMAKE_LIBRARY_OUTPUT_DIRECTORY:dir={}", outputDir.display()))
                                .arg(format!("-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY:dir={}", outputDir.display()))
                                .arg(format!("{}", srcPath.display()))
                                .spawn()
    {
        Ok(p) => p,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };

    // the content of stderr is converted into compilation errors
    match cmakeProcess.stderr.clone() {
        Some(mut stderr) => match stderr.read_to_str() {
            Ok(s) => if s.len() >= 1 {
                ecx.span_err(span, s.as_slice());
                return DummyResult::any(span)
            },
            Err(err) => ecx.span_err(span, format!("{}", err).as_slice())
        },
        None => ecx.span_warn(span, "could not open stderr pipe to cmake")
    }

    // invoking make
    let mut makeCommand = Command::new("make");
    makeCommand.cwd(&buildDirectory);
    match &libname { &Some(ref l) => { makeCommand.arg(l.as_slice()); }, _ => () };
    let makeProcess = match makeCommand.spawn() {
        Ok(p) => p,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };

    // the content of stderr is converted into compilation errors
    match makeProcess.stderr.clone() {
        Some(mut stderr) => match stderr.read_to_str() {
            Ok(s) => if s.len() >= 1 {
                ecx.span_err(span, s.as_slice());
                return DummyResult::any(span)
            },
            Err(err) => ecx.span_err(span, format!("{}", err).as_slice())
        },
        None => ecx.span_warn(span, "could not open stderr pipe to cmake")
    }

    // outputting the library name
    {
        let link = match &libname {
            &Some(ref l) => format!("#[link_args = \"-L {}\"]\n#[link(name=\"{}\")]\nextern {{}}", outputDir.display(), l),
            &None => format!("")
        };
        str_to_item(ecx, link.as_slice())
    }
}

fn str_to_item(ecx: &mut ExtCtxt, content: &str) -> Box<MacResult> {
    let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(), "".to_string(), content.to_string());

    match parser.parse_item_with_outer_attributes() {
        None => fail!(),
        Some(i) => MacItem::new(i)
    }
}

// converts an Expr into a String if possible
fn expr_to_literal(expr: ::std::gc::Gc<::syntax::ast::Expr>)
    -> Result<String, String>
{
    Ok(match expr.node {
        syntax::ast::ExprLit(lit) => {
            match lit.node {
                syntax::ast::LitStr(ref s, _) => s.to_str(),
                _ => return Err(format!("expected string literal but got `{}`", syntax::print::pprust::lit_to_str(lit)))
            }
        }
        _ => return Err(format!("expected string literal but got `{}`", syntax::print::pprust::expr_to_str(expr)))
    })
}

// tries to obtain the macro arguments from the token tree
fn parse_macro_arguments(cx: &mut ExtCtxt, tts: &[syntax::ast::TokenTree])
    -> Result<(Path, Option<String>), String>
{
    let mut parser = ::syntax::parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), Vec::from_slice(tts));

    let path = match Path::new_opt(try!(expr_to_literal(cx.expand_expr(parser.parse_expr())))) {
        Some(p) => p,
        None => return Err(format!("the path is not utf-8!"))
    };

    let libname = if parser.eat(&token::COMMA) {
        Some(try!(expr_to_literal(cx.expand_expr(parser.parse_expr()))))
    } else { None };

    if !parser.eat(&token::EOF) {
        return Err("too many arguments".to_string());
    }

    Ok((path, libname))
}
<commit_msg>Now working on windows<commit_after>#![feature(plugin_registrar)]
#![feature(quote)]
#![feature(phase)]

#[phase(plugin)]
extern crate regex_macros;

extern crate regex;
extern crate rustc;
extern crate syntax;

use std::io::Reader;
use std::io::process::Command;
use std::path::Path;
use syntax::parse::token;
use syntax::ast::{ TokenTree };
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult, MacItem};
use syntax::codemap::Span;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("cmake", macro_handler);
}

// main handler for the macro
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult> {
    // getting the arguments from the macro
    let (srcPath, libname) = match parse_macro_arguments(ecx, token_tree) {
        Ok(t) => t,
        Err(msg) => {
            ecx.span_err(span, msg.as_slice());
            return DummyResult::any(span)
        }
    };

    // absolute path
    let srcPath = ::std::os::make_absolute(&srcPath);

    // creating the build directory
    let buildDirectory = srcPath.join("cmake-build");

    // creating the directory if it doesn't exist
    if !buildDirectory.exists() {
        match ::std::io::fs::mkdir_recursive(&buildDirectory, ::std::io::UserRWX) {
            Ok(_) => (),
            Err(err) => {
                ecx.span_err(span, format!("{}", err).as_slice());
                return DummyResult::any(span)
            }
        }
    }

    // getting the libraries output directory
    let outputDir = srcPath.join("cmake-build-result");
    if !outputDir.exists() {
        match ::std::io::fs::mkdir_recursive(&outputDir, ::std::io::UserRWX) {
            Ok(_) => (),
            Err(err) => {
                ecx.span_err(span, format!("{}", err).as_slice());
                return DummyResult::any(span)
            }
        }
    }

    // getting the generator
    let (generatorCmake, generatorExec) = if cfg!(windows) {
        ("MinGW Makefiles", "mingw32-make")
    } else {
        ("Makefiles", "make")
    };

    // invoking CMake
    let cmakeProcess = match Command::new("cmake")
                                .cwd(&buildDirectory)
                                .args(&["-G", generatorCmake])
                                .arg(format!("-DCMAKE_LIBRARY_OUTPUT_DIRECTORY:dir={}", outputDir.display()))
                                .arg(format!("-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY:dir={}", outputDir.display()))
                                .arg(format!("{}", srcPath.display()))
                                .spawn()
    {
        Ok(p) => p,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };

    // the content of stderr is converted into compilation errors
    match cmakeProcess.stderr.clone() {
        Some(mut stderr) => match stderr.read_to_str() {
            Ok(s) => if s.len() >= 1 {
                ecx.span_err(span, s.as_slice());
                return DummyResult::any(span)
            },
            Err(err) => ecx.span_err(span, format!("{}", err).as_slice())
        },
        None => ecx.span_warn(span, "could not open stderr pipe to cmake")
    }

    // invoking make
    let mut makeCommand = Command::new(generatorExec);
    makeCommand.cwd(&buildDirectory);
    match &libname { &Some(ref l) => { makeCommand.arg(l.as_slice()); }, _ => () };
    let makeProcess = match makeCommand.spawn() {
        Ok(p) => p,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };

    // the content of stderr is converted into compilation errors
    match makeProcess.stderr.clone() {
        Some(mut stderr) => match stderr.read_to_str() {
            Ok(s) => if s.len() >= 1 {
                ecx.span_err(span, s.as_slice());
                return DummyResult::any(span)
            },
            Err(err) => ecx.span_err(span, format!("{}", err).as_slice())
        },
        None => ecx.span_warn(span, "could not open stderr pipe to cmake")
    }

    // outputting the library name
    {
        let link = match &libname {
            &Some(ref l) => format!("#[link_args = \"-L {}\"]\n#[link(name=\"{}\")]\nextern {{}}", outputDir.display().as_maybe_owned().escape_default().as_slice(), l),
            &None => format!("#[link_args = \"-L {}\"]\nextern {{}}", outputDir.display().as_maybe_owned().escape_default().as_slice())
        };
        str_to_item(ecx, link.as_slice())
    }
}

fn str_to_item(ecx: &mut ExtCtxt, content: &str) -> Box<MacResult> {
    let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(), "".to_string(), content.to_string());

    match parser.parse_item_with_outer_attributes() {
        None => fail!("unable to parse library output into items"),
        Some(i) => MacItem::new(i)
    }
}

// converts an Expr into a String if possible
fn expr_to_literal(expr: ::std::gc::Gc<::syntax::ast::Expr>)
    -> Result<String, String>
{
    Ok(match expr.node {
        syntax::ast::ExprLit(lit) => {
            match lit.node {
                syntax::ast::LitStr(ref s, _) => s.to_str(),
                _ => return Err(format!("expected string literal but got `{}`", syntax::print::pprust::lit_to_str(lit)))
            }
        }
        _ => return Err(format!("expected string literal but got `{}`", syntax::print::pprust::expr_to_str(expr)))
    })
}

// tries to obtain the macro arguments from the token tree
fn parse_macro_arguments(cx: &mut ExtCtxt, tts: &[syntax::ast::TokenTree])
    -> Result<(Path, Option<String>), String>
{
    let mut parser = ::syntax::parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), Vec::from_slice(tts));

    let path = match Path::new_opt(try!(expr_to_literal(cx.expand_expr(parser.parse_expr())))) {
        Some(p) => p,
        None => return Err(format!("the path is not utf-8!"))
    };

    let libname = if parser.eat(&token::COMMA) {
        Some(try!(expr_to_literal(cx.expand_expr(parser.parse_expr()))))
    } else { None };

    if !parser.eat(&token::EOF) {
        return Err("too many arguments".to_string());
    }

    Ok((path, libname))
}
<|endoftext|>


<commit_before>use std::io;
use std::vec::Vec;

use byteorder::{ByteOrder, BigEndian};
use protobuf::{Message, MessageStatic};

use raft::errors::{Result, Error};

const MSG_HEADER_LEN: usize = 16;
const MSG_MAGIC: u16 = 0xdaf4;
const MSG_VERSION_V1: u16 = 1;

// Encodes message with message ID and protobuf body.
// Message contains header + payload.
// Header is 16 bytes, format:
//  | 0xdaf4 (2 bytes)| 0x01 (version 2 bytes)| msg_len (4 bytes| msg_id (8 bytes)|, all use bigendian.
// Payload is a protobuf message.
pub fn encode_message<T: io::Write, M: Message>(w: &mut T, msg_id: u64, msg: &M) -> Result<()> {
    // Create a 16 bytes header and write it.
    let mut buf = vec!(0; MSG_HEADER_LEN);
    BigEndian::write_u16(&mut buf[0..2], MSG_MAGIC);
    BigEndian::write_u16(&mut buf[2..4], MSG_VERSION_V1);
    BigEndian::write_u64(&mut buf[8..16], msg_id);

    try!(msg.write_to_vec(&mut buf));
    // Set payload length here
    let payload_len = (buf.len() - MSG_HEADER_LEN) as u32;
    BigEndian::write_u32(&mut buf[4..8], payload_len);

    try!(w.write(&buf));
    Ok(())
}

// Decodes message with above encoded format, returns message ID.
pub fn decode_message<T: io::Read, M: Message>(r: &mut T, m: &mut M) -> Result<u64> {
    // First read 16 bytes header
    let mut header = [0; MSG_HEADER_LEN];
    // TODO: check exact read bytes number.
    try!(r.read(&mut header));

    let magic = BigEndian::read_u16(&header[0..2]);
    if MSG_MAGIC != magic {
        // TODO: use our own error.
        return Err(Error::Other(format!("invalid magic {}, not {}", magic, MSG_MAGIC)));
    }

    let version = BigEndian::read_u16(&header[2..4]);
    if MSG_VERSION_V1 != version {
        // TODO: use our own error.
        return Err(Error::Other(format!("unsupported version {}, we need {} now",
                                        version,
                                        MSG_VERSION_V1)));
    }

    let payload_len = BigEndian::read_u32(&header[4..8]) as usize;
    // TODO: check max payload

    let msg_id: u64 = BigEndian::read_u64(&header[8..16]);
    let mut payload = vec![0;payload_len];

    let n = try!(r.read(&mut payload));
    try!(m.merge_from_bytes(&payload));

    Ok(msg_id)
}

#[cfg(test)]
mod tests {
    use bytes::{Buf, ByteBuf, MutByteBuf};

    use raft::codec::{encode_message, decode_message};
    use raft::raftpb::{Message, MessageType};
    use raft::errors::{Result, Error};

    #[test]
    fn test_codec() {
        let mut m1 = Message::new();
        m1.set_field_type(MessageType::MsgBeat);

        let mut w = ByteBuf::mut_with_capacity(64);
        assert_eq!(encode_message(&mut w, 1, &m1).is_ok(), true);

        let mut m2 = Message::new();
        assert_eq!(decode_message(&mut w.flip(), &mut m2).unwrap(), 1);
        assert_eq!(m1, m2);
    }
}
<commit_msg>raft: Address comment.<commit_after>use std::io;
use std::vec::Vec;

use byteorder::{ByteOrder, BigEndian};
use protobuf::{Message, MessageStatic};

use raft::errors::{Result, Error};

const MSG_HEADER_LEN: usize = 16;
const MSG_MAGIC: u16 = 0xdaf4;
const MSG_VERSION_V1: u16 = 1;

// Encodes message with message ID and protobuf body.
// Message contains header + payload.
// Header is 16 bytes, format:
//  | 0xdaf4 (2 bytes)| 0x01 (version 2 bytes)| msg_len (4 bytes) | msg_id (8 bytes)|, all use bigendian.
// Payload is a protobuf message.
pub fn encode_message<T: io::Write, M: Message>(w: &mut T, msg_id: u64, msg: &M) -> Result<()> {
    // Create a 16 bytes header and write it.
    let mut buf = vec!(0; MSG_HEADER_LEN);
    BigEndian::write_u16(&mut buf[0..2], MSG_MAGIC);
    BigEndian::write_u16(&mut buf[2..4], MSG_VERSION_V1);
    BigEndian::write_u64(&mut buf[8..16], msg_id);

    try!(msg.write_to_vec(&mut buf));

    // Set payload length here
    let payload_len = (buf.len() - MSG_HEADER_LEN) as u32;
    BigEndian::write_u32(&mut buf[4..8], payload_len);

    try!(w.write(&buf));

    Ok(())
}

// Decodes message with above encoded format, returns message ID.
pub fn decode_message<T: io::Read, M: Message>(r: &mut T, m: &mut M) -> Result<u64> {
    // First read 16 bytes header
    let mut header = [0; MSG_HEADER_LEN];
    // TODO: check exact read bytes number.
    try!(r.read(&mut header));

    let magic = BigEndian::read_u16(&header[0..2]);
    if MSG_MAGIC != magic {
        return Err(Error::Other(format!("invalid magic {}, not {}", magic, MSG_MAGIC)));
    }

    let version = BigEndian::read_u16(&header[2..4]);
    if MSG_VERSION_V1 != version {
        return Err(Error::Other(format!("unsupported version {}, we need {} now",
                                        version,
                                        MSG_VERSION_V1)));
    }

    let payload_len = BigEndian::read_u32(&header[4..8]) as usize;
    // TODO: check max payload

    let msg_id: u64 = BigEndian::read_u64(&header[8..16]);
    let mut payload = vec![0;payload_len];

    let n = try!(r.read(&mut payload));
    try!(m.merge_from_bytes(&payload));

    Ok(msg_id)
}

#[cfg(test)]
mod tests {
    use bytes::{Buf, ByteBuf, MutByteBuf};

    use raft::codec::{encode_message, decode_message};
    use raft::raftpb::{Message, MessageType};
    use raft::errors::{Result, Error};

    #[test]
    fn test_codec() {
        let mut m1 = Message::new();
        m1.set_field_type(MessageType::MsgBeat);

        let mut w = ByteBuf::mut_with_capacity(64);
        assert_eq!(encode_message(&mut w, 1, &m1).is_ok(), true);

        let mut m2 = Message::new();
        assert_eq!(decode_message(&mut w.flip(), &mut m2).unwrap(), 1);
        assert_eq!(m1, m2);
    }
}
<|endoftext|>


<commit_before>const DATA: &'static str = include_str!("../data/input_6.txt");

pub fn main() -> Vec<String> {
    let s1 = light_show(DATA);
    let s2 = bright_show(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn doit<F, L>(f: F, state: &mut [[L; 1000]; 1000], a: (usize, usize), b: (usize, usize))
    where F: Fn(&mut L)
{
    for x in a.0..(b.0 + 1) {
        for y in a.1..(b.1 + 1) {
            f(&mut state[x][y]);
        }
    }
}

enum Cmnd {
    On((usize, usize), (usize, usize)),
    Off((usize, usize), (usize, usize)),
    Toggle((usize, usize), (usize, usize)),
}

fn parse_coords(line: &str) -> Result<((usize, usize), (usize, usize)), &'static str> {
    if let (Some(a), Some(b), Some(c), Some(d)) = scan_fmt!(&line,
                                                            "{d},{d} through {d},{d}",
                                                            usize,
                                                            usize,
                                                            usize,
                                                            usize) {
        Ok(((a, b), (c, d)))
    } else {
        Err("error parsing coordinates")
    }
}

fn parse_cmnd(line: &str) -> Result<Cmnd, &'static str> {
    let mut words = line.split_whitespace();

    match words.next() {
        Some("turn") => {
            match words.next() {
                Some("on") => {
                    let c = parse_coords(&words.collect::<String>());
                    c.map(|c| Cmnd::On(c.0, c.1))
                }
                Some("off") => {
                    let c = parse_coords(&words.collect::<String>());
                    c.map(|c| Cmnd::Off(c.0, c.1))
                }
                _ => Err("error parsing command"),
            }
        }
        Some("toggle") => {
            let c = parse_coords(&words.collect::<String>());
            c.map(|c| Cmnd::Toggle(c.0, c.1))
        }
        _ => Err("error parsing command"),
    }
}

fn light_show(input: &str) -> usize {
    let mut state = box [[false; 1000]; 1000];

    for line in input.lines() {
        let cmnd = parse_cmnd(line);
        let _ = cmnd.map(|c| {
            match c {
                Cmnd::On(a, b) => doit(|light: &mut bool| *light = true, &mut state, a, b),
                Cmnd::Off(a, b) => doit(|light: &mut bool| *light = false, &mut state, a, b),
                Cmnd::Toggle(a, b) => doit(|light: &mut bool| *light = !*light, &mut state, a, b),
            }
        });
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .filter(|&&on| on == true)
         .count()
}

fn bright_show(input: &str) -> u32 {
    let mut state = box [[0u32; 1000]; 1000];

    let on = |light: &mut u32| *light += 1;
    let off = |light: &mut u32| {
        if *light > 0 {
            *light -= 1
        }
    };
    let toggle = |light: &mut u32| *light += 2;

    for line in input.lines() {
        let cmnd = parse_cmnd(line);
        let _ = cmnd.map(|c| {
            match c {
                Cmnd::On(a, b) => doit(&on, &mut state, a, b),
                Cmnd::Off(a, b) => doit(&off, &mut state, a, b),
                Cmnd::Toggle(a, b) => doit(&toggle, &mut state, a, b),
            }
        });
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .sum()
}

#[cfg(test)]
mod test {
    use super::{light_show, bright_show};

    #[test]
    fn test_light_show() {
        assert_eq!(light_show("turn on 0,0 through 999,999"), 1000 * 1000);
        assert_eq!(light_show("toggle 0,0 through 999,0"), 1000);
        assert_eq!(light_show("turn off 499,499 through 500,500"), 0);
    }

    #[test]
    fn test_bright_show() {
        assert_eq!(bright_show("turn on 0,0 through 0,0"), 1);
        assert_eq!(bright_show("toggle 0,0 through 999,999"), 2 * 1000 * 1000);
    }
}
<commit_msg>day 6: use 'if let' instead of map and avoid needing to kill the return value<commit_after>const DATA: &'static str = include_str!("../data/input_6.txt");

pub fn main() -> Vec<String> {
    let s1 = light_show(DATA);
    let s2 = bright_show(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn doit<F, L>(f: F, state: &mut [[L; 1000]; 1000], a: (usize, usize), b: (usize, usize))
    where F: Fn(&mut L)
{
    for x in a.0..(b.0 + 1) {
        for y in a.1..(b.1 + 1) {
            f(&mut state[x][y]);
        }
    }
}

enum Cmnd {
    On((usize, usize), (usize, usize)),
    Off((usize, usize), (usize, usize)),
    Toggle((usize, usize), (usize, usize)),
}

fn parse_coords(line: &str) -> Result<((usize, usize), (usize, usize)), &'static str> {
    if let (Some(a), Some(b), Some(c), Some(d)) = scan_fmt!(&line,
                                                            "{d},{d} through {d},{d}",
                                                            usize,
                                                            usize,
                                                            usize,
                                                            usize) {
        Ok(((a, b), (c, d)))
    } else {
        Err("error parsing coordinates")
    }
}

fn parse_cmnd(line: &str) -> Result<Cmnd, &'static str> {
    let mut words = line.split_whitespace();

    match words.next() {
        Some("turn") => {
            match words.next() {
                Some("on") => {
                    let c = parse_coords(&words.collect::<String>());
                    c.map(|c| Cmnd::On(c.0, c.1))
                }
                Some("off") => {
                    let c = parse_coords(&words.collect::<String>());
                    c.map(|c| Cmnd::Off(c.0, c.1))
                }
                _ => Err("error parsing command"),
            }
        }
        Some("toggle") => {
            let c = parse_coords(&words.collect::<String>());
            c.map(|c| Cmnd::Toggle(c.0, c.1))
        }
        _ => Err("error parsing command"),
    }
}

fn light_show(input: &str) -> usize {
    let mut state = box [[false; 1000]; 1000];

    for line in input.lines() {
        if let Ok(cmnd) = parse_cmnd(line) {
            match cmnd {
                Cmnd::On(a, b) => doit(|light: &mut bool| *light = true, &mut state, a, b),
                Cmnd::Off(a, b) => doit(|light: &mut bool| *light = false, &mut state, a, b),
                Cmnd::Toggle(a, b) => doit(|light: &mut bool| *light = !*light, &mut state, a, b),
            }
        }
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .filter(|&&on| on == true)
         .count()
}

fn bright_show(input: &str) -> u32 {
    let mut state = box [[0u32; 1000]; 1000];

    for line in input.lines() {
        if let Ok(cmnd) = parse_cmnd(line) {
            match cmnd {
                Cmnd::On(a, b) => doit(|light: &mut u32| *light += 1, &mut state, a, b),
                Cmnd::Off(a, b) => {
                    doit(|light: &mut u32| {
                             if *light > 0 {
                                 *light -= 1
                             }
                         },
                         &mut state,
                         a,
                         b)
                }
                Cmnd::Toggle(a, b) => doit(|light: &mut u32| *light += 2, &mut state, a, b),
            }
        }
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .sum()
}

#[cfg(test)]
mod test {
    use super::{light_show, bright_show};

    #[test]
    fn test_light_show() {
        assert_eq!(light_show("turn on 0,0 through 999,999"), 1000 * 1000);
        assert_eq!(light_show("toggle 0,0 through 999,0"), 1000);
        assert_eq!(light_show("turn off 499,499 through 500,500"), 0);
    }

    #[test]
    fn test_bright_show() {
        assert_eq!(bright_show("turn on 0,0 through 0,0"), 1);
        assert_eq!(bright_show("toggle 0,0 through 999,999"), 2 * 1000 * 1000);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::cmp::{Ordering, };
use std::collections::{HashMap, HashSet, BinaryHeap};

pub fn single_night(file: &str) -> i64 {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    #[derive(Debug, Hash)]
    struct Node(String, i64);

    impl PartialEq for Node {
        fn eq(&self, other: &Node) -> bool {
            self.0.eq(&other.0)
        }
    }

    impl Eq for Node {}

    impl PartialOrd for Node {
        fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for Node {
        fn cmp(&self, other: &Node) -> Ordering {
            self.1.cmp(&other.1)
        }
    }

    impl Clone for Node {
        fn clone(&self) -> Self {
            Node(self.0.clone(), self.1)
        }
    }

    let mut nodes = HashSet::new();
    let mut edges = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        // println!("{}", s);

        let words: Vec<&str> = line.split_whitespace().collect();
        let from = Node(String::from(words[0]), i64::min_value());
        let to = Node(String::from(words[2]), i64::min_value());
        let distance = words[4]
            .parse::<i64>().expect("parse error");

        nodes.insert(from.clone());
        nodes.insert(to.clone());
        // negate distance because <BinaryHeap>.pop() returns highest
        edges.insert((from, to), -distance);
    }
    let mut nodes: Vec<Node> = nodes.iter().cloned().collect();
    let mut p_queue = BinaryHeap::new();
    let source = nodes.pop().unwrap();
    let source = Node(source.0, 0);
    nodes.push(source);
    println!("nodes");
    for node in nodes.clone() {
        println!("{:?}", node);
        p_queue.push(node);
    }
    println!("queue");
    for n in p_queue.clone().into_vec() {
        println!("{:?}", n);
    }
    let mut nodes = nodes;
    println!("calculating...");
    loop {
        if p_queue.is_empty() { break; }

        let node = p_queue.pop().unwrap();

        println!("Pop {:?}", node);
        // for each neighbor of n
        for (from_to, edge) in edges.iter() {
            let (ref from, ref to) = *from_to;
            if from == &node {
                let alt = node.1 - edge;
                if let Some(neighbor)
                    = p_queue.clone().iter().find(|&n| n == to) {
                    if alt > neighbor.1 {
                        p_queue.push(Node(node.0.clone(), alt));
                    }
                    println!("Push {:?} {:?}", neighbor, alt);
                }
                //println!("{:?} {:?} {:?} {:?}", from, to, edge, node);
            }
        }
    }
    -1
}
<commit_msg>Drop Binary Heap and use Vec only.<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::cmp::Ordering;

pub fn single_night(file: &str) -> i64 {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    #[derive(Debug)]
    struct Node(String, i64);

    impl PartialEq for Node {
        fn eq(&self, other: &Node) -> bool {
            self.0.eq(&other.0)
        }
    }

    impl Eq for Node {}

    impl PartialOrd for Node {
        fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
            Some(self.cmp(other))
        }
    }

    impl Ord for Node {
        fn cmp(&self, other: &Node) -> Ordering {
            self.1.cmp(&other.1)
        }
    }

    impl Clone for Node {
        fn clone(&self) -> Self {
            Node(self.0.clone(), self.1)
        }
    }

    let mut nodes = Vec::new();
    let mut edges = Vec::new();
    for line in reader.lines() {
        let line = line.unwrap();
        // println!("{}", s);

        let words: Vec<&str> = line.split_whitespace().collect();
        let from = Node(String::from(words[0]), i64::max_value());
        let to = Node(String::from(words[2]), i64::max_value());
        let distance = words[4]
                           .parse::<i64>()
                           .expect("parse error");

        nodes.push(from.clone());
        nodes.push(to.clone());
        edges.push((from, to, distance));
    }
    // remove duplicate nodes
    nodes.sort_by(|a, b| a.0.cmp(&b.0));
    nodes.dedup();

    // make last node source
    let source = nodes.pop().unwrap();
    let source = Node(source.0, 0);
    nodes.push(source);

    println!("nodes");
    for node in nodes.clone() {
        println!("{:?}", node);
    }

    println!("calculating...");
    loop {
        if nodes.is_empty() {
            break;
        }
        nodes.sort_by(|a, b| a.0.cmp(&b.0));

        let node = nodes.pop().unwrap();
        println!("Got min {:?}", node);

        // for each neighbor of n
        for edge in edges.iter() {
            let (ref from, ref to, ref dist) = *edge;
            if from == &node {
                let alt = node.1 + *dist;
                if let Ok(neighbor_index) = nodes.binary_search(to) {
                    let mut neighbor = nodes.get_mut(neighbor_index).unwrap();
                    // TODO assign new weight to neighbor
                    if alt < neighbor.1 {
                        *neighbor = Node(to.0.clone(), alt);
                    }
                    println!("New weight {:?} {:?}", neighbor, alt);
                }
                // println!("{:?} {:?} {:?} {:?}", from, to, edge, node);
            }
        }
    }
    -1
}
<|endoftext|>


<commit_before>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

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

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[allow(dead_code)]
    fn assert_error_autotraits()
    where
        Error: Unpin + Send + Sync + 'static,
    {
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<commit_msg>Simplify autotraits test<commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

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

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

#[cfg(test)]
mod repr_correctness {
    use super::*;

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[test]
    fn error_autotraits() {
        fn assert<E: Unpin + Send + Sync + 'static>() {}
        assert::<Error>();
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use std::num::{ParseFloatError, ParseIntError};

#[derive(Debug)]
pub enum Error {
    BoundsMissing(ErrorReason),
    MalformedTag(ErrorReason),
    MalformedNode(ErrorReason),
    MalformedWay(ErrorReason),
    MalformedRelation(ErrorReason),
    UnknownElement,
    XmlParseError(xml::reader::Error),
}

use std::fmt;

#[derive(Debug)]
pub enum ErrorReason {
    ParseFloat(ParseFloatError),
    ParseInt(ParseIntError),
    IllegalNesting,
    Missing,
}

impl From<ParseFloatError> for ErrorReason {
    fn from(err: ParseFloatError) -> ErrorReason {
        ErrorReason::ParseFloat(err)
    }
}

impl From<ParseIntError> for ErrorReason {
    fn from(err: ParseIntError) -> ErrorReason {
        ErrorReason::ParseInt(err)
    }
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::XmlParseError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        match *self {
            BoundsMissing(ref reason) => write!(f, "OSM XML error: Missing bounds: {:?}", reason),
            MalformedTag(ref reason) => write!(f, "OSM XML error: Malformed tag: {:?}", reason),
            MalformedNode(ref reason) => write!(f, "OSM XML error: Malformed node: {:?}", reason),
            MalformedWay(ref reason) => write!(f, "OSM XML error: Malformed way: {:?}", reason),
            MalformedRelation(ref reason) => write!(f, "OSM XML error: Malformed relation: {:?}", reason),
            UnknownElement => write!(f, "OSM XML error: Unknown XML element"),
            XmlParseError(ref reason) => write!(f, "OSM XML parse error: {}", reason),
        }

    }
}<commit_msg>Added std::Error for Error<commit_after>extern crate xml;

use std::num::{ParseFloatError, ParseIntError};

#[derive(Debug)]
pub enum Error {
    BoundsMissing(ErrorReason),
    MalformedTag(ErrorReason),
    MalformedNode(ErrorReason),
    MalformedWay(ErrorReason),
    MalformedRelation(ErrorReason),
    UnknownElement,
    XmlParseError(xml::reader::Error),
}

use std::fmt;

#[derive(Debug)]
pub enum ErrorReason {
    ParseFloat(ParseFloatError),
    ParseInt(ParseIntError),
    IllegalNesting,
    Missing,
}

impl From<ParseFloatError> for ErrorReason {
    fn from(err: ParseFloatError) -> ErrorReason {
        ErrorReason::ParseFloat(err)
    }
}

impl From<ParseIntError> for ErrorReason {
    fn from(err: ParseIntError) -> ErrorReason {
        ErrorReason::ParseInt(err)
    }
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::XmlParseError(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        match *self {
            BoundsMissing(ref reason) => write!(f, "OSM XML error: Missing bounds: {:?}", reason),
            MalformedTag(ref reason) => write!(f, "OSM XML error: Malformed tag: {:?}", reason),
            MalformedNode(ref reason) => write!(f, "OSM XML error: Malformed node: {:?}", reason),
            MalformedWay(ref reason) => write!(f, "OSM XML error: Malformed way: {:?}", reason),
            MalformedRelation(ref reason) => write!(f, "OSM XML error: Malformed relation: {:?}", reason),
            UnknownElement => write!(f, "OSM XML error: Unknown XML element"),
            XmlParseError(ref reason) => write!(f, "OSM XML parse error: {}", reason),
        }

    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        "OSM XML error"
    }

    fn cause(&self) -> Option<&::std::error::Error> {
        None
    }
}<|endoftext|>


<commit_before>#[cfg(target_os = "linux")]
use secret_service::SsError;
#[cfg(target_os = "macos")]
use security_framework::base::Error as SfError;
use std::error;
use std::fmt;
use std::string::FromUtf8Error;

pub type Result<T> = ::std::result::Result<T, KeyringError>;

#[derive(Debug)]
pub enum KeyringError {
    #[cfg(target_os = "macos")]
    MacOsKeychainError,
    #[cfg(target_os = "linux")]
    SecretServiceError(SsError),
    #[cfg(target_os = "windows")]
    WindowsVaultError,
    NoBackendFound,
    NoPasswordFound,
    Parse(FromUtf8Error),
}

impl fmt::Display for KeyringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => write!(f, "Mac Os Keychain Error"),
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => write!(f, "Secret Service Error: {}", err),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => write!(f, "Windows Vault Error"),
            KeyringError::NoBackendFound => write!(f, "Keyring error: No Backend Found"),
            KeyringError::NoPasswordFound => write!(f, "Keyring Error: No Password Found"),
            KeyringError::Parse(ref err) => write!(f, "Keyring Parse Error: {}", err),
        }
    }
}

impl error::Error for KeyringError {
    fn description(&self) -> &str {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => "Mac Os Keychain Error",
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => err.description(),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => "Windows Vault Error",
            KeyringError::NoBackendFound => "No Backend Found",
            KeyringError::NoPasswordFound => "No Password Found",
            KeyringError::Parse(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => Some(err),
            _ => None,
        }
    }
}

#[cfg(target_os = "linux")]
impl From<SsError> for KeyringError {
    fn from(err: SsError) -> KeyringError {
        KeyringError::SecretServiceError(err)
    }
}

#[cfg(target_os = "macos")]
impl From<SfError> for KeyringError {
    fn from(err: SfError) -> KeyringError {
        KeyringError::MacOsKeychainError(err)
    }
}

impl From<FromUtf8Error> for KeyringError {
    fn from(err: FromUtf8Error) -> KeyringError {
        KeyringError::Parse(err)
    }
}
<commit_msg>Embed Mac security-framework errors in KeyringError<commit_after>#[cfg(target_os = "linux")]
use secret_service::SsError;
#[cfg(target_os = "macos")]
use security_framework::base::Error as SfError;
use std::error;
use std::fmt;
use std::string::FromUtf8Error;

pub type Result<T> = ::std::result::Result<T, KeyringError>;

#[derive(Debug)]
pub enum KeyringError {
    #[cfg(target_os = "macos")]
    MacOsKeychainError(SfError),
    #[cfg(target_os = "linux")]
    SecretServiceError(SsError),
    #[cfg(target_os = "windows")]
    WindowsVaultError,
    NoBackendFound,
    NoPasswordFound,
    Parse(FromUtf8Error),
}

impl fmt::Display for KeyringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError(ref err) => write!(f, "Mac Os Keychain Error: {}", err),
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => write!(f, "Secret Service Error: {}", err),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => write!(f, "Windows Vault Error"),
            KeyringError::NoBackendFound => write!(f, "Keyring error: No Backend Found"),
            KeyringError::NoPasswordFound => write!(f, "Keyring Error: No Password Found"),
            KeyringError::Parse(ref err) => write!(f, "Keyring Parse Error: {}", err),
        }
    }
}

impl error::Error for KeyringError {
    fn description(&self) -> &str {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError(ref err) => err.description(),
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => err.description(),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => "Windows Vault Error",
            KeyringError::NoBackendFound => "No Backend Found",
            KeyringError::NoPasswordFound => "No Password Found",
            KeyringError::Parse(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => Some(err),
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError(ref err) => Some(err),
            _ => None,
        }
    }
}

#[cfg(target_os = "linux")]
impl From<SsError> for KeyringError {
    fn from(err: SsError) -> KeyringError {
        KeyringError::SecretServiceError(err)
    }
}

#[cfg(target_os = "macos")]
impl From<SfError> for KeyringError {
    fn from(err: SfError) -> KeyringError {
        KeyringError::MacOsKeychainError(err)
    }
}

impl From<FromUtf8Error> for KeyringError {
    fn from(err: FromUtf8Error) -> KeyringError {
        KeyringError::Parse(err)
    }
}
<|endoftext|>


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

//! External callback definitions

use libc::{c_char, c_int, c_void};
use std::mem::transmute;
use std::comm::Sender;
use std::ptr::null;
use std::str::raw::{from_c_str, from_buf_len};

use super::*;
use super::error::ErrorData;

pub fn new_handler() -> ffi::xmlSAXHandler {
    ffi::xmlSAXHandler {
        internalSubset:         None,
        isStandalone:           None,
        hasInternalSubset:      None,
        hasExternalSubset:      None,
        resolveEntity:          None,
        getEntity:              None,
        entityDecl:             None,
        notationDecl:           None,
        attributeDecl:          None,
        elementDecl:            None,
        unparsedEntityDecl:     None,
        setDocumentLocator:     None,
        startDocument:          Some(start_document),
        endDocument:            Some(end_document),
        startElement:           Some(start_element),
        endElement:             Some(end_element),
        reference:              None,
        characters:             Some(characters),
        ignorableWhitespace:    None,               // use characters
        processingInstruction:  None,
        comment:                Some(comment),
        warning:                None,               // use serror
        error:                  None,               // use serror
        fatalError:             None,               // use serror
        getParameterEntity:     None,
        cdataBlock:             Some(cdata_block),
        externalSubset:         None,
        initialized:            ffi::XML_SAX2_MAGIC,
        _private:               null(),
        startElementNs:         None,
        endElementNs:           None,
        serror:                 Some(serror),
    }
}

unsafe fn sender_from_ptr(ctx: *const c_void) -> &Sender<ParseResult> { transmute(ctx) }

extern "C" fn start_document(ctx: *const c_void) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(StartDocument)
        );
    }
}

extern "C" fn end_document(ctx: *const c_void) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(EndDocument)
        );
    }
}

extern "C" fn start_element(ctx: *const c_void, name: *const ffi::xmlChar, atts: *const *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(StartElement(from_c_str(name as *const c_char), Attributes::from_buf(atts)))
        );
    }
}

extern "C" fn end_element(ctx: *const c_void, name: *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(EndElement(from_c_str(name as *const c_char)))
        );
    }
}

extern "C" fn characters(ctx: *const c_void, ch: *const ffi::xmlChar, len: c_int) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(Characters(from_buf_len(ch, len as uint)))
        );
    }
}

extern "C" fn comment(ctx: *const c_void, value: *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(Comment(from_c_str(value as *const c_char)))
        );
    }
}

extern "C" fn cdata_block(ctx: *const c_void, value: *const ffi::xmlChar, len: c_int) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(CdataBlock(from_buf_len(value, len as uint)))
        );
    }
}

extern "C" fn serror(ctx: *const c_void, error: *const ffi::xmlError) {
    unsafe {
        ErrorData::from_ptr(error).map(|err| {
            sender_from_ptr(ctx).send(Err(err.clone()));
        });
    }
}
<commit_msg>Fix for lifetime elision<commit_after>// Copyright 2013 The SAX-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! External callback definitions

use libc::{c_char, c_int, c_void};
use std::mem::transmute;
use std::comm::Sender;
use std::ptr::null;
use std::str::raw::{from_c_str, from_buf_len};

use super::*;
use super::error::ErrorData;

pub fn new_handler() -> ffi::xmlSAXHandler {
    ffi::xmlSAXHandler {
        internalSubset:         None,
        isStandalone:           None,
        hasInternalSubset:      None,
        hasExternalSubset:      None,
        resolveEntity:          None,
        getEntity:              None,
        entityDecl:             None,
        notationDecl:           None,
        attributeDecl:          None,
        elementDecl:            None,
        unparsedEntityDecl:     None,
        setDocumentLocator:     None,
        startDocument:          Some(start_document),
        endDocument:            Some(end_document),
        startElement:           Some(start_element),
        endElement:             Some(end_element),
        reference:              None,
        characters:             Some(characters),
        ignorableWhitespace:    None,               // use characters
        processingInstruction:  None,
        comment:                Some(comment),
        warning:                None,               // use serror
        error:                  None,               // use serror
        fatalError:             None,               // use serror
        getParameterEntity:     None,
        cdataBlock:             Some(cdata_block),
        externalSubset:         None,
        initialized:            ffi::XML_SAX2_MAGIC,
        _private:               null(),
        startElementNs:         None,
        endElementNs:           None,
        serror:                 Some(serror),
    }
}

// aaaaaahhh this is so unsafe!
unsafe fn sender_from_ptr<'a>(ctx: *const c_void) -> &'a Sender<ParseResult> { transmute(ctx) }

extern "C" fn start_document(ctx: *const c_void) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(StartDocument)
        );
    }
}

extern "C" fn end_document(ctx: *const c_void) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(EndDocument)
        );
    }
}

extern "C" fn start_element(ctx: *const c_void, name: *const ffi::xmlChar, atts: *const *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(StartElement(from_c_str(name as *const c_char), Attributes::from_buf(atts)))
        );
    }
}

extern "C" fn end_element(ctx: *const c_void, name: *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(EndElement(from_c_str(name as *const c_char)))
        );
    }
}

extern "C" fn characters(ctx: *const c_void, ch: *const ffi::xmlChar, len: c_int) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(Characters(from_buf_len(ch, len as uint)))
        );
    }
}

extern "C" fn comment(ctx: *const c_void, value: *const ffi::xmlChar) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(Comment(from_c_str(value as *const c_char)))
        );
    }
}

extern "C" fn cdata_block(ctx: *const c_void, value: *const ffi::xmlChar, len: c_int) {
    unsafe {
        sender_from_ptr(ctx).send(
            Ok(CdataBlock(from_buf_len(value, len as uint)))
        );
    }
}

extern "C" fn serror(ctx: *const c_void, error: *const ffi::xmlError) {
    unsafe {
        ErrorData::from_ptr(error).map(|err| {
            sender_from_ptr(ctx).send(Err(err.clone()));
        });
    }
}
<|endoftext|>


<commit_before>use {HashSet, HashMap};
use std::collections::{RingBuf, Deque};
use std::fmt;

// call this Unigraph instead?
pub trait Graph<T> {
    /// Insert a new node, returning its index
    fn add_node(&mut self, val: T) -> NodeIndex;

    /// Insert a new edge, returning an error if one of the indices is invalid
    /// and a result otherwise
    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool>;

    /// Return an iterator over the out-neighbors for a given node
    fn adj(&self, i: NodeIndex) -> NodeIndices;

    /// Return the number of nodes in the graph
    fn num_nodes(&self) -> uint;

    fn node_indices(&self) -> NodeIndices;
}

struct GraphError {
    error_type: GraphErrorType,
}

impl GraphError {
    fn invalid_index(ind: NodeIndex) -> GraphError {
        GraphError { error_type: InvalidNodeIndex(ind) }
    }
}

type GraphResult<T> = Result<T, GraphError>;

enum GraphErrorType {
    InvalidNodeIndex(NodeIndex),
}

pub type NodeIndex = uint;
type NodeIndexSet = HashSet<NodeIndex>;

#[deriving(Show, Clone)]
struct Node<T> {
    data: T,
    index: NodeIndex,
}

/// Undirected graph. Allows loops.
pub struct Ungraph<T> {
    nodes: HashMap<NodeIndex, Node<T>>,
    adj: HashMap<NodeIndex, NodeIndexSet>,
    num_nodes: uint,
}

impl<T: fmt::Show> fmt::Show for Ungraph<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        write!(fmt, "{{");
        for n in self.nodes.values() {
            write!(fmt, " {} ", n.data);
        }
        write!(fmt, "}}  ");

        for (&i, adj) in self.adj.iter() {
            for &j in adj.iter() {
                write!(fmt, "({}, {})", self.get_node(i).data,
                                        self.get_node(j).data);
            }
        }

        Ok(())
    }
}

/// Directed graph. Allows loops.
pub struct Digraph<T> {
    nodes: HashMap<NodeIndex, Node<T>>,
    in_adj: HashMap<NodeIndex, NodeIndexSet>,
    out_adj: HashMap<NodeIndex, NodeIndexSet>,
    num_nodes: uint,
}

impl<T: fmt::Show> fmt::Show for Digraph<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        write!(fmt, "{{");
        for n in self.nodes.values() {
            write!(fmt, " {} ", n.data);
        }
        write!(fmt, "}}  ");

        for (&i, adj) in self.out_adj.iter() {
            for &j in adj.iter() {
                write!(fmt, "({}, {})", self.get_node(i).data,
                                        self.get_node(j).data);
            }
        }

        Ok(())
    }
}

impl<T> Ungraph<T> {
    pub fn new() -> Ungraph<T> {
        Ungraph { nodes: HashMap::new(), adj: HashMap::new(), num_nodes: 0 }
    }

    pub fn degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if !self.adj.contains_key(&ind) {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok( self.get_adj(ind).len() )
        }
    }

    pub fn get_node<'a>(&'a self, i: NodeIndex) -> &'a Node<T> {
        self.nodes.find(&i).unwrap()
    }

    pub fn get_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.adj.find(&i).unwrap()
    }
}

impl<T: Clone> Ungraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &NodeIndexSet) -> Ungraph<T> {
        let mut new = Ungraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for &ind in nodes.iter() {
            let new_ind = new.add_node(self.get_node(ind).data.clone());
            ind_map.insert(ind, new_ind);
        }

        for i in nodes.iter() {
            let actual_i = *ind_map.find(i).unwrap();
            for j in self.get_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(actual_i, *ind_map.find(j).unwrap());
                }
            }
        }

        new
    }
}

impl<T> Graph<T> for Ungraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.insert(ind, Node { data: val, index: ind });
        self.adj.insert(ind, HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else if !self.nodes.contains_key(&j) {
            Err(GraphError::invalid_index(j))
        } else {
            if self.get_adj(i).contains(&j) {
                Ok(false)
            } else {
                self.adj.find_mut(&i).unwrap().insert(j);
                self.adj.find_mut(&j).unwrap().insert(i);
                Ok(true)
            }
        }
    }

    fn adj(&self, i: NodeIndex) -> NodeIndices {
        FromIterator::from_iter(self.get_adj(i).iter().map(|&x| x))
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }

    fn node_indices(&self) -> NodeIndices {
        FromIterator::from_iter(self.nodes.keys().map(|&x| x))
    }
}

impl<T> Digraph<T> {
    pub fn new() -> Digraph<T> {
        Digraph { nodes: HashMap::new(),
                  in_adj: HashMap::new(),
                  out_adj: HashMap::new(),
                  num_nodes: 0 }
    }

    pub fn out_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if !self.nodes.contains_key(&ind) {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.get_out_adj(ind).len())
        }
    }

    pub fn in_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.get_in_adj(ind).len())
        }
    }

    pub fn get_node<'a>(&'a self, i: NodeIndex) -> &'a Node<T> {
        self.nodes.find(&i).unwrap()
    }

    pub fn get_in_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.in_adj.find(&i).unwrap()
    }

    pub fn get_out_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.out_adj.find(&i).unwrap()
    }
}

impl<T: Clone> Digraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &NodeIndexSet) -> Digraph<T> {
        let mut new = Digraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for &ind in nodes.iter() {
            let new_ind = new.add_node(self.get_node(ind).data.clone());
            ind_map.insert(ind, new_ind);
        }

        for i in nodes.iter() {
            let actual_i = *ind_map.find(i).unwrap();
            for j in self.get_in_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(*ind_map.find(j).unwrap(), actual_i);
                }
            }

            for j in self.get_out_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(actual_i, *ind_map.find(j).unwrap());
                }
            }
        }

        new
    }

    // Returns the transpose of the graph
    pub fn transpose(&self) -> Digraph<T> {
        let mut new = Digraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for n in self.nodes.values() {
            let new_ind = new.add_node(n.data.clone());
            ind_map.insert(n.index, new_ind);
        }

        for &i in self.nodes.keys() {
            let actual_i = *ind_map.find(&i).unwrap();

            for j in self.get_in_adj(i).iter() {
                new.add_edge(actual_i, *ind_map.find(j).unwrap());
            }

            for j in self.get_out_adj(i).iter() {
                new.add_edge(*ind_map.find(j).unwrap(), actual_i);
            }
        }
        new
    }
}

impl<T> Graph<T> for Digraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.insert(ind, Node { data: val, index: ind });
        self.in_adj.insert(ind, HashSet::new());
        self.out_adj.insert(ind, HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else if !self.nodes.contains_key(&j) {
            Err(GraphError::invalid_index(j))
        } else {
            if self.get_out_adj(i).contains(&j) {
                Ok(false)
            } else {
                self.out_adj.find_mut(&i).unwrap().insert(j);
                self.in_adj.find_mut(&j).unwrap().insert(i);
                Ok(true)
            }
        }
    }

    fn adj(&self, i: NodeIndex) -> NodeIndices {
        FromIterator::from_iter(self.get_out_adj(i).iter().map(|&x| x))
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }

    fn node_indices(&self) -> NodeIndices {
        FromIterator::from_iter(self.nodes.keys().map(|&x| x))
    }
}

struct NodeIndices {
    indices: Vec<NodeIndex>,
    curr: uint,
}

impl Iterator<NodeIndex> for NodeIndices {
    fn next(&mut self) -> Option<NodeIndex> {
        if self.curr < self.indices.len() {
            self.curr += 1;
            Some(self.indices[self.curr - 1])
        } else {
            None
        }
    }
}

impl FromIterator<NodeIndex> for NodeIndices {
    fn from_iter<T: Iterator<NodeIndex>>(mut it: T) -> NodeIndices {
        let mut vec = vec!();
        for i in it {
            vec.push(i);
        }
        NodeIndices { indices: vec, curr: 0 }
    }

}
<commit_msg>Add remove_node() method to Graph trait and implement it for both Ungraph and Digraph<commit_after>use {HashSet, HashMap};
use std::collections::{RingBuf, Deque};
use std::fmt;

// call this Unigraph instead?
pub trait Graph<T> {
    /// Insert a new node, returning its index
    fn add_node(&mut self, val: T) -> NodeIndex;

    /// Insert a new edge, returning an error if one of the indices is invalid
    /// and a result otherwise
    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool>;

    /// Remove a new node, returning its index
    fn remove_node(&mut self, i: NodeIndex) -> GraphResult<()>;

    /// Return an iterator over the out-neighbors for a given node
    fn adj(&self, i: NodeIndex) -> NodeIndices;

    /// Return the number of nodes in the graph
    fn num_nodes(&self) -> uint;

    fn node_indices(&self) -> NodeIndices;
}

struct GraphError {
    error_type: GraphErrorType,
}

impl GraphError {
    fn invalid_index(ind: NodeIndex) -> GraphError {
        GraphError { error_type: InvalidNodeIndex(ind) }
    }
}

type GraphResult<T> = Result<T, GraphError>;

enum GraphErrorType {
    InvalidNodeIndex(NodeIndex),
}

pub type NodeIndex = uint;
type NodeIndexSet = HashSet<NodeIndex>;

#[deriving(Show, Clone)]
struct Node<T> {
    data: T,
    index: NodeIndex,
}

/// Undirected graph. Allows loops.
pub struct Ungraph<T> {
    nodes: HashMap<NodeIndex, Node<T>>,
    adj: HashMap<NodeIndex, NodeIndexSet>,
    num_nodes: uint,
}

impl<T: fmt::Show> fmt::Show for Ungraph<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        write!(fmt, "{{");
        for n in self.nodes.values() {
            write!(fmt, " {} ", n.data);
        }
        write!(fmt, "}}  ");

        for (&i, adj) in self.adj.iter() {
            for &j in adj.iter() {
                write!(fmt, "({}, {})", self.get_node(i).data,
                                        self.get_node(j).data);
            }
        }

        Ok(())
    }
}

/// Directed graph. Allows loops.
pub struct Digraph<T> {
    nodes: HashMap<NodeIndex, Node<T>>,
    in_adj: HashMap<NodeIndex, NodeIndexSet>,
    out_adj: HashMap<NodeIndex, NodeIndexSet>,
    num_nodes: uint,
}

impl<T: fmt::Show> fmt::Show for Digraph<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
        write!(fmt, "{{");
        for n in self.nodes.values() {
            write!(fmt, " {} ", n.data);
        }
        write!(fmt, "}}  ");

        for (&i, adj) in self.out_adj.iter() {
            for &j in adj.iter() {
                write!(fmt, "({}, {})", self.get_node(i).data,
                                        self.get_node(j).data);
            }
        }

        Ok(())
    }
}

impl<T> Ungraph<T> {
    pub fn new() -> Ungraph<T> {
        Ungraph { nodes: HashMap::new(), adj: HashMap::new(), num_nodes: 0 }
    }

    pub fn degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if !self.adj.contains_key(&ind) {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok( self.get_adj(ind).len() )
        }
    }

    pub fn get_node<'a>(&'a self, i: NodeIndex) -> &'a Node<T> {
        self.nodes.find(&i).unwrap()
    }

    pub fn get_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.adj.find(&i).unwrap()
    }
}

impl<T: Clone> Ungraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &NodeIndexSet) -> Ungraph<T> {
        let mut new = Ungraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for &ind in nodes.iter() {
            let new_ind = new.add_node(self.get_node(ind).data.clone());
            ind_map.insert(ind, new_ind);
        }

        for i in nodes.iter() {
            let actual_i = *ind_map.find(i).unwrap();
            for j in self.get_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(actual_i, *ind_map.find(j).unwrap());
                }
            }
        }

        new
    }
}

impl<T> Graph<T> for Ungraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.insert(ind, Node { data: val, index: ind });
        self.adj.insert(ind, HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else if !self.nodes.contains_key(&j) {
            Err(GraphError::invalid_index(j))
        } else {
            if self.get_adj(i).contains(&j) {
                Ok(false)
            } else {
                self.adj.find_mut(&i).unwrap().insert(j);
                self.adj.find_mut(&j).unwrap().insert(i);
                Ok(true)
            }
        }
    }

    fn remove_node(&mut self, i: NodeIndex) -> GraphResult<()> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else {
            self.nodes.remove(&i);

            for j in self.adj(i) {
                self.adj.find_mut(&j).unwrap().remove(&i);
            }
            self.adj.remove(&i);
            self.num_nodes -= 1;
            Ok(())
        }
    }

    fn adj(&self, i: NodeIndex) -> NodeIndices {
        FromIterator::from_iter(self.get_adj(i).iter().map(|&x| x))
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }

    fn node_indices(&self) -> NodeIndices {
        FromIterator::from_iter(self.nodes.keys().map(|&x| x))
    }
}

impl<T> Digraph<T> {
    pub fn new() -> Digraph<T> {
        Digraph { nodes: HashMap::new(),
                  in_adj: HashMap::new(),
                  out_adj: HashMap::new(),
                  num_nodes: 0 }
    }

    pub fn out_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if !self.nodes.contains_key(&ind) {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.get_out_adj(ind).len())
        }
    }

    pub fn in_degree(&mut self, ind: NodeIndex) -> Result<uint, GraphError> {
        if ind >= self.num_nodes {
            Err(GraphError::invalid_index(ind))
        } else {
            Ok(self.get_in_adj(ind).len())
        }
    }

    fn in_adj(&self, i: NodeIndex) -> NodeIndices {
        FromIterator::from_iter(self.get_in_adj(i).iter().map(|&x| x))
    }

    pub fn is_dag(&self) -> bool {
        false
    }

    pub fn get_node<'a>(&'a self, i: NodeIndex) -> &'a Node<T> {
        self.nodes.find(&i).unwrap()
    }

    pub fn get_in_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.in_adj.find(&i).unwrap()
    }

    pub fn get_out_adj<'a>(&'a self, i: NodeIndex) -> &'a NodeIndexSet {
        self.out_adj.find(&i).unwrap()
    }
}

impl<T: Clone> Digraph<T> {
    /// Returns a new graph induced by a set of node indices
    pub fn induced_subgraph(&self, nodes: &NodeIndexSet) -> Digraph<T> {
        let mut new = Digraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for &ind in nodes.iter() {
            let new_ind = new.add_node(self.get_node(ind).data.clone());
            ind_map.insert(ind, new_ind);
        }

        for i in nodes.iter() {
            let actual_i = *ind_map.find(i).unwrap();
            for j in self.get_in_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(*ind_map.find(j).unwrap(), actual_i);
                }
            }

            for j in self.get_out_adj(*i).iter() {
                if nodes.contains(j) {
                    new.add_edge(actual_i, *ind_map.find(j).unwrap());
                }
            }
        }

        new
    }

    // Returns the transpose of the graph
    pub fn transpose(&self) -> Digraph<T> {
        let mut new = Digraph::new();
        let mut ind_map = HashMap::new(); // maps old indices to new

        for n in self.nodes.values() {
            let new_ind = new.add_node(n.data.clone());
            ind_map.insert(n.index, new_ind);
        }

        for &i in self.nodes.keys() {
            let actual_i = *ind_map.find(&i).unwrap();

            for j in self.get_in_adj(i).iter() {
                new.add_edge(actual_i, *ind_map.find(j).unwrap());
            }

            for j in self.get_out_adj(i).iter() {
                new.add_edge(*ind_map.find(j).unwrap(), actual_i);
            }
        }
        new
    }
}

impl<T> Graph<T> for Digraph<T> {
    fn add_node(&mut self, val: T) -> NodeIndex {
        let ind = self.num_nodes;
        self.nodes.insert(ind, Node { data: val, index: ind });
        self.in_adj.insert(ind, HashSet::new());
        self.out_adj.insert(ind, HashSet::new());
        self.num_nodes += 1;
        ind
    }

    fn add_edge(&mut self, i: NodeIndex, j: NodeIndex) -> GraphResult<bool> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else if !self.nodes.contains_key(&j) {
            Err(GraphError::invalid_index(j))
        } else {
            if self.get_out_adj(i).contains(&j) {
                Ok(false)
            } else {
                self.out_adj.find_mut(&i).unwrap().insert(j);
                self.in_adj.find_mut(&j).unwrap().insert(i);
                Ok(true)
            }
        }
    }

    fn remove_node(&mut self, i: NodeIndex) -> GraphResult<()> {
        if !self.nodes.contains_key(&i) {
            Err(GraphError::invalid_index(i))
        } else {
            self.nodes.remove(&i);

            for j in self.adj(i) {
                self.in_adj.find_mut(&j).unwrap().remove(&i);
            }
            self.out_adj.remove(&i);

            for j in self.in_adj(i) {
                self.out_adj.find_mut(&j).unwrap().remove(&i);
            }
            self.in_adj.remove(&i);

            self.num_nodes -= 1;
            Ok(())
        }
    }

    fn adj(&self, i: NodeIndex) -> NodeIndices {
        FromIterator::from_iter(self.get_out_adj(i).iter().map(|&x| x))
    }

    fn num_nodes(&self) -> uint {
        self.num_nodes
    }

    fn node_indices(&self) -> NodeIndices {
        FromIterator::from_iter(self.nodes.keys().map(|&x| x))
    }
}

struct NodeIndices {
    indices: Vec<NodeIndex>,
    curr: uint,
}

impl Iterator<NodeIndex> for NodeIndices {
    fn next(&mut self) -> Option<NodeIndex> {
        if self.curr < self.indices.len() {
            self.curr += 1;
            Some(self.indices[self.curr - 1])
        } else {
            None
        }
    }
}

impl FromIterator<NodeIndex> for NodeIndices {
    fn from_iter<T: Iterator<NodeIndex>>(mut it: T) -> NodeIndices {
        let mut vec = vec!();
        for i in it {
            vec.push(i);
        }
        NodeIndices { indices: vec, curr: 0 }
    }
}
<|endoftext|>


<commit_before>//! Render output types and related functions.

use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Output types.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan)
}

/// Associate an output type to a given type.
pub trait OutputType {
  const OUTPUT: Type;
}

/// Render outputs.
pub trait OutputTypes {
  /// Get the types of the output.
  fn ty() -> &'static [Type];
}

impl<A> OutputTypes for A where A: OutputType {
  fn ty() -> &'static [Type] {
    &[A::OUTPUT]
  }
}

macro_rules! multi_output_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> OutputTypes for ($($t),*) where $($t: OutputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::OUTPUT),*]
      }
    }
  }
}

multi_output_type_impl!(A, B);
multi_output_type_impl!(A, B, C);
multi_output_type_impl!(A, B, C, D);
multi_output_type_impl!(A, B, C, D, E);
multi_output_type_impl!(A, B, C, D, E, F);
multi_output_type_impl!(A, B, C, D, E, F, G);
multi_output_type_impl!(A, B, C, D, E, F, G, H);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// An output.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Output {
  /// Name of the output.
  name: String,
  /// Type of the output.
  #[serde(rename = "type")]
  ty: Type
}

impl Output {
  /// Create a new output.
  pub fn new<T, N>(name: N) -> Self
  where T: OutputType,
        N: Into<String> {
    Output {
      name: name.into(),
      ty: T::OUTPUT
    }
  }
}

#[cfg(test)]
mod tests {
  use serde_json::{from_str, to_string};

  use crate::render::types::*;
  use super::*;

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::OUTPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::OUTPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::OUTPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::OUTPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::OUTPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::OUTPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::OUTPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::OUTPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::OUTPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::OUTPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::OUTPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::OUTPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::OUTPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::OUTPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::OUTPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::OUTPUT).unwrap(), r#"{"bool":4}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::OUTPUT);
  }
}
<commit_msg>Add the render output -> glsl function.<commit_after>//! Render output types and related functions.

use glsl::syntax::{ExternalDeclaration, StructFieldSpecifier, TypeSpecifier, TypeSpecifierNonArray};
use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Output types.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan)
}

/// Associate an output type to a given type.
pub trait OutputType {
  const OUTPUT: Type;
}

/// Render outputs.
pub trait OutputTypes {
  /// Get the types of the output.
  fn ty() -> &'static [Type];
}

impl<A> OutputTypes for A where A: OutputType {
  fn ty() -> &'static [Type] {
    &[A::OUTPUT]
  }
}

macro_rules! multi_output_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> OutputTypes for ($($t),*) where $($t: OutputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::OUTPUT),*]
      }
    }
  }
}

multi_output_type_impl!(A, B);
multi_output_type_impl!(A, B, C);
multi_output_type_impl!(A, B, C, D);
multi_output_type_impl!(A, B, C, D, E);
multi_output_type_impl!(A, B, C, D, E, F);
multi_output_type_impl!(A, B, C, D, E, F, G);
multi_output_type_impl!(A, B, C, D, E, F, G, H);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_output_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// An output.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Output {
  /// Name of the output.
  name: String,
  /// Type of the output.
  #[serde(rename = "type")]
  ty: Type
}

impl Output {
  /// Create a new output.
  pub fn new<T, N>(name: N) -> Self
  where T: OutputType,
        N: Into<String> {
    Output {
      name: name.into(),
      ty: T::OUTPUT
    }
  }
}

/// Generate a GLSL structure given a list of outputs.
pub(crate) fn outputs_to_struct_decl<'a, O>(
  name : &str,
  outputs: O
) -> ExternalDeclaration
where O: IntoIterator<Item = &'a Output> {
  ExternalDeclaration::new_struct(name, outputs.into_iter().map(output_to_struct_field))
}

/// Generate a struct field from an ouput.
fn output_to_struct_field(output: &Output) -> StructFieldSpecifier {
  StructFieldSpecifier::new(output.name.as_str(), glsl_type_from_output_type(&output.ty))
}

/// Generate a GLSL type from a given output type.
fn glsl_type_from_output_type(ty: &Type) -> TypeSpecifier {
  let ty_nonarray = match *ty {
    Type::Int(TypeChan::One) => TypeSpecifierNonArray::Int,
    Type::Int(TypeChan::Two) => TypeSpecifierNonArray::IVec2,
    Type::Int(TypeChan::Three) => TypeSpecifierNonArray::IVec3,
    Type::Int(TypeChan::Four) => TypeSpecifierNonArray::IVec4,
    Type::UInt(TypeChan::One) => TypeSpecifierNonArray::UInt,
    Type::UInt(TypeChan::Two) => TypeSpecifierNonArray::UVec2,
    Type::UInt(TypeChan::Three) => TypeSpecifierNonArray::UVec3,
    Type::UInt(TypeChan::Four) => TypeSpecifierNonArray::UVec4,
    Type::Float(TypeChan::One) => TypeSpecifierNonArray::Float,
    Type::Float(TypeChan::Two) => TypeSpecifierNonArray::Vec2,
    Type::Float(TypeChan::Three) => TypeSpecifierNonArray::Vec3,
    Type::Float(TypeChan::Four) => TypeSpecifierNonArray::Vec4,
    Type::Bool(TypeChan::One) => TypeSpecifierNonArray::Bool,
    Type::Bool(TypeChan::Two) => TypeSpecifierNonArray::BVec2,
    Type::Bool(TypeChan::Three) => TypeSpecifierNonArray::BVec3,
    Type::Bool(TypeChan::Four) => TypeSpecifierNonArray::BVec4,
  };

  TypeSpecifier::new(ty_nonarray)
}

#[cfg(test)]
mod tests {
  use glsl_quasiquote::glsl;
  use serde_json::{from_str, to_string};

  use crate::render::types::*;
  use super::*;

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::OUTPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::OUTPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::OUTPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::OUTPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::OUTPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::OUTPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::OUTPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::OUTPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::OUTPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::OUTPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::OUTPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::OUTPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::OUTPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::OUTPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::OUTPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::OUTPUT).unwrap(), r#"{"bool":4}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::OUTPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::OUTPUT);
  }

  #[test]
  fn outputs_to_glsl_struct() {
    let color = Output::new::<RGBAF, _>("color");
    let depth = Output::new::<Float, _>("depth");
    let outputs = &[color, depth];

    let ed = vec![outputs_to_struct_decl("Output", outputs)];
    let expected = glsl!{
      struct Output {
        vec4 color;
        float depth;
      };
    };

    assert_eq!(ed, expected);
  }
}
<|endoftext|>