<commit_before>#![deny(missing_docs)]

//! A DSL parsing library for human readable text documents

extern crate read_token;
extern crate range;

pub use parse_error_handler::{
    stderr_unwrap,
    ParseErrorHandler
};
pub use parse_error::ParseError;
pub use meta_rules::{ parse, Rule };

/// The type of debug id used to track down errors in rules.
pub type DebugId = usize;

use std::sync::Arc;
use std::fs::File;
use std::path::Path;
use range::Range;

pub mod bootstrap;
pub mod json;
pub mod meta_rules;
pub mod tokenizer;

mod parse_error;
mod parse_error_handler;

mod all {
    pub use super::*;
}

/// Represents meta data.
#[derive(PartialEq, Clone, Debug)]
pub enum MetaData {
    /// Starts node.
    StartNode(Arc<String>),
    /// Ends node.
    EndNode(Arc<String>),
    /// Sets bool property.
    Bool(Arc<String>, bool),
    /// Sets f64 property.
    F64(Arc<String>, f64),
    /// Sets string property.
    String(Arc<String>, Arc<String>),
}

/// Stores syntax.
#[derive(Clone, Debug, PartialEq)]
pub struct Syntax {
    /// Rule data.
    pub rules: Vec<Rule>,
    /// Name of rules.
    pub names: Vec<Arc<String>>,
}

impl Syntax {
    /// Creates a new syntax.
    pub fn new() -> Syntax {
        Syntax {
            rules: vec![],
            names: vec![]
        }
    }

    /// Adds a new rule.
    pub fn push(&mut self, name: Arc<String>, rule: Rule) {
        self.rules.push(rule);
        self.names.push(name);
    }
}

/// Reads syntax from text.
pub fn syntax(rules: &str) -> Result<Syntax, Range<ParseError>> {
    let mut tokens = vec![];
    try!(parse(&bootstrap::rules(), rules, &mut tokens));
    let mut ignored_meta_data = vec![];
    match bootstrap::convert(&tokens, &mut ignored_meta_data) {
        Ok(res) => Ok(res),
        Err(()) => Err((Range::empty(0).wrap(ParseError::Conversion(
            format!("Bootstrapping rules are incorrect")))))
    }
}

/// Convenience method for loading data, using the new meta language.
/// Panics if there is an error, and writes error message to
/// standard error output.
pub fn load_syntax_data<A, B>(
    syntax_path: A,
    data_path: B
) -> Vec<Range<MetaData>>
    where A: AsRef<Path>, B: AsRef<Path>
{
    use std::io::Read;

    let mut syntax_file = File::open(syntax_path).unwrap();
    let mut s = String::new();
    syntax_file.read_to_string(&mut s).unwrap();
    let rules = stderr_unwrap(&s, syntax(&s));

    let mut data_file = File::open(data_path).unwrap();
    let mut d = String::new();
    data_file.read_to_string(&mut d).unwrap();
    let mut tokens = vec![];
    stderr_unwrap(&d, parse(&rules, &d, &mut tokens));
    tokens
}

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

    fn is_thread_safe<T: Send + Sync>() {}

    #[test]
    fn meta_data_thread_safe() {
        is_thread_safe::<MetaData>();
    }

    #[test]
    fn parse_error_thread_safe() {
        is_thread_safe::<ParseError>();
    }

    #[test]
    fn rule_thread_safe() {
        is_thread_safe::<Rule>();
    }

    #[test]
    fn syntax_thread_safe() {
        is_thread_safe::<Syntax>();
    }
}
<commit_msg>Fixed comment<commit_after>#![deny(missing_docs)]

//! A DSL parsing library for human readable text documents

extern crate read_token;
extern crate range;

pub use parse_error_handler::{
    stderr_unwrap,
    ParseErrorHandler
};
pub use parse_error::ParseError;
pub use meta_rules::{ parse, Rule };

/// The type of debug id used to track down errors in rules.
pub type DebugId = usize;

use std::sync::Arc;
use std::fs::File;
use std::path::Path;
use range::Range;

pub mod bootstrap;
pub mod json;
pub mod meta_rules;
pub mod tokenizer;

mod parse_error;
mod parse_error_handler;

mod all {
    pub use super::*;
}

/// Represents meta data.
#[derive(PartialEq, Clone, Debug)]
pub enum MetaData {
    /// Starts node.
    StartNode(Arc<String>),
    /// Ends node.
    EndNode(Arc<String>),
    /// Sets bool property.
    Bool(Arc<String>, bool),
    /// Sets f64 property.
    F64(Arc<String>, f64),
    /// Sets string property.
    String(Arc<String>, Arc<String>),
}

/// Stores syntax.
#[derive(Clone, Debug, PartialEq)]
pub struct Syntax {
    /// Rule data.
    pub rules: Vec<Rule>,
    /// Name of rules.
    pub names: Vec<Arc<String>>,
}

impl Syntax {
    /// Creates a new syntax.
    pub fn new() -> Syntax {
        Syntax {
            rules: vec![],
            names: vec![]
        }
    }

    /// Adds a new rule.
    pub fn push(&mut self, name: Arc<String>, rule: Rule) {
        self.rules.push(rule);
        self.names.push(name);
    }
}

/// Reads syntax from text.
pub fn syntax(rules: &str) -> Result<Syntax, Range<ParseError>> {
    let mut tokens = vec![];
    try!(parse(&bootstrap::rules(), rules, &mut tokens));
    let mut ignored_meta_data = vec![];
    match bootstrap::convert(&tokens, &mut ignored_meta_data) {
        Ok(res) => Ok(res),
        Err(()) => Err((Range::empty(0).wrap(ParseError::Conversion(
            format!("Bootstrapping rules are incorrect")))))
    }
}

/// Convenience method for loading data, using the meta language.
/// Panics if there is an error, and writes error message to
/// standard error output.
pub fn load_syntax_data<A, B>(
    syntax_path: A,
    data_path: B
) -> Vec<Range<MetaData>>
    where A: AsRef<Path>, B: AsRef<Path>
{
    use std::io::Read;

    let mut syntax_file = File::open(syntax_path).unwrap();
    let mut s = String::new();
    syntax_file.read_to_string(&mut s).unwrap();
    let rules = stderr_unwrap(&s, syntax(&s));

    let mut data_file = File::open(data_path).unwrap();
    let mut d = String::new();
    data_file.read_to_string(&mut d).unwrap();
    let mut tokens = vec![];
    stderr_unwrap(&d, parse(&rules, &d, &mut tokens));
    tokens
}

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

    fn is_thread_safe<T: Send + Sync>() {}

    #[test]
    fn meta_data_thread_safe() {
        is_thread_safe::<MetaData>();
    }

    #[test]
    fn parse_error_thread_safe() {
        is_thread_safe::<ParseError>();
    }

    #[test]
    fn rule_thread_safe() {
        is_thread_safe::<Rule>();
    }

    #[test]
    fn syntax_thread_safe() {
        is_thread_safe::<Syntax>();
    }
}
<|endoftext|>


<commit_before>//! # Packet parsing for the Internet Protocol Suite
//!
//! ## Example usage
//! ```
//! use peel_ip::PeelIp;
//!
//! let mut peel = PeelIp::new();
//! let input = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0];
//! let result = peel.traverse(&input, vec![]).unwrap();
//! assert_eq!(result.len(), 1);
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate log;

#[macro_use]
extern crate nom;
extern crate peel;
extern crate path;

#[macro_use]
pub mod memcmp;

pub mod layer1;
pub mod layer2;
pub mod layer3;
pub mod layer4;

use prelude::*;

/// Provides sensible imports for packet parsers
pub mod prelude {
    pub use std::fmt;
    pub use std::error::Error;
    pub use std::str::{self, FromStr};
    pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

    pub use nom::*;
    pub use path::{Path, Connection, Data, Identifier};
    pub use path::error::ErrorType as PathErrorType;
    pub use peel::prelude::*;
    pub use super::{Layer, ParserVariant, PeelIp};

    /// A shorthand for the `IpProtocol` based `Path`
    pub type PathIp = Path<IpProtocol, ()>;

    /// Link
    pub use layer1::*;
    pub use layer1::ethernet::*;
    pub use layer1::arp::*;

    /// Internet
    pub use layer2::*;
    pub use layer2::ipv4::*;
    pub use layer2::ipv6::*;
    pub use layer2::icmp::*;
    pub use layer2::icmpv6::*;

    // Transport
    pub use layer3::*;
    pub use layer3::tcp::*;
    pub use layer3::tls::*;
    pub use layer3::udp::*;

    // Application
    pub use layer4::http::*;
    pub use layer4::ntp::*;
}

#[derive(Debug)]
/// The return value for the variant retrieval of the Parser trait
pub enum ParserVariant {
    /// Ethernet parser
    Ethernet(EthernetParser),

    /// Address Resolution Protocol parser
    Arp(ArpParser),

    /// Internet Protocol version 4 parser
    Ipv4(Ipv4Parser),

    /// Internet Protocol version 6 parser
    Ipv6(Ipv6Parser),

    /// Internet Control Message Protocol parser
    Icmp(IcmpParser),

    /// Internet Control Message Protocol version 6 parser
    Icmpv6(Icmpv6Parser),

    /// Transmission Control Protocol parser
    Tcp(TcpParser),

    /// Transport Layer Security parser
    Tls(TlsParser),

    /// Hypertext Transfer Protocol parser
    Http(HttpParser),

    /// User Datagram Protocol parser
    Udp(UdpParser),

    /// Network Time Protocol parser
    Ntp(NtpParser),
}

#[derive(Debug, Eq, PartialEq)]
/// Return values for the actual parsers
pub enum Layer {
    /// Ethernet protocol packet variant
    Ethernet(EthernetPacket),

    /// Address Resolution Protocol packet variant
    Arp(ArpPacket),

    /// Internet Protocol version 4 packet variant
    Ipv4(Ipv4Packet),

    /// Internet Protocol version 6 packet variant
    Ipv6(Ipv6Packet),

    /// Internet Control Message Protocol packet variant
    Icmp(IcmpPacket),

    /// Internet Control Message Protocol version 6 packet variant
    Icmpv6(Icmpv6Packet),

    /// Transmission Control Protocol packet variant
    Tcp(TcpPacket),

    /// Transport Layer Security packet variant
    Tls(TlsPacket),

    /// Hypertext Transfer Protocol packet variant
    Http(HttpPacket),

    /// User Datagram Protocol packet variant
    Udp(UdpPacket),

    /// Network Time Protocol packet variant
    Ntp(NtpPacket),
}

macro_rules! impl_fmt_display {
    ($name: ident) => {
        impl fmt::Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $name::Ethernet(_) => write!(f, "Ethernet"),
                    $name::Arp(_) => write!(f, "ARP"),
                    $name::Ipv4(_) => write!(f, "IPv4"),
                    $name::Ipv6(_) => write!(f, "IPv6"),
                    $name::Icmp(_) => write!(f, "ICMP"),
                    $name::Icmpv6(_) => write!(f, "ICMPv6"),
                    $name::Tcp(_) => write!(f, "TCP"),
                    $name::Tls(_) => write!(f, "TLS"),
                    $name::Http(_) => write!(f, "HTTP"),
                    $name::Udp(_) => write!(f, "UDP"),
                    $name::Ntp(_) => write!(f, "NTP"),
                }
            }
        }
    }
}

impl_fmt_display!(Layer);
impl_fmt_display!(ParserVariant);

/// Peel for TCP/IP packets
pub struct PeelIp;

impl PeelIp {
    /// Creates a new `Peel` structure for TCP/IP based packet parsing
    pub fn new() -> Peel<Layer, ParserVariant, PathIp> {
        // Create a tree
        let mut p = Peel::new();

        // Ethernet
        let eth = p.new_parser(EthernetParser);

        // ARP
        p.link_new_parser(eth, ArpParser);

        // IPv4/6
        let ipv4 = p.link_new_parser(eth, Ipv4Parser);
        let ipv6 = p.link_new_parser(eth, Ipv6Parser);
        p.link(ipv4, ipv6);
        p.link(ipv4, ipv4);
        p.link(ipv6, ipv6);

        // ICMP/v6
        p.link_new_parser(ipv4, IcmpParser);
        p.link_new_parser(ipv6, Icmpv6Parser);

        // TCP
        let tcp = p.link_new_parser(ipv4, TcpParser);
        p.link(ipv6, tcp);

        // UDP
        let udp = p.link_new_parser(ipv4, UdpParser);
        p.link(ipv6, udp);

        // TLS
        let tls = p.link_new_parser(tcp, TlsParser);

        // HTTP
        let http = p.link_new_parser(tcp, HttpParser);
        p.link(tls, http);

        // NTP
        p.link_new_parser(udp, NtpParser);

        // Create a path instance
        p.data = Some(Path::new());

        p
    }
}
<commit_msg>Improved internal peel handling<commit_after>//! # Packet parsing for the Internet Protocol Suite
//!
//! ## Example usage
//! ```
//! use peel_ip::PeelIp;
//!
//! let mut peel = PeelIp::new();
//! let input = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0];
//! let result = peel.traverse(&input, vec![]).unwrap();
//! assert_eq!(result.len(), 1);
//! ```
#![deny(missing_docs)]

#[macro_use]
extern crate log;

#[macro_use]
extern crate nom;
extern crate peel;
extern crate path;

#[macro_use]
pub mod memcmp;

pub mod layer1;
pub mod layer2;
pub mod layer3;
pub mod layer4;

use prelude::*;

/// Provides sensible imports for packet parsers
pub mod prelude {
    pub use std::fmt;
    pub use std::error::Error;
    pub use std::str::{self, FromStr};
    pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

    pub use nom::*;
    pub use path::{Path, Connection, Data, Identifier};
    pub use path::error::ErrorType as PathErrorType;
    pub use peel::prelude::*;
    pub use super::{Layer, ParserVariant, PeelIp};

    /// A shorthand for the `IpProtocol` based `Path`
    pub type PathIp = Path<IpProtocol, ()>;

    /// Link
    pub use layer1::*;
    pub use layer1::ethernet::*;
    pub use layer1::arp::*;

    /// Internet
    pub use layer2::*;
    pub use layer2::ipv4::*;
    pub use layer2::ipv6::*;
    pub use layer2::icmp::*;
    pub use layer2::icmpv6::*;

    // Transport
    pub use layer3::*;
    pub use layer3::tcp::*;
    pub use layer3::tls::*;
    pub use layer3::udp::*;

    // Application
    pub use layer4::http::*;
    pub use layer4::ntp::*;
}

#[derive(Debug)]
/// The return value for the variant retrieval of the Parser trait
pub enum ParserVariant {
    /// Ethernet parser
    Ethernet(EthernetParser),

    /// Address Resolution Protocol parser
    Arp(ArpParser),

    /// Internet Protocol version 4 parser
    Ipv4(Ipv4Parser),

    /// Internet Protocol version 6 parser
    Ipv6(Ipv6Parser),

    /// Internet Control Message Protocol parser
    Icmp(IcmpParser),

    /// Internet Control Message Protocol version 6 parser
    Icmpv6(Icmpv6Parser),

    /// Transmission Control Protocol parser
    Tcp(TcpParser),

    /// Transport Layer Security parser
    Tls(TlsParser),

    /// Hypertext Transfer Protocol parser
    Http(HttpParser),

    /// User Datagram Protocol parser
    Udp(UdpParser),

    /// Network Time Protocol parser
    Ntp(NtpParser),
}

#[derive(Debug, Eq, PartialEq)]
/// Return values for the actual parsers
pub enum Layer {
    /// Ethernet protocol packet variant
    Ethernet(EthernetPacket),

    /// Address Resolution Protocol packet variant
    Arp(ArpPacket),

    /// Internet Protocol version 4 packet variant
    Ipv4(Ipv4Packet),

    /// Internet Protocol version 6 packet variant
    Ipv6(Ipv6Packet),

    /// Internet Control Message Protocol packet variant
    Icmp(IcmpPacket),

    /// Internet Control Message Protocol version 6 packet variant
    Icmpv6(Icmpv6Packet),

    /// Transmission Control Protocol packet variant
    Tcp(TcpPacket),

    /// Transport Layer Security packet variant
    Tls(TlsPacket),

    /// Hypertext Transfer Protocol packet variant
    Http(HttpPacket),

    /// User Datagram Protocol packet variant
    Udp(UdpPacket),

    /// Network Time Protocol packet variant
    Ntp(NtpPacket),
}

macro_rules! impl_fmt_display {
    ($name: ident) => {
        impl fmt::Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                match *self {
                    $name::Ethernet(_) => write!(f, "Ethernet"),
                    $name::Arp(_) => write!(f, "ARP"),
                    $name::Ipv4(_) => write!(f, "IPv4"),
                    $name::Ipv6(_) => write!(f, "IPv6"),
                    $name::Icmp(_) => write!(f, "ICMP"),
                    $name::Icmpv6(_) => write!(f, "ICMPv6"),
                    $name::Tcp(_) => write!(f, "TCP"),
                    $name::Tls(_) => write!(f, "TLS"),
                    $name::Http(_) => write!(f, "HTTP"),
                    $name::Udp(_) => write!(f, "UDP"),
                    $name::Ntp(_) => write!(f, "NTP"),
                }
            }
        }
    }
}

impl_fmt_display!(Layer);
impl_fmt_display!(ParserVariant);

/// Peel for TCP/IP packets
pub struct PeelIp {
    /// Internal peel structure
    pub peel: Peel<Layer, ParserVariant, PathIp>,
}

impl PeelIp {
    /// Creates a new `Peel` structure for TCP/IP based packet parsing
    pub fn new() -> PeelIp {
        // Create a tree
        let mut p = Peel::new();

        // Ethernet
        let eth = p.new_parser(EthernetParser);

        // ARP
        p.link_new_parser(eth, ArpParser);

        // IPv4/6
        let ipv4 = p.link_new_parser(eth, Ipv4Parser);
        let ipv6 = p.link_new_parser(eth, Ipv6Parser);
        p.link(ipv4, ipv6);
        p.link(ipv4, ipv4);
        p.link(ipv6, ipv6);

        // ICMP/v6
        p.link_new_parser(ipv4, IcmpParser);
        p.link_new_parser(ipv6, Icmpv6Parser);

        // TCP
        let tcp = p.link_new_parser(ipv4, TcpParser);
        p.link(ipv6, tcp);

        // UDP
        let udp = p.link_new_parser(ipv4, UdpParser);
        p.link(ipv6, udp);

        // TLS
        let tls = p.link_new_parser(tcp, TlsParser);

        // HTTP
        let http = p.link_new_parser(tcp, HttpParser);
        p.link(tls, http);

        // NTP
        p.link_new_parser(udp, NtpParser);

        // Create a path instance
        p.data = Some(Path::new());

        PeelIp { peel: p }
    }

    /// Traverse the parser tree
    pub fn traverse(&mut self, input: &[u8], result: Vec<Layer>) -> PeelResult<Vec<Layer>> {
        self.peel.traverse(input, result)
    }
}
<|endoftext|>


<commit_before>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        ffi::init_parser();
        let mut result = mem::uninitialized();
        query.with_c_str(|query| {
            ffi::parse_query(query, &mut result);
        });
        match result.success != 0 {
            true => Ok(ParseInfo {
                num_params: result.num_params as uint,
            }),
            false => Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            }),
        }
    }
}
<commit_msg>Cleanup and some bug fixes<commit_after>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::c_str::CString;
use std::mem;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: uint,
}

struct ParseError {
    message: CString,
    index: uint,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(query.get()) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(query.get()) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message.as_str().unwrap()).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        let mut result = mem::uninitialized();
        query.with_c_str(|query| ffi::parse_query(query, &mut result));
        if result.success != 0 {
            Ok(ParseInfo {
                num_params: result.num_params as uint,
            })
        } else {
            Err(ParseError {
                message: CString::new(result.error_message, true),
                index: result.index as uint,
            })
        }
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate rand;
extern crate rayon;
extern crate pbr;

use image::{Rgba, RgbaImage, Pixel};

use pbr::ProgressBar;

use rand::Rng;

use rayon::prelude::*;

#[derive(Clone, Copy, Debug)]
pub struct Point {
    x: i32,
    y: i32,
}

impl Point {
    pub fn cross_product(&self, b: Point) -> i32 {
        self.x * b.y - self.y * b.x
    }
}

#[derive(Debug, Copy, Clone)]
struct BoundingBox {
    top_left: Point,
    bottom_right: Point,
}

trait Primitive {
    fn is_inside_primitive(&self, p: Point) -> bool;
    fn bounding_box(&self) -> BoundingBox;
    fn get_color(&self) -> Option<Rgba<u8>>;
    fn set_color(&mut self, color: Rgba<u8>);
}

#[derive(Debug, Copy, Clone)]
struct Triangle {
    a: Point,
    b: Point,
    c: Point,
    color: Option<Rgba<u8>>,

    span_div: Option<f32>,
}

impl Triangle {
    fn new(a: Point, b: Point, c: Point) -> Triangle {
        Triangle {
            a: a,
            b: b,
            c: c,
            color: None,
            span_div: None,
        }
    }

    fn span_div_save(&mut self) {
        self.span_div = Some(self.span_div());
    }

    fn span_div(&self) -> f32 {
        match self.span_div {
            Some(div) => div,
            None => {
                let span_a = Point {
                    x: self.b.x - self.a.x,
                    y: self.b.y - self.a.y,
                };
                let span_b = Point {
                    x: self.c.x - self.a.x,
                    y: self.c.y - self.a.y,
                };

                1.0 / span_a.cross_product(span_b) as f32
            }
        }
    }
}

impl Primitive for Triangle {
    fn is_inside_primitive(&self, p: Point) -> bool {
        let span_a = Point {
            x: self.b.x - self.a.x,
            y: self.b.y - self.a.y,
        };
        let span_b = Point {
            x: self.c.x - self.a.x,
            y: self.c.y - self.a.y,
        };

        let q = Point {
            x: p.x - self.a.x,
            y: p.y - self.a.y,
        };

        let s = q.cross_product(span_b) as f32 * self.span_div();
        let t = span_a.cross_product(q) as f32 * self.span_div();

        (s >= 0.0) && (t >= 0.0) && ((s + t) <= 1.0)
    }

    fn bounding_box(&self) -> BoundingBox {
        use std::cmp::{min, max};
        BoundingBox {
            top_left: Point {
                x: min(min(self.a.x, self.b.x), self.c.x),
                y: min(min(self.a.y, self.b.y), self.c.y),
            },
            bottom_right: Point {
                x: max(max(self.a.x, self.b.x), self.c.x),
                y: max(max(self.a.y, self.b.y), self.c.y),
            },
        }
    }

    fn get_color(&self) -> Option<Rgba<u8>> {
        self.color
    }

    fn set_color(&mut self, color: Rgba<u8>) {
        self.color = Some(color);
    }
}

pub trait PointGenerator {
    fn next_point(&mut self, width: u32, height: u32) -> Point;
}

pub struct RandomPointGenerator {
    rng: Box<Rng>,
}

impl RandomPointGenerator {
    pub fn new() -> RandomPointGenerator {
        RandomPointGenerator { rng: Box::new(rand::weak_rng()) }
    }
}

impl PointGenerator for RandomPointGenerator {
    fn next_point(&mut self, width: u32, height: u32) -> Point {
        Point {
            x: self.rng.gen_range(0, width as i32),
            y: self.rng.gen_range(0, height as i32),
        }
    }
}

pub struct Geometrify {
    point_gen: Box<PointGenerator>,
    iterations: u32,
    samples: u32,
}

impl Geometrify {
    pub fn new(point_gen: Box<PointGenerator>, iterations: u32, samples: u32) -> Geometrify {
        Geometrify {
            point_gen: point_gen,
            iterations: iterations,
            samples: samples,
        }
    }

    pub fn set_iterations(&mut self, iterations: u32) {
        self.iterations = iterations
    }

    pub fn set_samples(&mut self, samples: u32) {
        self.samples = samples
    }

    fn calculate_color(image: &RgbaImage, primitive: &Primitive) -> Rgba<u8> {
        let bb = primitive.bounding_box();

        let mut count = 0u64;
        let mut cr = 0u64;
        let mut cg = 0u64;
        let mut cb = 0u64;
        let mut ca = 0u64;

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let (r, g, b, a) = image.get_pixel(x as u32, y as u32).channels4();
                cr += r as u64;
                cg += g as u64;
                cb += b as u64;
                ca += a as u64;
                count += 1;
            }
        }

        if count == 0 {
            Rgba::from_channels(255, 255, 255, 255)
        } else {
            Rgba::from_channels(
                (cr / count) as u8,
                (cg / count) as u8,
                (cb / count) as u8,
                (ca / count) as u8,
            )
        }
    }

    fn generate_primitive(&mut self, width: u32, height: u32) -> Triangle {
        Triangle::new(
            self.point_gen.next_point(width, height),
            self.point_gen.next_point(width, height),
            self.point_gen.next_point(width, height),
        )
    }

    fn add_to_image(image: &mut RgbaImage, primitive: &Primitive) {
        let bb = primitive.bounding_box();

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let p = Point {
                    x: x as i32,
                    y: y as i32,
                };
                if primitive.is_inside_primitive(p) {
                    *image.get_pixel_mut(x as u32, y as u32) =
                        Geometrify::mix_color(
                            primitive.get_color().expect("color of triangle not set"),
                            *image.get_pixel(x as u32, y as u32),
                        );
                }
            }
        }
    }

    fn mix_color(first: Rgba<u8>, second: Rgba<u8>) -> Rgba<u8> {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();

        Rgba::from_channels(
            ((((r1 as u32 + r2 as u32)) / 2) as u8),
            ((((g1 as u32 + g2 as u32)) / 2) as u8),
            ((((b1 as u32 + b2 as u32)) / 2) as u8),
            ((((a1 as u32 + a2 as u32)) / 2) as u8),
        )
    }

    fn difference(first: Rgba<u8>, second: Rgba<u8>) -> u32 {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();
        let mut d = 0i32;

        d += i32::abs((r1 as i32 - r2 as i32));
        d += i32::abs((g1 as i32 - g2 as i32));
        d += i32::abs((b1 as i32 - b2 as i32));
        d += i32::abs((a1 as i32 - a2 as i32));

        d as u32
    }

    fn calculate_difference(original: &RgbaImage,
                            current: &RgbaImage,
                            diff_lut: &Vec<u64>,
                            primitive: &Primitive)
                            -> u64 {
        let bb = primitive.bounding_box();

        // Use LUT to calculate difference outside of the BB
        // TODO: Check whether indices are correct!
        let mut d = diff_lut[diff_lut.len() - 1];
        if bb.bottom_right.y > 0 && bb.bottom_right.x > 0 {
            d -= diff_lut[((bb.bottom_right.y - 1) as u32 * current.width() +
             bb.bottom_right.x as u32 - 1) as usize];
        }
        if bb.top_left.y > 0 && bb.bottom_right.x > 0 {
            d += diff_lut[((bb.top_left.y - 1) as u32 * current.width() +
             bb.bottom_right.x as u32 - 1) as usize];
        }
        if bb.bottom_right.y > 0 && bb.top_left.x > 0 {
            d += diff_lut[((bb.bottom_right.y - 1) as u32 * current.width() +
             bb.top_left.x as u32 - 1) as usize];
        }
        if bb.top_left.y > 0 && bb.top_left.x > 0 {
            d -= diff_lut[((bb.top_left.y - 1) as u32 * current.width() +
             bb.top_left.x as u32 - 1) as usize];
        }

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let original_rgb = original.get_pixel(x as u32, y as u32);
                let result_rgb = if (bb.top_left.x as u32 <= x as u32) &&
                                    (x as u32 <= bb.bottom_right.x as u32) &&
                                    (bb.top_left.y as u32 <= y as u32) &&
                                    (y as u32 <= bb.bottom_right.y as u32) &&
                                    (primitive.is_inside_primitive(
                    Point {
                        x: x as i32,
                        y: y as i32,
                    }
                )) {
                    Geometrify::mix_color(
                        *current.get_pixel(x as u32, y as u32),
                        primitive.get_color().expect("triangle color not "),
                    )
                } else {
                    *current.get_pixel(x as u32, y as u32)
                };

                d += Geometrify::difference(*original_rgb, result_rgb) as u64;
            }
        }

        d
    }

    fn calculate_difference_lut(a: &RgbaImage, b: &RgbaImage) -> Vec<u64> {
        let mut result = Vec::new();

        for y in 0..a.height() {
            for x in 0..a.width() {
                let mut ldiff = Geometrify::difference(*a.get_pixel(x, y), *b.get_pixel(x, y)) as
                                u64;
                if x > 0 {
                    ldiff += result[(y * a.width() + x - 1) as usize];
                }
                if y > 0 {
                    ldiff += result[((y - 1) * a.width() + x) as usize];
                }
                if x > 0 && y > 0 {
                    ldiff -= result[((y - 1) * a.width() + x - 1) as usize];
                }

                result.push(ldiff);
            }
        }

        result
    }

    pub fn apply(&mut self, image: RgbaImage) -> RgbaImage {
        let mut progress = ProgressBar::new(self.iterations as u64);
        progress.format("|#--|");

        let mut destination = RgbaImage::new(image.width(), image.height());

        for _ in 0..self.iterations {
            let difference_lut = Geometrify::calculate_difference_lut(&image, &destination);

            let primitives = (0..self.samples)
                .map(|_| self.generate_primitive(image.width(), image.height()))
                .map(
                    |mut p| {
                        p.span_div_save();
                        p
                    }
                )
                .collect::<Vec<Triangle>>();
            let min_primitive = primitives
                .par_iter()
                .map(
                    |primitive| {
                        let mut prim = *primitive;
                        prim.color = Some(Geometrify::calculate_color(&image, &prim));
                        (prim,
                         Geometrify::calculate_difference(
                            &image,
                            &destination,
                            &difference_lut,
                            &prim,
                        ))
                    }
                )
                .min_by_key(|tup| tup.1);

            Geometrify::add_to_image(
                &mut destination,
                &min_primitive.expect("no fitting triangle found").0,
            );
            progress.inc();
        }
        progress.finish_print("done");

        destination
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>Fix clippy warnings.<commit_after>extern crate image;
extern crate rand;
extern crate rayon;
extern crate pbr;

use image::{Rgba, RgbaImage, Pixel};

use pbr::ProgressBar;

use rand::Rng;

use rayon::prelude::*;

#[derive(Clone, Copy, Debug)]
pub struct Point {
    x: i32,
    y: i32,
}

impl Point {
    pub fn cross_product(&self, b: Point) -> i32 {
        self.x * b.y - self.y * b.x
    }
}

#[derive(Debug, Copy, Clone)]
struct BoundingBox {
    top_left: Point,
    bottom_right: Point,
}

trait Primitive {
    fn is_inside_primitive(&self, p: Point) -> bool;
    fn bounding_box(&self) -> BoundingBox;
    fn get_color(&self) -> Option<Rgba<u8>>;
    fn set_color(&mut self, color: Rgba<u8>);
}

#[derive(Debug, Copy, Clone)]
struct Triangle {
    a: Point,
    b: Point,
    c: Point,
    color: Option<Rgba<u8>>,

    span_div: Option<f32>,
}

impl Triangle {
    fn new(a: Point, b: Point, c: Point) -> Triangle {
        Triangle {
            a: a,
            b: b,
            c: c,
            color: None,
            span_div: None,
        }
    }

    fn span_div_save(&mut self) {
        self.span_div = Some(self.span_div());
    }

    fn span_div(&self) -> f32 {
        match self.span_div {
            Some(div) => div,
            None => {
                let span_a = Point {
                    x: self.b.x - self.a.x,
                    y: self.b.y - self.a.y,
                };
                let span_b = Point {
                    x: self.c.x - self.a.x,
                    y: self.c.y - self.a.y,
                };

                1.0 / span_a.cross_product(span_b) as f32
            }
        }
    }
}

impl Primitive for Triangle {
    fn is_inside_primitive(&self, p: Point) -> bool {
        let span_a = Point {
            x: self.b.x - self.a.x,
            y: self.b.y - self.a.y,
        };
        let span_b = Point {
            x: self.c.x - self.a.x,
            y: self.c.y - self.a.y,
        };

        let q = Point {
            x: p.x - self.a.x,
            y: p.y - self.a.y,
        };

        let s = q.cross_product(span_b) as f32 * self.span_div();
        let t = span_a.cross_product(q) as f32 * self.span_div();

        (s >= 0.0) && (t >= 0.0) && ((s + t) <= 1.0)
    }

    fn bounding_box(&self) -> BoundingBox {
        use std::cmp::{min, max};
        BoundingBox {
            top_left: Point {
                x: min(min(self.a.x, self.b.x), self.c.x),
                y: min(min(self.a.y, self.b.y), self.c.y),
            },
            bottom_right: Point {
                x: max(max(self.a.x, self.b.x), self.c.x),
                y: max(max(self.a.y, self.b.y), self.c.y),
            },
        }
    }

    fn get_color(&self) -> Option<Rgba<u8>> {
        self.color
    }

    fn set_color(&mut self, color: Rgba<u8>) {
        self.color = Some(color);
    }
}

pub trait PointGenerator {
    fn next_point(&mut self, width: u32, height: u32) -> Point;
}

pub struct RandomPointGenerator {
    rng: Box<Rng>,
}

impl RandomPointGenerator {
    pub fn new() -> RandomPointGenerator {
        RandomPointGenerator { rng: Box::new(rand::weak_rng()) }
    }
}

impl Default for RandomPointGenerator {
    fn default() -> Self {
        RandomPointGenerator::new()
    }
}

impl PointGenerator for RandomPointGenerator {
    fn next_point(&mut self, width: u32, height: u32) -> Point {
        Point {
            x: self.rng.gen_range(0, width as i32),
            y: self.rng.gen_range(0, height as i32),
        }
    }
}

pub struct Geometrify {
    point_gen: Box<PointGenerator>,
    iterations: u32,
    samples: u32,
}

impl Geometrify {
    pub fn new(point_gen: Box<PointGenerator>, iterations: u32, samples: u32) -> Geometrify {
        Geometrify {
            point_gen: point_gen,
            iterations: iterations,
            samples: samples,
        }
    }

    pub fn set_iterations(&mut self, iterations: u32) {
        self.iterations = iterations
    }

    pub fn set_samples(&mut self, samples: u32) {
        self.samples = samples
    }

    fn calculate_color(image: &RgbaImage, primitive: &Primitive) -> Rgba<u8> {
        let bb = primitive.bounding_box();

        let mut count = 0u64;
        let mut cr = 0u64;
        let mut cg = 0u64;
        let mut cb = 0u64;
        let mut ca = 0u64;

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let (r, g, b, a) = image.get_pixel(x as u32, y as u32).channels4();
                cr += r as u64;
                cg += g as u64;
                cb += b as u64;
                ca += a as u64;
                count += 1;
            }
        }

        if count == 0 {
            Rgba::from_channels(255, 255, 255, 255)
        } else {
            Rgba::from_channels(
                (cr / count) as u8,
                (cg / count) as u8,
                (cb / count) as u8,
                (ca / count) as u8,
            )
        }
    }

    fn generate_primitive(&mut self, width: u32, height: u32) -> Triangle {
        Triangle::new(
            self.point_gen.next_point(width, height),
            self.point_gen.next_point(width, height),
            self.point_gen.next_point(width, height),
        )
    }

    fn add_to_image(image: &mut RgbaImage, primitive: &Primitive) {
        let bb = primitive.bounding_box();

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let p = Point {
                    x: x as i32,
                    y: y as i32,
                };
                if primitive.is_inside_primitive(p) {
                    *image.get_pixel_mut(x as u32, y as u32) =
                        Geometrify::mix_color(
                            primitive.get_color().expect("color of triangle not set"),
                            *image.get_pixel(x as u32, y as u32),
                        );
                }
            }
        }
    }

    fn mix_color(first: Rgba<u8>, second: Rgba<u8>) -> Rgba<u8> {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();

        Rgba::from_channels(
            (((r1 as u32 + r2 as u32) / 2) as u8),
            (((g1 as u32 + g2 as u32) / 2) as u8),
            (((b1 as u32 + b2 as u32) / 2) as u8),
            (((a1 as u32 + a2 as u32) / 2) as u8),
        )
    }

    fn difference(first: Rgba<u8>, second: Rgba<u8>) -> u32 {
        let (r1, g1, b1, a1) = first.channels4();
        let (r2, g2, b2, a2) = second.channels4();
        let mut d = 0i32;

        d += i32::abs(r1 as i32 - r2 as i32);
        d += i32::abs(g1 as i32 - g2 as i32);
        d += i32::abs(b1 as i32 - b2 as i32);
        d += i32::abs(a1 as i32 - a2 as i32);

        d as u32
    }

    fn calculate_difference(original: &RgbaImage,
                            current: &RgbaImage,
                            diff_lut: &[u64],
                            primitive: &Primitive)
                            -> u64 {
        let bb = primitive.bounding_box();

        // Use LUT to calculate difference outside of the BB
        // TODO: Check whether indices are correct!
        let mut d = diff_lut[diff_lut.len() - 1];
        if bb.bottom_right.y > 0 && bb.bottom_right.x > 0 {
            d -= diff_lut[((bb.bottom_right.y - 1) as u32 * current.width() +
             bb.bottom_right.x as u32 - 1) as usize];
        }
        if bb.top_left.y > 0 && bb.bottom_right.x > 0 {
            d += diff_lut[((bb.top_left.y - 1) as u32 * current.width() +
             bb.bottom_right.x as u32 - 1) as usize];
        }
        if bb.bottom_right.y > 0 && bb.top_left.x > 0 {
            d += diff_lut[((bb.bottom_right.y - 1) as u32 * current.width() +
             bb.top_left.x as u32 - 1) as usize];
        }
        if bb.top_left.y > 0 && bb.top_left.x > 0 {
            d -= diff_lut[((bb.top_left.y - 1) as u32 * current.width() +
             bb.top_left.x as u32 - 1) as usize];
        }

        for y in bb.top_left.y..bb.bottom_right.y {
            for x in bb.top_left.x..bb.bottom_right.x {
                let original_rgb = original.get_pixel(x as u32, y as u32);
                let result_rgb = if (bb.top_left.x as u32 <= x as u32) &&
                                    (x as u32 <= bb.bottom_right.x as u32) &&
                                    (bb.top_left.y as u32 <= y as u32) &&
                                    (y as u32 <= bb.bottom_right.y as u32) &&
                                    (primitive.is_inside_primitive(
                    Point {
                        x: x as i32,
                        y: y as i32,
                    }
                )) {
                    Geometrify::mix_color(
                        *current.get_pixel(x as u32, y as u32),
                        primitive.get_color().expect("triangle color not "),
                    )
                } else {
                    *current.get_pixel(x as u32, y as u32)
                };

                d += Geometrify::difference(*original_rgb, result_rgb) as u64;
            }
        }

        d
    }

    fn calculate_difference_lut(a: &RgbaImage, b: &RgbaImage) -> Vec<u64> {
        let mut result = Vec::new();

        for y in 0..a.height() {
            for x in 0..a.width() {
                let mut ldiff = Geometrify::difference(*a.get_pixel(x, y), *b.get_pixel(x, y)) as
                                u64;
                if x > 0 {
                    ldiff += result[(y * a.width() + x - 1) as usize];
                }
                if y > 0 {
                    ldiff += result[((y - 1) * a.width() + x) as usize];
                }
                if x > 0 && y > 0 {
                    ldiff -= result[((y - 1) * a.width() + x - 1) as usize];
                }

                result.push(ldiff);
            }
        }

        result
    }

    pub fn apply(&mut self, image: RgbaImage) -> RgbaImage {
        let mut progress = ProgressBar::new(self.iterations as u64);
        progress.format("|#--|");

        let mut destination = RgbaImage::new(image.width(), image.height());

        for _ in 0..self.iterations {
            let difference_lut = Geometrify::calculate_difference_lut(&image, &destination);

            let primitives = (0..self.samples)
                .map(|_| self.generate_primitive(image.width(), image.height()))
                .map(
                    |mut p| {
                        p.span_div_save();
                        p
                    }
                )
                .collect::<Vec<Triangle>>();
            let min_primitive = primitives
                .par_iter()
                .map(
                    |primitive| {
                        let mut prim = *primitive;
                        prim.color = Some(Geometrify::calculate_color(&image, &prim));
                        (prim,
                         Geometrify::calculate_difference(
                            &image,
                            &destination,
                            &difference_lut,
                            &prim,
                        ))
                    }
                )
                .min_by_key(|tup| tup.1);

            Geometrify::add_to_image(
                &mut destination,
                &min_primitive.expect("no fitting triangle found").0,
            );
            progress.inc();
        }
        progress.finish_print("done");

        destination
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>//! ## Defining procedural macros
//!
//! Two crates are required to define a macro.
//!
//! ### The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for example
//! traits or functions or ordinary macros.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//!
//! ```rust
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! #[allow(unused_imports)]
//! #[macro_use]
//! extern crate demo_hack_impl;
//! #[doc(hidden)]
//! pub use demo_hack_impl::*;
//!
//! proc_macro_expr_decl! {
//!     /// Add one to an expression.
//!     add_one! => add_one_impl
//! }
//!
//! proc_macro_item_decl! {
//!     /// A function that always returns 2.
//!     two_fn! => two_fn_impl
//! }
//! # fn main() {}
//! ```
//!
//! ### The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper functions
//! and private modules are fine but nothing can be public.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! proc_macro_expr_impl! {
//!     /// Add one to an expression.
//!     pub fn add_one_impl(input: &str) -> String {
//!         format!("1 + {}", input)
//!     }
//! }
//!
//! proc_macro_item_impl! {
//!     /// A function that always returns 2.
//!     pub fn two_fn_impl(input: &str) -> String {
//!         format!("fn {}() -> u8 {{ 2 }}", input)
//!     }
//! }
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.3"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is a
//! proc macro:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! ## Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your implementation
//! crate), then use your procedural macros as though it were magic. They even get
//! reasonable error messages if your procedural macro panics.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/example
//!
//! ```rust
//! #[macro_use]
//! extern crate demo_hack;
//!
//! two_fn!(two);
//!
//! fn main() {
//!     let x = two();
//!     let nine = add_one!(x) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! ---
//!
//! # Expansion of expression macros
//!
//! ```rust,ignore
//! m!(ARGS)
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     #[derive(m_impl)]
//!     #[allow(unused)]
//!     enum ProcMacroHack {
//!         Input = (stringify!(ARGS), 0).1,
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     macro_rules! proc_macro_call {
//!         () => { RESULT }
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     RESULT
//! }
//! ```
//!
//! # Expansion of item macros
//!
//! ```rust,ignore
//! m!(ARGS);
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! #[derive(m_impl)]
//! #[allow(unused)]
//! enum ProcMacroHack {
//!     Input = (stringify!(ARGS), 0).1,
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! RESULT
//! ```

#[cfg(feature = "proc_macro")]
extern crate proc_macro;

// Allow the "unused" #[macro_use] because there is a different un-ignorable
// warning otherwise:
//
//    proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
#[allow(unused_imports)]
#[macro_use]
extern crate proc_macro_hack_impl;
#[doc(hidden)]
pub use proc_macro_hack_impl::*;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
pub use proc_macro::TokenStream;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        $crate::TokenStream
    }
}

#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        ::proc_macro::TokenStream
    }
}

/// Declare a hacky procedural macro that expands to an expression.
///
/// ```rust
/// # #[macro_use] extern crate proc_macro_hack;
/// proc_macro_expr_decl! {
///     /// Add one to an expression.
///     add_one! => add_one_impl
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! proc_macro_expr_decl {
    (#[$attr:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!((#[$attr]) $($rest)+);
    };
    ($name:ident ! => $name_impl:ident) => {
        proc_macro_expr_decl_helper!(() $name ! => $name_impl);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_expr_decl_helper {
    (($($attrs:tt)*) #[$first:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!(($($attrs)* #[$first]) $($rest)+);
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused, non_camel_case_types)]
        $($attrs)*
        enum $name {
            $name_impl
        }
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident #[$first:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!(($($attrs)*) $name ! => $name_impl);
        proc_macro_expr_decl_helper!((#[$first]) $($rest)+);
    };
}

/// Declare a hacky procedural macro that expands to items.
///
/// ```rust
/// # #[macro_use] extern crate proc_macro_hack;
/// proc_macro_item_decl! {
///     /// A function that always returns 2.
///     two_fn! => two_fn_impl
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! proc_macro_item_decl {
    (#[$attr:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!((#[$attr]) $($rest)+);
    };
    ($name:ident ! => $name_impl:ident) => {
        proc_macro_item_decl_helper!(() $name ! => $name_impl);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_item_decl_helper {
    (($($attrs:tt)*) #[$first:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!(($($attrs)* #[$first]) $($rest)+);
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused, non_camel_case_types)]
        $($attrs)*
        enum $name {
            $name_impl
        }
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident #[$first:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!(($($attrs)*) $name ! => $name_impl);
        proc_macro_item_decl_helper!((#[$first]) $($rest)+);
    };
}

/// Implement a hacky procedural macro that expands to an expression.
///
/// ```rust,ignore
/// proc_macro_expr_impl! {
///     /// Add one to an expression.
///     pub fn add_one_impl(input: &str) -> String {
///         format!("1 + {}", input)
///     }
/// }
/// ```
#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            // Parses an input that looks like:
            //
            // ```
            // #[allow(unused)]
            // enum ProcMacroHack {
            //     Input = (stringify!(ARGS), 0).1,
            // }
            // ```
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                format!("
                    macro_rules! proc_macro_call {{
                        () => {{
                            {}
                        }}
                    }}
                ", func(tokens)).parse().unwrap()
            }
        )+
    }
}

/// Implement a hacky procedural macro that expands to items.
///
/// ```rust,ignore
/// proc_macro_item_impl! {
///     /// A function that always returns 2.
///     pub fn two_fn_impl(input: &str) -> String {
///         format!("fn {}() -> u8 {{ 2 }}", input)
///     }
/// }
/// ```
#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            // Parses an input that looks like:
            //
            // ```
            // #[allow(unused)]
            // enum ProcMacroHack {
            //     Input = (stringify!(ARGS), 0).1,
            // }
            // ```
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                func(tokens).parse().unwrap()
            }
        )+
    }
}
<commit_msg>Be consistent with semicolon in macro rules<commit_after>//! ## Defining procedural macros
//!
//! Two crates are required to define a macro.
//!
//! ### The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for example
//! traits or functions or ordinary macros.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//!
//! ```rust
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! #[allow(unused_imports)]
//! #[macro_use]
//! extern crate demo_hack_impl;
//! #[doc(hidden)]
//! pub use demo_hack_impl::*;
//!
//! proc_macro_expr_decl! {
//!     /// Add one to an expression.
//!     add_one! => add_one_impl
//! }
//!
//! proc_macro_item_decl! {
//!     /// A function that always returns 2.
//!     two_fn! => two_fn_impl
//! }
//! # fn main() {}
//! ```
//!
//! ### The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper functions
//! and private modules are fine but nothing can be public.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate proc_macro_hack;
//!
//! proc_macro_expr_impl! {
//!     /// Add one to an expression.
//!     pub fn add_one_impl(input: &str) -> String {
//!         format!("1 + {}", input)
//!     }
//! }
//!
//! proc_macro_item_impl! {
//!     /// A function that always returns 2.
//!     pub fn two_fn_impl(input: &str) -> String {
//!         format!("fn {}() -> u8 {{ 2 }}", input)
//!     }
//! }
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.3"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is a
//! proc macro:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! ## Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your implementation
//! crate), then use your procedural macros as though it were magic. They even get
//! reasonable error messages if your procedural macro panics.
//!
//! https://github.com/dtolnay/proc-macro-hack/tree/master/example
//!
//! ```rust
//! #[macro_use]
//! extern crate demo_hack;
//!
//! two_fn!(two);
//!
//! fn main() {
//!     let x = two();
//!     let nine = add_one!(x) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! ---
//!
//! # Expansion of expression macros
//!
//! ```rust,ignore
//! m!(ARGS)
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     #[derive(m_impl)]
//!     #[allow(unused)]
//!     enum ProcMacroHack {
//!         Input = (stringify!(ARGS), 0).1,
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     macro_rules! proc_macro_call {
//!         () => { RESULT }
//!     }
//!     proc_macro_call!()
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! {
//!     RESULT
//! }
//! ```
//!
//! # Expansion of item macros
//!
//! ```rust,ignore
//! m!(ARGS);
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! #[derive(m_impl)]
//! #[allow(unused)]
//! enum ProcMacroHack {
//!     Input = (stringify!(ARGS), 0).1,
//! }
//! ```
//!
//! ... expands to ...
//!
//! ```rust,ignore
//! RESULT
//! ```

#[cfg(feature = "proc_macro")]
extern crate proc_macro;

// Allow the "unused" #[macro_use] because there is a different un-ignorable
// warning otherwise:
//
//    proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
#[allow(unused_imports)]
#[macro_use]
extern crate proc_macro_hack_impl;
#[doc(hidden)]
pub use proc_macro_hack_impl::*;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
pub use proc_macro::TokenStream;

#[cfg(feature = "proc_macro")]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        $crate::TokenStream
    };
}

#[cfg(not(feature = "proc_macro"))]
#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_tokenstream {
    () => {
        ::proc_macro::TokenStream
    };
}

/// Declare a hacky procedural macro that expands to an expression.
///
/// ```rust
/// # #[macro_use] extern crate proc_macro_hack;
/// proc_macro_expr_decl! {
///     /// Add one to an expression.
///     add_one! => add_one_impl
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! proc_macro_expr_decl {
    (#[$attr:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!((#[$attr]) $($rest)+);
    };
    ($name:ident ! => $name_impl:ident) => {
        proc_macro_expr_decl_helper!(() $name ! => $name_impl);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_expr_decl_helper {
    (($($attrs:tt)*) #[$first:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!(($($attrs)* #[$first]) $($rest)+);
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackExpr)]
        #[allow(unused, non_camel_case_types)]
        $($attrs)*
        enum $name {
            $name_impl
        }
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident #[$first:meta] $($rest:tt)+) => {
        proc_macro_expr_decl_helper!(($($attrs)*) $name ! => $name_impl);
        proc_macro_expr_decl_helper!((#[$first]) $($rest)+);
    };
}

/// Declare a hacky procedural macro that expands to items.
///
/// ```rust
/// # #[macro_use] extern crate proc_macro_hack;
/// proc_macro_item_decl! {
///     /// A function that always returns 2.
///     two_fn! => two_fn_impl
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! proc_macro_item_decl {
    (#[$attr:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!((#[$attr]) $($rest)+);
    };
    ($name:ident ! => $name_impl:ident) => {
        proc_macro_item_decl_helper!(() $name ! => $name_impl);
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! proc_macro_item_decl_helper {
    (($($attrs:tt)*) #[$first:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!(($($attrs)* #[$first]) $($rest)+);
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident) => {
        #[derive(ProcMacroHackItem)]
        #[allow(unused, non_camel_case_types)]
        $($attrs)*
        enum $name {
            $name_impl
        }
    };
    (($($attrs:tt)*) $name:ident ! => $name_impl:ident #[$first:meta] $($rest:tt)+) => {
        proc_macro_item_decl_helper!(($($attrs)*) $name ! => $name_impl);
        proc_macro_item_decl_helper!((#[$first]) $($rest)+);
    };
}

/// Implement a hacky procedural macro that expands to an expression.
///
/// ```rust,ignore
/// proc_macro_expr_impl! {
///     /// Add one to an expression.
///     pub fn add_one_impl(input: &str) -> String {
///         format!("1 + {}", input)
///     }
/// }
/// ```
#[macro_export]
macro_rules! proc_macro_expr_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            // Parses an input that looks like:
            //
            // ```
            // #[allow(unused)]
            // enum ProcMacroHack {
            //     Input = (stringify!(ARGS), 0).1,
            // }
            // ```
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                format!("
                    macro_rules! proc_macro_call {{
                        () => {{
                            {}
                        }}
                    }}
                ", func(tokens)).parse().unwrap()
            }
        )+
    };
}

/// Implement a hacky procedural macro that expands to items.
///
/// ```rust,ignore
/// proc_macro_item_impl! {
///     /// A function that always returns 2.
///     pub fn two_fn_impl(input: &str) -> String {
///         format!("fn {}() -> u8 {{ 2 }}", input)
///     }
/// }
/// ```
#[macro_export]
macro_rules! proc_macro_item_impl {
    ($(
        $( #[$attr:meta] )*
        pub fn $func:ident($input:ident: &str) -> String $body:block
    )+) => {
        $(
            // Parses an input that looks like:
            //
            // ```
            // #[allow(unused)]
            // enum ProcMacroHack {
            //     Input = (stringify!(ARGS), 0).1,
            // }
            // ```
            $( #[$attr] )*
            #[proc_macro_derive($func)]
            pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
                let source = input.to_string();
                let source = source.trim();

                let prefix = "#[allow(unused)]\nenum ProcMacroHack {";
                let suffix = "}";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "Input =";
                let suffix = "0).1,";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let source = &source[prefix.len() .. source.len() - suffix.len()].trim();

                let prefix = "(stringify!(";
                let suffix = "),";
                assert!(source.starts_with(prefix));
                assert!(source.ends_with(suffix));
                let tokens = &source[prefix.len() .. source.len() - suffix.len()].trim();

                fn func($input: &str) -> String $body

                func(tokens).parse().unwrap()
            }
        )+
    };
}
<|endoftext|>


<commit_before>extern crate x264_sys as ffi;

use std::mem;
use ffi::x264::*;
use std::ptr::null;
use std::os::raw::c_int;

pub struct Picture {
    pic: x264_picture_t,
    height: i32, // to compute the slice dimension
    native: bool,
}

impl Picture {
    /*
    pub fn new() -> Picture {
        let mut pic = unsafe { mem::uninitialized() };

        unsafe { x264_picture_init(&mut pic as *mut x264_picture_t) };

        Picture { pic: pic }
    }
*/
    pub fn from_param(param: &Param) -> Result<Picture, &'static str> {
        let mut pic = unsafe { mem::uninitialized() };

        let ret = unsafe {
            x264_picture_alloc(&mut pic as *mut x264_picture_t,
                               param.par.i_csp,
                               param.par.i_width,
                               param.par.i_height)
        };
        if ret < 0 {
            Err("Allocation Failure")
        } else {
            Ok(Picture {
                   pic: pic,
                   height: param.par.i_height,
                   native: true,
               })
        }
    }

    pub fn as_slice<'a>(&'a self, plane: usize) -> Result<&'a [u8], &'static str> {
        if plane > self.pic.img.i_plane as usize {
            Err("Invalid Argument")
        } else {
            let size = self.height * self.pic.img.i_stride[plane];
            Ok(unsafe { std::slice::from_raw_parts(self.pic.img.plane[plane], size as usize) })
        }
    }

    pub fn as_slice_mut<'a>(&'a mut self, plane: usize) -> Result<&'a mut [u8], &'static str> {
        if plane > self.pic.img.i_plane as usize {
            Err("Invalid Argument")
        } else {
            let size = self.height * self.pic.img.i_stride[plane];
            Ok(unsafe { std::slice::from_raw_parts_mut(self.pic.img.plane[plane], size as usize) })
        }
    }

    pub fn set_timestamp(mut self, pts: i64) -> Picture {
        self.pic.i_pts = pts;
        self
    }
}

impl Drop for Picture {
    fn drop(&mut self) {
        if self.native {
            unsafe { x264_picture_clean(&mut self.pic as *mut x264_picture_t) };
        }
    }
}

// TODO: Provide a builder API instead?
pub struct Param {
    par: x264_param_t,
}

impl Param {
    pub fn new() -> Param {
        let mut par = unsafe { mem::uninitialized() };

        unsafe {
            x264_param_default(&mut par as *mut x264_param_t);
        }

        Param { par: par }
    }
    pub fn default_preset<'a, O>(tune: O, preset: O) -> Result<Param, &'static str>
        where O: Into<Option<&'a str>>
    {
        let mut par = unsafe { mem::uninitialized() };
        let c_tune = tune.into().map_or_else(|| null(), |v| v.as_ptr() as *const i8);
        let c_preset = preset.into().map_or_else(|| null(), |v| v.as_ptr() as *const i8);
        match unsafe {
                  x264_param_default_preset(&mut par as *mut x264_param_t, c_tune, c_preset)
              } {
            -1 => Err("Invalid Argument"),
            0 => Ok(Param { par: par }),
            _ => Err("Unexpected"),
        }
    }
    pub fn apply_profile(mut self, profile: &str) -> Result<Param, &'static str> {
        match unsafe { x264_param_apply_profile(&mut self.par, profile.as_ptr() as *const i8) } {
            -1 => Err("Invalid Argument"),
            0 => Ok(self),
            _ => Err("Unexpected"),
        }
    }
    pub fn param_parse<'a>(mut self, name: &str, value: &str) -> Result<Param, &'static str> {
        match unsafe {
                  x264_param_parse(&mut self.par,
                                   name.as_ptr() as *const i8,
                                   value.as_ptr() as *const i8)
              } {
            -1 => Err("Invalid Argument"),
            0 => Ok(self),
            _ => Err("Unexpected"),
        }
    }
    pub fn set_dimension(mut self, height: usize, width: usize) -> Param {
        self.par.i_height = height as c_int;
        self.par.i_width = width as c_int;

        self
    }
}

// TODO: Expose a NAL abstraction
pub struct NalData {
    vec: Vec<u8>,
}

impl NalData {
    /*
     * x264 functions return x264_nal_t arrays that are valid only until another
     * function of that kind is called.
     *
     * Always copy the data over.
     *
     * TODO: Consider using Bytes as backing store.
     */
    fn from_nals(c_nals: *mut x264_nal_t, nb_nal: usize) -> NalData {
        let mut data = NalData { vec: Vec::new() };

        for i in 0..nb_nal {
            let nal = unsafe { Box::from_raw(c_nals.offset(i as isize)) };

            let payload =
                unsafe { std::slice::from_raw_parts(nal.p_payload, nal.i_payload as usize) };

            data.vec.extend_from_slice(payload);

            mem::forget(payload);
            mem::forget(nal);
        }

        data
    }

    pub fn as_bytes(&self) -> &[u8] {
        self.vec.as_slice()
    }
}

pub struct Encoder {
    enc: *mut x264_t,
}

impl Encoder {
    pub fn open(par: &mut Param) -> Result<Encoder, &'static str> {
        let enc = unsafe { x264_encoder_open(&mut par.par as *mut x264_param_t) };

        if enc.is_null() {
            Err("Out of Memory")
        } else {
            Ok(Encoder { enc: enc })
        }
    }

    pub fn get_headers(&mut self) -> Result<NalData, &'static str> {
        let mut nb_nal: c_int = 0;
        let mut c_nals: *mut x264_nal_t = unsafe { mem::uninitialized() };

        let bytes = unsafe {
            x264_encoder_headers(self.enc,
                                 &mut c_nals as *mut *mut x264_nal_t,
                                 &mut nb_nal as *mut c_int)
        };

        if bytes < 0 {
            Err("Encoding Headers Failed")
        } else {
            Ok(NalData::from_nals(c_nals, nb_nal as usize))
        }
    }

    pub fn encode<'a, P>(&mut self, pic: P) -> Result<Option<(NalData, i64, i64)>, &'static str>
        where P: Into<Option<&'a Picture>>
    {
        let mut pic_out: x264_picture_t = unsafe { mem::uninitialized() };
        let mut c_nals: *mut x264_nal_t = unsafe { mem::uninitialized() };
        let mut nb_nal: c_int = 0;
        let c_pic = pic.into().map_or_else(|| null(), |v| &v.pic as *const x264_picture_t);

        let ret = unsafe {
            x264_encoder_encode(self.enc,
                                &mut c_nals as *mut *mut x264_nal_t,
                                &mut nb_nal as *mut c_int,
                                c_pic as *mut x264_picture_t,
                                &mut pic_out as *mut x264_picture_t)
        };
        if ret < 0 {
            Err("Error encoding")
        } else {
            if nb_nal > 0 {
                let data = NalData::from_nals(c_nals, nb_nal as usize);
                Ok(Some((data, pic_out.i_pts, pic_out.i_dts)))
            } else {
                Ok(None)
            }
        }
    }

    pub fn delayed_frames(&self) -> bool {
        unsafe { x264_encoder_delayed_frames(self.enc) != 0 }
    }
}

impl Drop for Encoder {
    fn drop(&mut self) {
        unsafe { x264_encoder_close(self.enc) };
    }
}

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

    #[test]
    fn test_open() {
        let mut par = Param::new().set_dimension(640, 480);

        let mut enc = Encoder::open(&mut par).unwrap();

        let headers = enc.get_headers().unwrap();

        println!("Headers len {}", headers.as_bytes().len());
    }

    #[test]
    fn test_picture() {
        let par = Param::new().set_dimension(640, 480);
        {
            let mut pic = Picture::from_param(&par).unwrap();
            {
                let p = pic.as_slice_mut(0).unwrap();
                p[0] = 1;
            }
            let p = pic.as_slice(0).unwrap();

            assert_eq!(p[0], 1);
        }
    }

    #[test]
    fn test_encode() {
        let mut par = Param::new().set_dimension(640, 480);
        let mut enc = Encoder::open(&mut par).unwrap();
        let mut pic = Picture::from_param(&par).unwrap();

        let headers = enc.get_headers().unwrap();

        println!("Headers len {}", headers.as_bytes().len());

        for pts in 0..5 {
            pic = pic.set_timestamp(pts as i64);
            let ret = enc.encode(&pic).unwrap();
            match ret {
                Some((_, pts, dts)) => println!("Frame pts {}, dts {}", pts, dts),
                _ => (),
            }
        }

        while enc.delayed_frames() {
            let ret = enc.encode(None).unwrap();
            match ret {
                Some((_, pts, dts)) => println!("Frame pts {}, dts {}", pts, dts),
                _ => (),
            }
        }
    }
}
<commit_msg>param: Use CString<commit_after>extern crate x264_sys as ffi;

use std::mem;
use ffi::x264::*;
use std::ptr::null;
use std::os::raw::c_int;
use std::ffi::CString;

pub struct Picture {
    pic: x264_picture_t,
    height: i32, // to compute the slice dimension
    native: bool,
}

impl Picture {
    /*
    pub fn new() -> Picture {
        let mut pic = unsafe { mem::uninitialized() };

        unsafe { x264_picture_init(&mut pic as *mut x264_picture_t) };

        Picture { pic: pic }
    }
*/
    pub fn from_param(param: &Param) -> Result<Picture, &'static str> {
        let mut pic = unsafe { mem::uninitialized() };

        let ret = unsafe {
            x264_picture_alloc(&mut pic as *mut x264_picture_t,
                               param.par.i_csp,
                               param.par.i_width,
                               param.par.i_height)
        };
        if ret < 0 {
            Err("Allocation Failure")
        } else {
            Ok(Picture {
                   pic: pic,
                   height: param.par.i_height,
                   native: true,
               })
        }
    }

    pub fn as_slice<'a>(&'a self, plane: usize) -> Result<&'a [u8], &'static str> {
        if plane > self.pic.img.i_plane as usize {
            Err("Invalid Argument")
        } else {
            let size = self.height * self.pic.img.i_stride[plane];
            Ok(unsafe { std::slice::from_raw_parts(self.pic.img.plane[plane], size as usize) })
        }
    }

    pub fn as_slice_mut<'a>(&'a mut self, plane: usize) -> Result<&'a mut [u8], &'static str> {
        if plane > self.pic.img.i_plane as usize {
            Err("Invalid Argument")
        } else {
            let size = self.height * self.pic.img.i_stride[plane];
            Ok(unsafe { std::slice::from_raw_parts_mut(self.pic.img.plane[plane], size as usize) })
        }
    }

    pub fn set_timestamp(mut self, pts: i64) -> Picture {
        self.pic.i_pts = pts;
        self
    }
}

impl Drop for Picture {
    fn drop(&mut self) {
        if self.native {
            unsafe { x264_picture_clean(&mut self.pic as *mut x264_picture_t) };
        }
    }
}

// TODO: Provide a builder API instead?
pub struct Param {
    par: x264_param_t,
}

impl Param {
    pub fn new() -> Param {
        let mut par = unsafe { mem::uninitialized() };

        unsafe {
            x264_param_default(&mut par as *mut x264_param_t);
        }

        Param { par: par }
    }
    pub fn default_preset<'a, 'b, Oa, Ob>(tune: Oa, preset: Ob) -> Result<Param, &'static str>
        where Oa: Into<Option<&'a str>>,
              Ob: Into<Option<&'b str>>
    {
        let mut par = unsafe { mem::uninitialized() };
        let t = tune.into().map_or_else(|| None, |v| Some(CString::new(v).unwrap()));
        let p = preset.into().map_or_else(|| None, |v| Some(CString::new(v).unwrap()));

        let c_tune = t.map_or_else(|| null(), |v| v.as_ptr() as *const i8);
        let c_preset = p.map_or_else(|| null(), |v| v.as_ptr() as *const i8);
        match unsafe {
                  x264_param_default_preset(&mut par as *mut x264_param_t, c_tune, c_preset)
              } {
            -1 => Err("Invalid Argument"),
            0 => Ok(Param { par: par }),
            _ => Err("Unexpected"),
        }
    }
    pub fn apply_profile(mut self, profile: &str) -> Result<Param, &'static str> {
        let p = CString::new(profile).unwrap();
        match unsafe { x264_param_apply_profile(&mut self.par, p.as_ptr() as *const i8) } {
            -1 => Err("Invalid Argument"),
            0 => Ok(self),
            _ => Err("Unexpected"),
        }
    }
    pub fn param_parse<'a>(mut self, name: &str, value: &str) -> Result<Param, &'static str> {
        let n = CString::new(name).unwrap();
        let v = CString::new(value).unwrap();
        match unsafe {
                  x264_param_parse(&mut self.par,
                                   n.as_ptr() as *const i8,
                                   v.as_ptr() as *const i8)
              } {
            -1 => Err("Invalid Argument"),
            0 => Ok(self),
            _ => Err("Unexpected"),
        }
    }
    pub fn set_dimension(mut self, height: usize, width: usize) -> Param {
        self.par.i_height = height as c_int;
        self.par.i_width = width as c_int;

        self
    }
}

// TODO: Expose a NAL abstraction
pub struct NalData {
    vec: Vec<u8>,
}

impl NalData {
    /*
     * x264 functions return x264_nal_t arrays that are valid only until another
     * function of that kind is called.
     *
     * Always copy the data over.
     *
     * TODO: Consider using Bytes as backing store.
     */
    fn from_nals(c_nals: *mut x264_nal_t, nb_nal: usize) -> NalData {
        let mut data = NalData { vec: Vec::new() };

        for i in 0..nb_nal {
            let nal = unsafe { Box::from_raw(c_nals.offset(i as isize)) };

            let payload =
                unsafe { std::slice::from_raw_parts(nal.p_payload, nal.i_payload as usize) };

            data.vec.extend_from_slice(payload);

            mem::forget(payload);
            mem::forget(nal);
        }

        data
    }

    pub fn as_bytes(&self) -> &[u8] {
        self.vec.as_slice()
    }
}

pub struct Encoder {
    enc: *mut x264_t,
}

impl Encoder {
    pub fn open(par: &mut Param) -> Result<Encoder, &'static str> {
        let enc = unsafe { x264_encoder_open(&mut par.par as *mut x264_param_t) };

        if enc.is_null() {
            Err("Out of Memory")
        } else {
            Ok(Encoder { enc: enc })
        }
    }

    pub fn get_headers(&mut self) -> Result<NalData, &'static str> {
        let mut nb_nal: c_int = 0;
        let mut c_nals: *mut x264_nal_t = unsafe { mem::uninitialized() };

        let bytes = unsafe {
            x264_encoder_headers(self.enc,
                                 &mut c_nals as *mut *mut x264_nal_t,
                                 &mut nb_nal as *mut c_int)
        };

        if bytes < 0 {
            Err("Encoding Headers Failed")
        } else {
            Ok(NalData::from_nals(c_nals, nb_nal as usize))
        }
    }

    pub fn encode<'a, P>(&mut self, pic: P) -> Result<Option<(NalData, i64, i64)>, &'static str>
        where P: Into<Option<&'a Picture>>
    {
        let mut pic_out: x264_picture_t = unsafe { mem::uninitialized() };
        let mut c_nals: *mut x264_nal_t = unsafe { mem::uninitialized() };
        let mut nb_nal: c_int = 0;
        let c_pic = pic.into().map_or_else(|| null(), |v| &v.pic as *const x264_picture_t);

        let ret = unsafe {
            x264_encoder_encode(self.enc,
                                &mut c_nals as *mut *mut x264_nal_t,
                                &mut nb_nal as *mut c_int,
                                c_pic as *mut x264_picture_t,
                                &mut pic_out as *mut x264_picture_t)
        };
        if ret < 0 {
            Err("Error encoding")
        } else {
            if nb_nal > 0 {
                let data = NalData::from_nals(c_nals, nb_nal as usize);
                Ok(Some((data, pic_out.i_pts, pic_out.i_dts)))
            } else {
                Ok(None)
            }
        }
    }

    pub fn delayed_frames(&self) -> bool {
        unsafe { x264_encoder_delayed_frames(self.enc) != 0 }
    }
}

impl Drop for Encoder {
    fn drop(&mut self) {
        unsafe { x264_encoder_close(self.enc) };
    }
}

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

    #[test]
    fn test_open() {
        let mut par = Param::new().set_dimension(640, 480);

        let mut enc = Encoder::open(&mut par).unwrap();

        let headers = enc.get_headers().unwrap();

        println!("Headers len {}", headers.as_bytes().len());
    }

    #[test]
    fn test_picture() {
        let par = Param::new().set_dimension(640, 480);
        {
            let mut pic = Picture::from_param(&par).unwrap();
            {
                let p = pic.as_slice_mut(0).unwrap();
                p[0] = 1;
            }
            let p = pic.as_slice(0).unwrap();

            assert_eq!(p[0], 1);
        }
    }

    #[test]
    fn test_encode() {
        let mut par = Param::new().set_dimension(640, 480);
        let mut enc = Encoder::open(&mut par).unwrap();
        let mut pic = Picture::from_param(&par).unwrap();

        let headers = enc.get_headers().unwrap();

        println!("Headers len {}", headers.as_bytes().len());

        for pts in 0..5 {
            pic = pic.set_timestamp(pts as i64);
            let ret = enc.encode(&pic).unwrap();
            match ret {
                Some((_, pts, dts)) => println!("Frame pts {}, dts {}", pts, dts),
                _ => (),
            }
        }

        while enc.delayed_frames() {
            let ret = enc.encode(None).unwrap();
            match ret {
                Some((_, pts, dts)) => println!("Frame pts {}, dts {}", pts, dts),
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! natural_constants: a collection of constants and helper functions
//!
//! Written by Willi Kappler, Version 0.1 (2016.06.13)
//!
//! Repository: https://github.com/willi-kappler/natural_constants
//!
//! License: MIT
//!

// For clippy
// #![feature(plugin)]
//
// #![plugin(clippy)]

#![allow(non_upper_case_globals)]
#![allow(dead_code)]

pub mod math;
pub mod physics;
pub mod chemistry;
pub mod biology;
pub mod engineering;
pub mod conversion;
pub mod units;
<commit_msg>remove mod units<commit_after>//! natural_constants: a collection of constants and helper functions
//!
//! Written by Willi Kappler, Version 0.1 (2016.06.13)
//!
//! Repository: https://github.com/willi-kappler/natural_constants
//!
//! License: MIT
//!

// For clippy
// #![feature(plugin)]
//
// #![plugin(clippy)]

#![allow(non_upper_case_globals)]
#![allow(dead_code)]

pub mod math;
pub mod physics;
pub mod chemistry;
pub mod biology;
pub mod engineering;
pub mod conversion;
<|endoftext|>