<commit_before>use std::collections::HashMap;
use std::io::{self, File};
use src;
use ty;
use ty::Type;

fn convert_naive(w: &mut Writer, in_: &ty::Type, out: &ty::Type, cfgs: &[String]) {
    assert!(in_.count == out.count);
    let count = in_.count;
    let header = src::impl_header("::Convert", true, in_, Some(out));
    write!(w, "\
#[cfg(not(any({cfg})))]
{header}
    #[inline(always)] fn convert(self) -> {out} {{ ",
           cfg = cfgs.connect(","), header = header, out = out.name).unwrap();

    if count == 1 {
        write!(w, "self as {out}", out = out.name).unwrap();
    } else {
        write!(w,
               "let (a, b) = ::HalfVector::split(self); \
               <<{out} as ::HalfVector>::Half as ::DoubleVector>::merge(a.convert(), b.convert())",
               out = out.name).unwrap();
    }
    writeln!(w," }}\n}}").unwrap();

}

#[derive(Copy)]
enum Promotion {
    None,
    DoubleInput,
    HalveOutput,
}

fn convert_x86(w: &mut Writer,
               in_: &ty::Type, out: &ty::Type,
               instr: &str, promote: Promotion) -> String {
    let name = &instr[..instr.bytes().position(|b| b == b'_').unwrap()];
    let x86_64 = match name {
        "sse" | "sse2" => "target_arch = \"x86_64\",",
        _ => ""
    };
    let cfg = format!("any({x86_64}feature=\"{name}\")", x86_64 = x86_64, name = name);

    let (input, output) = match promote {
        Promotion::None => ("", ""),
        Promotion::DoubleInput => (".merge(::std::mem::uninitialized())", ""),
        Promotion::HalveOutput => ("", ".lower()"),
    };

    writeln!(w,"\
#[cfg({cfg})]
{header}
    #[inline(always)] fn convert(self) -> {out} {{
        (unsafe {{ ::llvmint::x86::{instr}(self{input}) }}){output}
    }}
}}",
             cfg = cfg,
             header = src::impl_header("::Convert", true, in_, Some(out)),
             input = input, output = output,
             out = out.name,
             instr = instr).unwrap();

    cfg
}

macro_rules! special_cases {
    ($($count: expr, $in_: ident $iwidth: expr, $out: ident $owidth: expr,
       $instr: expr, $promote: ident);*;) => {{
        let mut map = HashMap::new();
        $(
            map.insert((Type::new(stringify!($in_), $iwidth, $count),
                        Type::new(stringify!($out), $owidth, $count)),
                       ($instr, Promotion::$promote));
            )*
            map
    }}
}
pub fn convert_impls(tys: &ty::Types, dst: &Path) {
    io::fs::mkdir_recursive(&dst.join("convert_impls"), io::USER_RWX).unwrap();
    let mut out = File::create(&dst.join("convert_impls/mod.rs")).unwrap();

    writeln!(&mut out, "mod naive;").unwrap();
    let mut naive = File::create(&dst.join("convert_impls/naive.rs")).unwrap();
    writeln!(&mut naive, "#![cfg(not(feature = \"no_naive\"))]").unwrap();

    writeln!(&mut out, "mod x86;").unwrap();
    let mut x86 = File::create(&dst.join("convert_impls/x86.rs")).unwrap();
    writeln!(&mut x86, "#![cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))]").unwrap();

    writeln!(&mut out, "mod arm;").unwrap();
    let mut arm = File::create(&dst.join("convert_impls/arm.rs")).unwrap();
    writeln!(&mut arm, "#![cfg(any(target_arch = \"arm\"))]").unwrap();

    let x86_special = special_cases! {

        4, i 32, f 32, "sse2_cvtdq2ps", None;
        4, f 32, i 32, "sse2_cvttps2dq", None;

        4, i 32, f 64, "avx_cvtdq2_pd_256", None;
        4, f 64, i 32, "avx_cvtt_pd2dq_256", None;
        4, f 64, f 32, "avx_cvt_pd2_ps_256", None;
        4, f 32, f 64, "avx_cvt_ps2_pd_256", None;

        8, i 32, f 32, "avx_cvtdq2_ps_256", None;
        8, f 32, i 32, "avx_cvtt_ps2dq_256", None;
    };

    let mut cfgs = vec![];
    for (count, types) in tys.by_count.iter() {
        for i in types.iter() {
            for o in types.iter() {
                let pair = (i.clone(), o.clone());
                cfgs.clear();
                if let Some(&(instr, promote)) = x86_special.get(&pair) {
                    cfgs.push(convert_x86(&mut x86, i, o, instr, promote));
                }

                if *count == 1 {
                    convert_naive(&mut out, i, o, &cfgs[]);
                } else {
                    convert_naive(&mut naive, i, o, &cfgs[]);
                }
            }
        }
    }
}
<commit_msg>Add more x86 conversions.<commit_after>use std::collections::HashMap;
use std::io::{self, File};
use src;
use ty;
use ty::Type;

fn convert_naive(w: &mut Writer, in_: &ty::Type, out: &ty::Type, cfgs: &[String]) {
    assert!(in_.count == out.count);
    let count = in_.count;
    let header = src::impl_header("::Convert", true, in_, Some(out));
    write!(w, "\
#[cfg(not(any({cfg})))]
{header}
    #[inline(always)] fn convert(self) -> {out} {{ ",
           cfg = cfgs.connect(","), header = header, out = out.name).unwrap();

    if count == 1 {
        write!(w, "self as {out}", out = out.name).unwrap();
    } else {
        write!(w,
               "let (a, b) = ::HalfVector::split(self); \
               <<{out} as ::HalfVector>::Half as ::DoubleVector>::merge(a.convert(), b.convert())",
               out = out.name).unwrap();
    }
    writeln!(w," }}\n}}").unwrap();

}

#[derive(Copy)]
enum Promotion {
    None,
    DoubleInput,
    HalveOutput,
}

fn convert_x86(w: &mut Writer,
               in_: &ty::Type, out: &ty::Type,
               instr: &str, promote: Promotion) -> String {
    let name = &instr[..instr.bytes().position(|b| b == b'_').unwrap()];
    let x86_64 = match name {
        "sse" | "sse2" => "target_arch = \"x86_64\",",
        _ => ""
    };
    let cfg = format!("any({x86_64}feature=\"{name}\")", x86_64 = x86_64, name = name);

    let (input, output) = match promote {
        Promotion::None => ("", ""),
        Promotion::DoubleInput => (".merge(::std::mem::uninitialized())", ""),
        Promotion::HalveOutput => ("", ".lower()"),
    };

    writeln!(w,"\
#[cfg({cfg})]
{header}
    #[inline(always)] fn convert(self) -> {out} {{
        (unsafe {{ ::llvmint::x86::{instr}(self{input}) }}){output}
    }}
}}",
             cfg = cfg,
             header = src::impl_header("::Convert", true, in_, Some(out)),
             input = input, output = output,
             out = out.name,
             instr = instr).unwrap();

    cfg
}

macro_rules! special_cases {
    ($($count: expr, $in_: ident $iwidth: expr, $out: ident $owidth: expr,
       $instr: expr, $promote: ident);*;) => {{
        let mut map = HashMap::new();
        $(
            map.insert((Type::new(stringify!($in_), $iwidth, $count),
                        Type::new(stringify!($out), $owidth, $count)),
                       ($instr, Promotion::$promote));
            )*
            map
    }}
}
pub fn convert_impls(tys: &ty::Types, dst: &Path) {
    io::fs::mkdir_recursive(&dst.join("convert_impls"), io::USER_RWX).unwrap();
    let mut out = File::create(&dst.join("convert_impls/mod.rs")).unwrap();

    writeln!(&mut out, "mod naive;").unwrap();
    let mut naive = File::create(&dst.join("convert_impls/naive.rs")).unwrap();
    writeln!(&mut naive, "#![cfg(not(feature = \"no_naive\"))]").unwrap();

    writeln!(&mut out, "mod x86;").unwrap();
    let mut x86 = File::create(&dst.join("convert_impls/x86.rs")).unwrap();
    writeln!(&mut x86, "#![cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))]").unwrap();

    writeln!(&mut out, "mod arm;").unwrap();
    let mut arm = File::create(&dst.join("convert_impls/arm.rs")).unwrap();
    writeln!(&mut arm, "#![cfg(any(target_arch = \"arm\"))]").unwrap();

    let x86_special = special_cases! {
        2, i 32, f 64, "sse2_cvtdq2pd", DoubleInput;
        2, f 64, i 32, "sse2_cvttpd2dq", HalveOutput;
        2, f 32, f 64, "sse2_cvtps2pd", DoubleInput;
        2, f 64, f 32, "sse2_cvtpd2ps", HalveOutput;

        4, i 32, f 32, "sse2_cvtdq2ps", None;
        4, f 32, i 32, "sse2_cvttps2dq", None;

        4, i 32, f 64, "avx_cvtdq2_pd_256", None;
        4, f 64, i 32, "avx_cvtt_pd2dq_256", None;
        4, f 64, f 32, "avx_cvt_pd2_ps_256", None;
        4, f 32, f 64, "avx_cvt_ps2_pd_256", None;

        8, i 32, f 32, "avx_cvtdq2_ps_256", None;
        8, f 32, i 32, "avx_cvtt_ps2dq_256", None;
    };

    let mut cfgs = vec![];
    for (count, types) in tys.by_count.iter() {
        for i in types.iter() {
            for o in types.iter() {
                let pair = (i.clone(), o.clone());
                cfgs.clear();
                if let Some(&(instr, promote)) = x86_special.get(&pair) {
                    cfgs.push(convert_x86(&mut x86, i, o, instr, promote));
                }

                if *count == 1 {
                    convert_naive(&mut out, i, o, &cfgs[]);
                } else {
                    convert_naive(&mut naive, i, o, &cfgs[]);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate crc;

use std::io::{ BufRead, BufReader, Read };
use std::fs::File;
use std::path::Path;

use self::crc::{crc32, Hasher32};

pub fn verify_file_crc32(file: &File) -> u32
{
    let mut digest = crc32::Digest::new(crc32::IEEE);

    for line in file.bytes() {
        digest.write(&[line.unwrap()]);
    }

    digest.sum32()
}<commit_msg>Format code.<commit_after>extern crate crc;

use std::io::{ BufRead, BufReader, Read };
use std::fs::File;
use std::path::Path;
use self::crc::{crc32, Hasher32};

pub fn verify_file_crc32(file: &File) -> u32
{
    let mut digest = crc32::Digest::new(crc32::IEEE);

    for line in file.bytes() {
        digest.write(&[line.unwrap()]);
    }

    return digest.sum32();
}<|endoftext|>


<commit_before>extern crate iron;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, Ingot, Furnace, Alloy, Request, Response, ServerT};
use iron::ingot::{Status, Continue};

#[deriving(Clone)]
struct HelloWorld;

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
    fn enter(&mut self, _request: &mut Rq, response: &mut Rs, _alloy: &mut Alloy) -> Status {
        let _ = response.write(bytes!("Hello World!"));
        Continue
    }
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.smelt(HelloWorld);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<commit_msg>(cleanup) Refactored example to work with new API.<commit_after>extern crate iron;

use std::io::net::ip::Ipv4Addr;

use iron::{Ingot, Iron, Alloy, Request, Response, ServerT};
use iron::ingot::{Status, Continue};

#[deriving(Clone)]
struct HelloWorld;

impl Ingot for HelloWorld {
    fn enter(&mut self,
             _request: &mut Request,
             response: &mut Response,
             _alloy: &mut Alloy) -> Status {
        let _ = response.write(bytes!("Hello World!"));
        Continue
    }
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.smelt(HelloWorld);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<|endoftext|>


<commit_before>extern crate http;
extern crate iron;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, Chain, Alloy, Request, Response, ServerT};
use iron::mixin::Serve;
use iron::middleware::{Status, Continue};

fn hello_world(_req: &mut Request, res: &mut Response, _alloy: &mut Alloy) -> Status {
    let _ = res.serve(::http::status::Ok, "Hello, world!");
    Continue
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.chain.link(hello_world);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<commit_msg>(fix) Updated example to FromFn<commit_after>extern crate http;
extern crate iron;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, Chain, Alloy, Request, Response, ServerT};
use iron::mixin::Serve;
use iron::middleware::{Status, Continue, FromFn};

fn hello_world(_req: &mut Request, res: &mut Response, _alloy: &mut Alloy) -> Status {
    let _ = res.serve(::http::status::Ok, "Hello, world!");
    Continue
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.chain.link(FromFn::new(hello_world));
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<|endoftext|>


<commit_before>extern crate polydraw;

use std::env;
use std::io::prelude::*;
use std::fs::File;

use polydraw::Application;
use polydraw::lang::LangRenderer;

fn main() {
   let filename = match env::args().nth(1) {
      Some(filename) => filename,
      None => {
         println!("No source file specified");
         return;
      }
   };

   let mut f = match File::open(&filename) {
      Ok(f) => f,
      Err(_) => {
         println!("Cannot open {}", &filename);
         return;
      }
   };

   let mut source = String::new();

   f.read_to_string(&mut source).unwrap();

   let mut renderer = match LangRenderer::new(&source) {
      Ok(renderer) => renderer,
      Err(err) => {
         println!("Error: {:?}", err);
         return;
      }
   };

   Application::new()
      .renderer(&mut renderer)
      .title("Scene")
      .size(800, 450)
      .run();
}
<commit_msg>Error printing fix<commit_after>extern crate polydraw;

use std::env;
use std::io::prelude::*;
use std::fs::File;

use polydraw::Application;
use polydraw::lang::LangRenderer;

fn main() {
   let filename = match env::args().nth(1) {
      Some(filename) => filename,
      None => {
         println!("No source file specified");
         return;
      }
   };

   let mut f = match File::open(&filename) {
      Ok(f) => f,
      Err(_) => {
         println!("Cannot open {}", &filename);
         return;
      }
   };

   let mut source = String::new();

   f.read_to_string(&mut source).unwrap();

   let mut renderer = match LangRenderer::new(&source) {
      Ok(renderer) => renderer,
      Err(err) => {
         println!("Error: {}", err);
         return;
      }
   };

   Application::new()
      .renderer(&mut renderer)
      .title("Scene")
      .size(800, 450)
      .run();
}
<|endoftext|>


<commit_before>//! Parses "match" queries

use rustc_serialize::json::Json;
use abra::{Term, Analyzer, Query, TermMatcher, TermScorer};

use mapping::FieldMapping;

use query_parser::{QueryParseContext, QueryParseError};
use query_parser::utils::{parse_string, parse_float, Operator, parse_operator};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    let field_name = if object.len() == 1 {
        object.keys().collect::<Vec<_>>()[0]
    } else {
        return Err(QueryParseError::ExpectedSingleKey)
    };

    // Get mapping for field
    let field_mapping = match context.mappings {
        Some(mappings) => mappings.get_field(field_name),
        None => None,
    };

    // Get configuration
    let mut query = Json::Null;
    let mut boost = 1.0f64;
    let mut operator = Operator::Or;

    match object[field_name] {
        Json::String(ref string) => query = object[field_name].clone(),
        Json::Object(ref inner_object) => {
            let mut has_query_key = false;

            for (key, value) in inner_object.iter() {
                match key.as_ref() {
                    "query" => {
                        has_query_key = true;
                        query = value.clone();
                    }
                    "boost" => {
                        boost = try!(parse_float(value));
                    }
                    "operator" => {
                        operator = try!(parse_operator(value))
                    }
                    _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
                }
            }

            if !has_query_key {
                return Err(QueryParseError::ExpectedKey("query"))
            }
        }
        _ => return Err(QueryParseError::ExpectedObjectOrString),
    }

    // Tokenise query string
    let tokens = match field_mapping {
        Some(ref field_mapping) => {
            field_mapping.process_value_for_query(query.clone())
        }
        None => {
            // TODO: Raise error?
            warn!("Unknown field: {}", field_name);

            FieldMapping::default().process_value_for_query(query.clone())
        }
    };

    let tokens = match tokens {
        Some(tokens) => tokens,
        None => {
            // Couldn't convert the passed in value into tokens
            // TODO: Raise error
            warn!("Unprocessable query: {}", query);

            return Ok(Query::MatchNone);
        }
    };

    // Create a term query for each token
    let mut sub_queries = Vec::new();
    for token in tokens {
        sub_queries.push(Query::MatchTerm {
            field: field_name.clone(),
            term: token.term,
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default(),
        });
    }

    // Combine the term queries
    let mut query = match operator {
        Operator::Or => {
            Query::new_disjunction(sub_queries)
        }
        Operator::And => {
            Query::new_conjunction(sub_queries)
        }
    };

    // Add boost
    query = Query::new_boost(query, boost);

    return Ok(query);
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use abra::{Term, Query, TermMatcher, TermScorer};

    use query_parser::{QueryParseContext, QueryParseError};

    use super::parse;

    #[test]
    fn test_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchTerm {
            field: "foo".to_string(),
            term: Term::String("bar".to_string()),
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default(),
        }))
    }

    #[test]
    fn test_multi_term_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar baz\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Disjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_simple_multi_term_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": \"bar baz\"
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Disjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_with_boost() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": 2.0
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Boost {
            query: Box::new(Query::MatchTerm {
                field: "foo".to_string(),
                term: Term::String("bar".to_string()),
                matcher: TermMatcher::Exact,
                scorer: TermScorer::default(),
            }),
            boost: 2.0f64,
        }))
    }

    #[test]
    fn test_with_boost_integer() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": 2
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Boost {
            query: Box::new(Query::MatchTerm {
                field: "foo".to_string(),
                term: Term::String("bar".to_string()),
                matcher: TermMatcher::Exact,
                scorer: TermScorer::default(),
            }),
            boost: 2.0f64,
        }))
    }

    #[test]
    fn test_with_and_operator() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar baz\",
                \"operator\": \"and\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Conjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // Array
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_incorrect_boost_type() {
        // String
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": \"2\"
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));

        // Array
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": [2]
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));

        // Object
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": {
                    \"value\": 2
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));
    }

    #[test]
    fn test_gives_error_for_missing_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedKey("query")));
    }

    #[test]
    fn test_gives_error_for_extra_key() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\"
            },
            \"hello\": \"world\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedSingleKey));
    }

    #[test]
    fn test_gives_error_for_extra_inner_key() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"hello\": \"world\"
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::UnrecognisedKey("hello".to_string())));
    }
}
<commit_msg>Use new boosting method in match query<commit_after>//! Parses "match" queries

use rustc_serialize::json::Json;
use abra::{Term, Analyzer, Query, TermMatcher, TermScorer};

use mapping::FieldMapping;

use query_parser::{QueryParseContext, QueryParseError};
use query_parser::utils::{parse_string, parse_float, Operator, parse_operator};

pub fn parse(context: &QueryParseContext, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    let field_name = if object.len() == 1 {
        object.keys().collect::<Vec<_>>()[0]
    } else {
        return Err(QueryParseError::ExpectedSingleKey)
    };

    // Get mapping for field
    let field_mapping = match context.mappings {
        Some(mappings) => mappings.get_field(field_name),
        None => None,
    };

    // Get configuration
    let mut query = Json::Null;
    let mut boost = 1.0f64;
    let mut operator = Operator::Or;

    match object[field_name] {
        Json::String(ref string) => query = object[field_name].clone(),
        Json::Object(ref inner_object) => {
            let mut has_query_key = false;

            for (key, value) in inner_object.iter() {
                match key.as_ref() {
                    "query" => {
                        has_query_key = true;
                        query = value.clone();
                    }
                    "boost" => {
                        boost = try!(parse_float(value));
                    }
                    "operator" => {
                        operator = try!(parse_operator(value))
                    }
                    _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
                }
            }

            if !has_query_key {
                return Err(QueryParseError::ExpectedKey("query"))
            }
        }
        _ => return Err(QueryParseError::ExpectedObjectOrString),
    }

    // Tokenise query string
    let tokens = match field_mapping {
        Some(ref field_mapping) => {
            field_mapping.process_value_for_query(query.clone())
        }
        None => {
            // TODO: Raise error?
            warn!("Unknown field: {}", field_name);

            FieldMapping::default().process_value_for_query(query.clone())
        }
    };

    let tokens = match tokens {
        Some(tokens) => tokens,
        None => {
            // Couldn't convert the passed in value into tokens
            // TODO: Raise error
            warn!("Unprocessable query: {}", query);

            return Ok(Query::MatchNone);
        }
    };

    // Create a term query for each token
    let mut sub_queries = Vec::new();
    for token in tokens {
        sub_queries.push(Query::MatchTerm {
            field: field_name.clone(),
            term: token.term,
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default(),
        });
    }

    // Combine the term queries
    let mut query = match operator {
        Operator::Or => {
            Query::new_disjunction(sub_queries)
        }
        Operator::And => {
            Query::new_conjunction(sub_queries)
        }
    };

    // Add boost
    query.boost(boost);

    return Ok(query);
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;

    use abra::{Term, Query, TermMatcher, TermScorer};

    use query_parser::{QueryParseContext, QueryParseError};

    use super::parse;

    #[test]
    fn test_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchTerm {
            field: "foo".to_string(),
            term: Term::String("bar".to_string()),
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default(),
        }))
    }

    #[test]
    fn test_multi_term_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar baz\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Disjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_simple_multi_term_match_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": \"bar baz\"
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Disjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_with_boost() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": 2.0
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchTerm {
            field: "foo".to_string(),
            term: Term::String("bar".to_string()),
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default_with_boost(2.0f64),
        }))
    }

    #[test]
    fn test_with_boost_integer() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": 2
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchTerm {
            field: "foo".to_string(),
            term: Term::String("bar".to_string()),
            matcher: TermMatcher::Exact,
            scorer: TermScorer::default_with_boost(2.0f64),
        }))
    }

    #[test]
    fn test_with_and_operator() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar baz\",
                \"operator\": \"and\"
            }
        }
        ").unwrap());

        assert_eq!(query, Ok(Query::Conjunction {
            queries: vec![
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("bar".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                },
                Query::MatchTerm {
                    field: "foo".to_string(),
                    term: Term::String("baz".to_string()),
                    matcher: TermMatcher::Exact,
                    scorer: TermScorer::default(),
                }
            ],
        }))
    }

    #[test]
    fn test_gives_error_for_incorrect_type() {
        // Array
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        [
            \"foo\"
        ]
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Integer
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        123
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));

        // Float
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        123.1234
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedObject));
    }

    #[test]
    fn test_gives_error_for_incorrect_boost_type() {
        // String
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": \"2\"
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));

        // Array
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": [2]
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));

        // Object
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"boost\": {
                    \"value\": 2
                }
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedFloat));
    }

    #[test]
    fn test_gives_error_for_missing_query() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedKey("query")));
    }

    #[test]
    fn test_gives_error_for_extra_key() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\"
            },
            \"hello\": \"world\"
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::ExpectedSingleKey));
    }

    #[test]
    fn test_gives_error_for_extra_inner_key() {
        let query = parse(&QueryParseContext::new(), &Json::from_str("
        {
            \"foo\": {
                \"query\": \"bar\",
                \"hello\": \"world\"
            }
        }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::UnrecognisedKey("hello".to_string())));
    }
}
<|endoftext|>


<commit_before>use nalgebra::Vector2;
use std::cmp::max;
use super::rounding_error_tolerant_math::*;
use std::ops::{Add, Sub, Mul, Neg};
use array_ext::*;

pub type Time = i64;

pub trait Vector: Clone + Add <Self, Output = Self> + Sub <Self, Output = Self> + Mul <i64, Output = Self> + Zero +

macro_rules! impl_trajectory_binop {
  ($Trajectory: ident, $Trait: ident, $method: ident) => {

impl <Vector: Clone + $Trait <Vector, Output = Vector>> $Trait for $Trajectory <Vector> {
  type Output = Self;
  fn $method (self, other: Self)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().$method (other.terms [index].clone())),
    }
  }
}

impl <'a, Vector: Clone + $Trait <& 'a Vector, Output = Vector>> $Trait <& 'a $Trajectory <Vector>> for $Trajectory <Vector> {
  type Output = Self;
  fn $method (self, other: & 'a $Trajectory <Vector>)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().$method (& other.terms [index])),
    }
  }
}

impl <'a, Vector: Clone> $Trait <$Trajectory <Vector>> for & 'a $Trajectory <Vector> where & 'a Vector: $Trait <Vector, Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn $method (self, other: $Trajectory <Vector>)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).$method (other.terms [index].clone())),
    }
  }
}

impl <'a, 'b, Vector> $Trait <& 'b $Trajectory <Vector>> for & 'a $Trajectory <Vector> where & 'a Vector: $Trait <& 'b Vector, Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn $method (self, other: & 'b $Trajectory <Vector>)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).clone().$method (& other.terms [index])),
    }
  }
}

  }
}

macro_rules! impl_trajectory_add_sub {

impl_binop ($Trait, $method, $Trajectory <Vector>, $Trajectory <Vector>, $Trajectory <Vector>, self, other, {
  //always let [$($first_identifiers),*] = self.terms;
  let [$($second_identifiers),*] = other.terms or & other.terms;
  $Trajectory {
    origin: self.origin,
    terms: [$($first_identifiers.method ($second_identifiers))*]
  }
});

}

impl_binop ($Trait, $method, $Trajectory <Vector>, Scalar, $Trajectory <Vector>, self, other, {
  $Trajectory {
    origin: self.origin,
    terms: [$($first_identifiers.method (other))*]
  }
});

macro_rules! impl_trajectory {
  ($Terms: ident, $Trajectory: ident, $degree: expr) => {

#[derive (Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Default)]
pub struct $Terms <Vector> ([Vector; $degree + 1]);

#[derive (Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Default)]
pub struct $Trajectory <Vector> {
  origin: Time,
  terms: $Terms <Vector>,
}

impl <Vector> $Terms <Vector> {
  pub fn constant (value: Vector)->Self {
    let mut array = [Vector::zero()];
    array [0] = value;
    $Terms (array)
  }
  pub fn term (&self, time: Time, which: usize)->Vector {
    let mut factor = 1;
    let mut result = terms [which].clone();
    for index in (which + 1)..($degree + 1) {
      factor *= time;
      result += terms [index]*(factor*binomial_coefficient (index, which));
    }
    result
  }
  pub fn set_origin (&mut self, new_origin: Time) {
    for index in 0.. $degree {
      self.0 [index] = self.taylor_coefficient (index, new_origin) ;
    }
  }
}

impl $Trajectory <Vector> {
  pub fn constant (value: Vector)->Self {
    $Trajectory {origin: Vector::zero(), terms: $Terms::constant (value)}
  }
  pub fn set_origin (&mut self, new_origin: Time) {
    self.terms.set_origin (new_origin - self.origin);
    self.origin = new_origin;
  }
  pub fn term (&self, time: Time, which: usize)->Vector {
    self.terms.taylor_coefficient (time - self.origin, which)
  }
  pub fn set_term (&mut self, time: Time, which: usize, value: Vector) {
    self.set_origin (time) ;
    self.terms.0 [which] = value;
  }
  pub fn add_term (&mut self, time: Time, which: usize, value: Vector) {
    self.set_origin (time);
    self.terms.0 [which] += value;
  }
  pub fn value (&mut self, time: Time)->Vector {self.term (time, 0)}
  pub fn velocity (&mut self, time: Time)->Vector {self.term (time, 1)}
  pub fn set_value (&mut self, time: Time, value: Vector) {self.set_term (time, 0, value)}
  pub fn set_velocity (&mut self, time: Time, value: Vector) {self.set_term (time, 1, value)}
  pub fn add_value (&mut self, time: Time, value: Vector) {self.add_term (time, 0, value)}
  pub fn add_velocity (&mut self, time: Time, value: Vector) {self.add_term (time, 1, value)}
}

impl <Vector: Ord + Div <Vector >> Trajectory <Vector> {
  pub fn next_time_lt (now: Time, value: Vector)->Option <Time> {
    if self.value (now) <value {Some (now)}
    else if $degree >= 2 && self.terms.0 [2] != Vector::zero() {
      unimplemented!()
    }
    else {
      if self.terms.0 [1] <= Vector::zero() {None}
      else {Some (self.origin + div_ceil ((value - self.terms.0 [0]), self.terms.0 [1]))}
    }
  }
  pub fn next_time_le (now: Time, value: Vector)->Option <Time> {
    self.next_time_lt (now, value + Vector::one())
  }
  pub fn next_time_gt (now: Time, value: Vector)->Option <Time> {
    (-self).next_time_lt (now, -value)
  }
  pub fn next_time_ge (now: Time, value: Vector)->Option <Time> {
    self.next_time_gt (now, value - Vector::one())
  }
}

impl_trajectory_arithmetic_trait! ($Trajectory, Add, add);
impl_trajectory_arithmetic_trait! ($Trajectory, Sub, sub);

impl <Vector: Clone + Neg <Output = Vector>> Neg for $Trajectory <Vector> {
  type Output = Self;
  fn neg (self)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().neg()),
    }
  }
}
impl <'a, Vector> Neg for & 'a $Trajectory <Vector> where & 'a Vector: Neg <Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn neg (self)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).neg()),
    }
  }
}

  };
}

impl_trajectory! (LinearTrajectoryTerms, LinearTrajectory, 1) ;
impl_trajectory! (QuadraticTrajectory, 2) ;

<commit_msg>Added some more possible implementations of stuff (build still broken)<commit_after>use nalgebra::Vector2;
use std::cmp::max;
use super::rounding_error_tolerant_math::*;
use std::ops::{Add, Sub, Mul, Neg};
use array_ext::*;

pub type Time = i64;

pub trait IntegerVector: Clone + Add <Self, Output = Self> + Sub <Self, Output = Self> + Mul <i64, Output = Self> + Zero + {
  type DistanceProxy: Scalar;
  fn distance_proxy (&self, other: & Self)->Self::DistanceProxy;
}

pub trait ScalarTrajectory: Trajectory <Value: Scalar> {
  ///
  fn non_strict_bounds (&self, input_range: [Time; 2])->[T; 2];
  fn next_time_ge (&self, start: Time, end: Time, target: Self::Value)->Option <Time> {
    //default impl that works for all locally Lipschitz functions; can optimize more in explicit impls
    let mut current_value = self.evaluate (start) ;
    if current_value >= target {return Some (start)}
    let mut start = start;
    let mut increment = Self::Value::one();
    loop {
      let [max,_] = self.slope_range ([start, start + increment]);
      if max >= target {increment >>= 1; break;}
      if start + increment == end {increment = end - start; break;}
      increment <<= 1;
      if start + increment > end {increment = end - start;}
    }
    loop {
      start += increment;
      current_value = self.evaluate (start);
      if current_value >= target {return Some (start)}
      if start == end {return None;}
      if start + increment > end {increment = end - start;}
      loop {
        let [max,_] = self.slope_range ([start, start + increment]);
        if max >= target {increment >>= 1;}
        else {break;}
      }
    }
  }
  pub fn next_time_gt (&self, start: Time, end: Time, target: Self::Value)->Option <Time> {
    self.next_time_ge (now, value + Vector::one())
  }
  pub fn next_time_(&self, start: Time, end: Time, target: Self::Value)->Option <Time> {
    (-self).next_time_ge (now, -value)
  }
  pub fn next_time_lt (&self, start: Time, end: Time, target: Self::Value)->Option <Time> {
    self.next_time_le (now, value - Vector::one())
  }
}

pub struct DistanceProxyTrajectory <'a, Vector: IntegerVector, T: Trajectory <Vector>> {
  first: & 'a T,
  second: & 'a T,
}
impl <'a, Vector: IntegerVector, T: Trajectory <Vector>> ScalarTrajectory <Vector::DistanceProxy> for DistanceProxyTrajectory <'a, Vector, T> {
  fn non_strict_bounds (&self, input_range: [Time; 2])->[Self::Value; 2] {
    {
      let first_bounds = self.first.component (dimension).non_strict_bounds (input_range);
      let second_bounds = self.second.component (dimension).non_strict_bounds (input_range);
      max_vector [dimension] = max (first_bounds [1] - second_bounds [0], second_bounds [1] - first_bounds [0]);
      min_vector [dimension] = if bounds_intersect (first_bounds, second_bounds) {Self::Value::zero()} else {
    [min_vector.distance_proxy(), max_vector.distance_proxy()]
  }
}

pub trait Trajectory: {
  type Value: IntegerVector;
  fn distance_proxy_trajectory (&self, other: & Self)->impl ScalarTrajectory <T::Component> {

  }
}

macro_rules! impl_trajectory_binop {
  ($Trajectory: ident, $Trait: ident, $method: ident) => {

impl <Vector: Clone + $Trait <Vector, Output = Vector>> $Trait for $Trajectory <Vector> {
  type Output = Self;
  fn $method (self, other: Self)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().$method (other.terms [index].clone())),
    }
  }
}

impl <'a, Vector: Clone + $Trait <& 'a Vector, Output = Vector>> $Trait <& 'a $Trajectory <Vector>> for $Trajectory <Vector> {
  type Output = Self;
  fn $method (self, other: & 'a $Trajectory <Vector>)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().$method (& other.terms [index])),
    }
  }
}

impl <'a, Vector: Clone> $Trait <$Trajectory <Vector>> for & 'a $Trajectory <Vector> where & 'a Vector: $Trait <Vector, Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn $method (self, other: $Trajectory <Vector>)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).$method (other.terms [index].clone())),
    }
  }
}

impl <'a, 'b, Vector> $Trait <& 'b $Trajectory <Vector>> for & 'a $Trajectory <Vector> where & 'a Vector: $Trait <& 'b Vector, Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn $method (self, other: & 'b $Trajectory <Vector>)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).clone().$method (& other.terms [index])),
    }
  }
}

  }
}

macro_rules! impl_trajectory_add_sub {

impl_binop ($Trait, $method, $Trajectory <Vector>, $Trajectory <Vector>, $Trajectory <Vector>, self, other, {
  //always let [$($first_identifiers),*] = self.terms;
  let [$($second_identifiers),*] = other.terms or & other.terms;
  $Trajectory {
    origin: self.origin,
    terms: [$($first_identifiers.method ($second_identifiers))*]
  }
});

}

impl_binop ($Trait, $method, $Trajectory <Vector>, Scalar, $Trajectory <Vector>, self, other, {
  $Trajectory {
    origin: self.origin,
    terms: [$($first_identifiers.method (other))*]
  }
});

macro_rules! impl_trajectory {
  ($Terms: ident, $Trajectory: ident, $degree: expr) => {

#[derive (Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Default)]
pub struct $Terms <Vector> ([Vector; $degree + 1]);

#[derive (Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug, Default)]
pub struct $Trajectory <Vector> {
  origin: Time,
  terms: $Terms <Vector>,
}

impl <Vector> $Terms <Vector> {
  pub fn constant (value: Vector)->Self {
    let mut array = [Vector::zero()];
    array [0] = value;
    $Terms (array)
  }
  pub fn term (&self, time: Time, which: usize)->Vector {
    let mut factor = 1;
    let mut result = terms [which].clone();
    for index in (which + 1)..($degree + 1) {
      factor *= time;
      result += terms [index]*(factor*binomial_coefficient (index, which));
    }
    result
  }
  pub fn set_origin (&mut self, new_origin: Time) {
    for index in 0.. $degree {
      self.0 [index] = self.taylor_coefficient (index, new_origin) ;
    }
  }
}

impl $Trajectory <Vector> {
  pub fn constant (value: Vector)->Self {
    $Trajectory {origin: Vector::zero(), terms: $Terms::constant (value)}
  }
  pub fn set_origin (&mut self, new_origin: Time) {
    self.terms.set_origin (new_origin - self.origin);
    self.origin = new_origin;
  }
  pub fn term (&self, time: Time, which: usize)->Vector {
    self.terms.taylor_coefficient (time - self.origin, which)
  }
  pub fn set_term (&mut self, time: Time, which: usize, value: Vector) {
    self.set_origin (time) ;
    self.terms.0 [which] = value;
  }
  pub fn add_term (&mut self, time: Time, which: usize, value: Vector) {
    self.set_origin (time);
    self.terms.0 [which] += value;
  }
  pub fn value (&mut self, time: Time)->Vector {self.term (time, 0)}
  pub fn velocity (&mut self, time: Time)->Vector {self.term (time, 1)}
  pub fn set_value (&mut self, time: Time, value: Vector) {self.set_term (time, 0, value)}
  pub fn set_velocity (&mut self, time: Time, value: Vector) {self.set_term (time, 1, value)}
  pub fn add_value (&mut self, time: Time, value: Vector) {self.add_term (time, 0, value)}
  pub fn add_velocity (&mut self, time: Time, value: Vector) {self.add_term (time, 1, value)}
}

impl <Vector: Ord + Div <Vector >> Trajectory <Vector> {
  pub fn next_time_lt (now: Time, value: Vector)->Option <Time> {
    if self.value (now) <value {Some (now)}
    else if $degree >= 2 && self.terms.0 [2] != Vector::zero() {
      unimplemented!()
    }
    else {
      if self.terms.0 [1] <= Vector::zero() {None}
      else {Some (self.origin + div_ceil ((value - self.terms.0 [0]), self.terms.0 [1]))}
    }
  }
  pub fn next_time_le (now: Time, value: Vector)->Option <Time> {
    self.next_time_lt (now, value + Vector::one())
  }
  pub fn next_time_gt (now: Time, value: Vector)->Option <Time> {
    (-self).next_time_lt (now, -value)
  }
  pub fn next_time_ge (now: Time, value: Vector)->Option <Time> {
    self.next_time_gt (now, value - Vector::one())
  }
}

impl_trajectory_arithmetic_trait! ($Trajectory, Add, add);
impl_trajectory_arithmetic_trait! ($Trajectory, Sub, sub);

impl <Vector: Clone + Neg <Output = Vector>> Neg for $Trajectory <Vector> {
  type Output = Self;
  fn neg (self)->Self {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | self.terms [index].clone().neg()),
    }
  }
}
impl <'a, Vector> Neg for & 'a $Trajectory <Vector> where & 'a Vector: Neg <Output = Vector> {
  type Output = $Trajectory <Vector>;
  fn neg (self)->$Trajectory <Vector> {
    $Trajectory {
      origin: self.origin,
      terms: Array::from_fn (| index | (& self.terms [index]).neg()),
    }
  }
}

  };
}

impl_trajectory! (LinearTrajectoryTerms, LinearTrajectory, 1) ;
impl_trajectory! (QuadraticTrajectory, 2) ;

<|endoftext|>


<commit_before>use std::iter::Iterator;
use std::time::Duration;

use num_rational::Ratio;

use crate::RgbaImage;
use crate::error::ImageResult;

/// An implementation dependent iterator, reading the frames as requested
pub struct Frames<'a> {
    iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
}

impl<'a> Frames<'a> {
    /// Creates a new `Frames` from an implementation specific iterator.
    pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
        Frames { iterator }
    }

    /// Steps through the iterator from the current frame until the end and pushes each frame into
    /// a `Vec`.
    /// If en error is encountered that error is returned instead.
    ///
    /// Note: This is equivalent to `Frames::collect::<ImageResult<Vec<Frame>>>()`
    pub fn collect_frames(self) -> ImageResult<Vec<Frame>> {
        self.collect()
    }
}

impl<'a> Iterator for Frames<'a> {
    type Item = ImageResult<Frame>;
    fn next(&mut self) -> Option<ImageResult<Frame>> {
        self.iterator.next()
    }
}

/// A single animation frame
#[derive(Clone)]
pub struct Frame {
    /// Delay between the frames in milliseconds
    delay: Delay,
    /// x offset
    left: u32,
    /// y offset
    top: u32,
    buffer: RgbaImage,
}

/// The delay of a frame relative to the previous one.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
pub struct Delay {
    ratio: Ratio<u32>,
}

impl Frame {
    /// Contructs a new frame without any delay.
    pub fn new(buffer: RgbaImage) -> Frame {
        Frame {
            delay: Delay::from_ratio(Ratio::from_integer(0)),
            left: 0,
            top: 0,
            buffer,
        }
    }

    /// Contructs a new frame
    pub fn from_parts(buffer: RgbaImage, left: u32, top: u32, delay: Delay) -> Frame {
        Frame {
            delay,
            left,
            top,
            buffer,
        }
    }

    /// Delay of this frame
    pub fn delay(&self) -> Delay {
        self.delay
    }

    /// Returns the image buffer
    pub fn buffer(&self) -> &RgbaImage {
        &self.buffer
    }

    /// Returns the image buffer
    pub fn into_buffer(self) -> RgbaImage {
        self.buffer
    }

    /// Returns the x offset
    pub fn left(&self) -> u32 {
        self.left
    }

    /// Returns the y offset
    pub fn top(&self) -> u32 {
        self.top
    }
}

impl Delay {
    /// Create a delay from a ratio of milliseconds.
    ///
    /// # Examples
    ///
    /// ```
    /// use image::Delay;
    /// let delay_10ms = Delay::from_numer_denom_ms(10, 1);
    /// ```
    pub fn from_numer_denom_ms(numerator: u32, denominator: u32) -> Self {
        Delay { ratio: Ratio::new_raw(numerator, denominator) }
    }

    /// Convert from a duration, clamped between 0 and an implemented defined maximum.
    ///
    /// The maximum is *at least* `i32::MAX` milliseconds. It should be noted that the accuracy of
    /// the result may be relative and very large delays have a coarse resolution.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::time::Duration;
    /// use image::Delay;
    ///
    /// let duration = Duration::from_millis(20);
    /// let delay = Delay::from_saturating_duration(duration);
    /// ```
    pub fn from_saturating_duration(duration: Duration) -> Self {
        // A few notes: The largest number we can represent as a ratio is u32::MAX but we can
        // sometimes represent much smaller numbers.
        //
        // We can represent duration as `millis+a/b` (where a < b, b > 0).
        // We must thus bound b with `b·millis + (b-1) <= u32::MAX` or
        // > `0 < b <= (u32::MAX + 1)/(millis + 1)`
        // Corollary: millis <= u32::MAX

        const MILLIS_BOUND: u128 = u32::max_value() as u128;

        let millis = duration.as_millis().min(MILLIS_BOUND);
        let submillis = (duration.as_nanos() % 1_000_000) as u32;

        let max_b = if millis > 0 {
            ((MILLIS_BOUND + 1)/(millis + 1)) as u32
        } else {
            MILLIS_BOUND as u32
        };
        let millis = millis as u32;

        let (a, b) = Self::closest_bounded_fraction(max_b, submillis, 1_000_000);
        Self::from_numer_denom_ms(a + b*millis, b)
    }

    /// The numerator and denominator of the delay in milliseconds.
    ///
    /// This is guaranteed to be an exact conversion if the `Delay` was previously created with the
    /// `from_numer_denom_ms` constructor.
    pub fn numer_denom_ms(self) -> (u32, u32) {
        (*self.ratio.numer(), *self.ratio.denom())
    }

    pub(crate) fn from_ratio(ratio: Ratio<u32>) -> Self {
        Delay { ratio }
    }

    pub(crate) fn into_ratio(self) -> Ratio<u32> {
        self.ratio
    }

    /// Given some fraction, compute an approximation with denominator bounded.
    ///
    /// Note that `denom_bound` bounds nominator and denominator of all intermediate
    /// approximations and the end result.
    fn closest_bounded_fraction(denom_bound: u32, nom: u32, denom: u32) -> (u32, u32) {
        use std::cmp::Ordering::{self, *};
        assert!(0 < denom);
        assert!(0 < denom_bound);
        assert!(nom < denom);

        // Avoid a few type troubles. All intermediate results are bounded by `denom_bound` which
        // is in turn bounded by u32::MAX. Representing with u64 allows multiplication of any two
        // values without fears of overflow.

        // Compare two fractions whose parts fit into a u32.
        fn compare_fraction((an, ad): (u64, u64), (bn, bd): (u64, u64)) -> Ordering {
            (an*bd).cmp(&(bn*ad))
        }

        // Computes the nominator of the absolute difference between two such fractions.
        fn abs_diff_nom((an, ad): (u64, u64), (bn, bd): (u64, u64)) -> u64 {
            let c0 = an*bd;
            let c1 = ad*bn;

            let d0 = c0.max(c1);
            let d1 = c0.min(c1);
            d0 - d1
        }

        let exact = (u64::from(nom), u64::from(denom));
        // The lower bound fraction, numerator and denominator.
        let mut lower = (0u64, 1u64);
        // The upper bound fraction, numerator and denominator.
        let mut upper = (1u64, 1u64);
        // The closest approximation for now.
        let mut guess = (u64::from(nom*2 > denom), 1u64);

        // loop invariant: ad, bd <= denom_bound
        // iterates the Farey sequence.
        loop {
            // Break if we are done.
            if compare_fraction(guess, exact) == Equal {
                break;
            }

            // Break if next Farey number is out-of-range.
            if u64::from(denom_bound) - lower.1 < upper.1 {
                break;
            }

            // Next Farey approximation n between a and b
            let next = (lower.0 + upper.0, lower.1 + upper.1);
            // if F < n then replace the upper bound, else replace lower.
            if compare_fraction(exact, next) == Less {
                upper = next;
            } else {
                lower = next;
            }

            // Now correct the closest guess.
            // In other words, if |c - f| > |n - f| then replace it with the new guess.
            // This favors the guess with smaller denominator on equality.

            // |g - f| = |g_diff_nom|/(gd*fd);
            let g_diff_nom = abs_diff_nom(guess, exact);
            // |n - f| = |n_diff_nom|/(nd*fd);
            let n_diff_nom = abs_diff_nom(next, exact);

            // The difference |n - f| is smaller than |g - f| if either the integral part of the
            // fraction |n_diff_nom|/nd is smaller than the one of |g_diff_nom|/gd or if they are
            // the same but the fractional part is larger.
            if match (n_diff_nom/next.1).cmp(&(g_diff_nom/guess.1)) {
                Less => true,
                Greater => false,
                // Note that the nominator for the fractional part is smaller than its denominator
                // which is smaller than u32 and can't overflow the multiplication with the other
                // denominator, that is we can compare these fractions by multiplication with the
                // respective other denominator.
                Equal => compare_fraction((n_diff_nom%next.1, next.1), (g_diff_nom%guess.1, guess.1)) == Less,
            } {
                guess = next;
            }
        }

        (guess.0 as u32, guess.1 as u32)
    }
}

impl From<Delay> for Duration {
    fn from(delay: Delay) -> Self {
        let ratio = delay.into_ratio();
        let ms = ratio.to_integer();
        let rest = ratio.numer() % ratio.denom();
        let nanos = (u64::from(rest) * 1_000_000) / u64::from(*ratio.denom());
        Duration::from_millis(ms.into()) + Duration::from_nanos(nanos)
    }
}

#[cfg(test)]
mod tests {
    use super::{Delay, Duration, Ratio};

    #[test]
    fn simple() {
        let second = Delay::from_numer_denom_ms(1000, 1);
        assert_eq!(Duration::from(second), Duration::from_secs(1));
    }

    #[test]
    fn fps_30() {
        let thirtieth = Delay::from_numer_denom_ms(1000, 30);
        let duration = Duration::from(thirtieth);
        assert_eq!(duration.as_secs(), 0);
        assert_eq!(duration.subsec_millis(), 33);
        assert_eq!(duration.subsec_nanos(), 33_333_333);
    }

    #[test]
    fn duration_outlier() {
        let oob = Duration::from_secs(0xFFFF_FFFF);
        let delay = Delay::from_saturating_duration(oob);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));
    }

    #[test]
    fn duration_approx() {
        let oob = Duration::from_millis(0xFFFF_FFFF) + Duration::from_micros(1);
        let delay = Delay::from_saturating_duration(oob);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));

        let inbounds = Duration::from_millis(0xFFFF_FFFF) - Duration::from_micros(1);
        let delay = Delay::from_saturating_duration(inbounds);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));

        let fine = Duration::from_millis(0xFFFF_FFFF/1000) + Duration::from_micros(0xFFFF_FFFF%1000);
        let delay = Delay::from_saturating_duration(fine);
        // Funnily, 0xFFFF_FFFF is divisble by 5, thus we compare with a `Ratio`.
        assert_eq!(delay.into_ratio(), Ratio::new(0xFFFF_FFFF, 1000));
    }

    #[test]
    fn precise() {
        // The ratio has only 32 bits in the numerator, too imprecise to get more than 11 digits
        // correct. But it may be expressed as 1_000_000/3 instead.
        let exceed = Duration::from_secs(333) + Duration::from_nanos(333_333_333);
        let delay = Delay::from_saturating_duration(exceed);
        assert_eq!(Duration::from(delay), exceed);
    }

    #[test]
    fn small() {
        // Not quite a delay of `1 ms`.
        let delay = Delay::from_numer_denom_ms(1 << 16, (1 << 16) + 1);
        let duration = Duration::from(delay);
        assert_eq!(duration.as_millis(), 0);
        // Not precisely the original but should be smaller than 0.
        let delay = Delay::from_saturating_duration(duration);
        assert_eq!(delay.into_ratio().to_integer(), 0);
    }
}
<commit_msg>frame: Add buffer_mut function<commit_after>use std::iter::Iterator;
use std::time::Duration;

use num_rational::Ratio;

use crate::RgbaImage;
use crate::error::ImageResult;

/// An implementation dependent iterator, reading the frames as requested
pub struct Frames<'a> {
    iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
}

impl<'a> Frames<'a> {
    /// Creates a new `Frames` from an implementation specific iterator.
    pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
        Frames { iterator }
    }

    /// Steps through the iterator from the current frame until the end and pushes each frame into
    /// a `Vec`.
    /// If en error is encountered that error is returned instead.
    ///
    /// Note: This is equivalent to `Frames::collect::<ImageResult<Vec<Frame>>>()`
    pub fn collect_frames(self) -> ImageResult<Vec<Frame>> {
        self.collect()
    }
}

impl<'a> Iterator for Frames<'a> {
    type Item = ImageResult<Frame>;
    fn next(&mut self) -> Option<ImageResult<Frame>> {
        self.iterator.next()
    }
}

/// A single animation frame
#[derive(Clone)]
pub struct Frame {
    /// Delay between the frames in milliseconds
    delay: Delay,
    /// x offset
    left: u32,
    /// y offset
    top: u32,
    buffer: RgbaImage,
}

/// The delay of a frame relative to the previous one.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
pub struct Delay {
    ratio: Ratio<u32>,
}

impl Frame {
    /// Contructs a new frame without any delay.
    pub fn new(buffer: RgbaImage) -> Frame {
        Frame {
            delay: Delay::from_ratio(Ratio::from_integer(0)),
            left: 0,
            top: 0,
            buffer,
        }
    }

    /// Contructs a new frame
    pub fn from_parts(buffer: RgbaImage, left: u32, top: u32, delay: Delay) -> Frame {
        Frame {
            delay,
            left,
            top,
            buffer,
        }
    }

    /// Delay of this frame
    pub fn delay(&self) -> Delay {
        self.delay
    }

    /// Returns the image buffer
    pub fn buffer(&self) -> &RgbaImage {
        &self.buffer
    }

    /// Returns a mutable image buffer
    pub fn buffer_mut(&mut self) -> &mut RgbaImage {
        &mut self.buffer
    }

    /// Returns the image buffer
    pub fn into_buffer(self) -> RgbaImage {
        self.buffer
    }

    /// Returns the x offset
    pub fn left(&self) -> u32 {
        self.left
    }

    /// Returns the y offset
    pub fn top(&self) -> u32 {
        self.top
    }
}

impl Delay {
    /// Create a delay from a ratio of milliseconds.
    ///
    /// # Examples
    ///
    /// ```
    /// use image::Delay;
    /// let delay_10ms = Delay::from_numer_denom_ms(10, 1);
    /// ```
    pub fn from_numer_denom_ms(numerator: u32, denominator: u32) -> Self {
        Delay { ratio: Ratio::new_raw(numerator, denominator) }
    }

    /// Convert from a duration, clamped between 0 and an implemented defined maximum.
    ///
    /// The maximum is *at least* `i32::MAX` milliseconds. It should be noted that the accuracy of
    /// the result may be relative and very large delays have a coarse resolution.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::time::Duration;
    /// use image::Delay;
    ///
    /// let duration = Duration::from_millis(20);
    /// let delay = Delay::from_saturating_duration(duration);
    /// ```
    pub fn from_saturating_duration(duration: Duration) -> Self {
        // A few notes: The largest number we can represent as a ratio is u32::MAX but we can
        // sometimes represent much smaller numbers.
        //
        // We can represent duration as `millis+a/b` (where a < b, b > 0).
        // We must thus bound b with `b·millis + (b-1) <= u32::MAX` or
        // > `0 < b <= (u32::MAX + 1)/(millis + 1)`
        // Corollary: millis <= u32::MAX

        const MILLIS_BOUND: u128 = u32::max_value() as u128;

        let millis = duration.as_millis().min(MILLIS_BOUND);
        let submillis = (duration.as_nanos() % 1_000_000) as u32;

        let max_b = if millis > 0 {
            ((MILLIS_BOUND + 1)/(millis + 1)) as u32
        } else {
            MILLIS_BOUND as u32
        };
        let millis = millis as u32;

        let (a, b) = Self::closest_bounded_fraction(max_b, submillis, 1_000_000);
        Self::from_numer_denom_ms(a + b*millis, b)
    }

    /// The numerator and denominator of the delay in milliseconds.
    ///
    /// This is guaranteed to be an exact conversion if the `Delay` was previously created with the
    /// `from_numer_denom_ms` constructor.
    pub fn numer_denom_ms(self) -> (u32, u32) {
        (*self.ratio.numer(), *self.ratio.denom())
    }

    pub(crate) fn from_ratio(ratio: Ratio<u32>) -> Self {
        Delay { ratio }
    }

    pub(crate) fn into_ratio(self) -> Ratio<u32> {
        self.ratio
    }

    /// Given some fraction, compute an approximation with denominator bounded.
    ///
    /// Note that `denom_bound` bounds nominator and denominator of all intermediate
    /// approximations and the end result.
    fn closest_bounded_fraction(denom_bound: u32, nom: u32, denom: u32) -> (u32, u32) {
        use std::cmp::Ordering::{self, *};
        assert!(0 < denom);
        assert!(0 < denom_bound);
        assert!(nom < denom);

        // Avoid a few type troubles. All intermediate results are bounded by `denom_bound` which
        // is in turn bounded by u32::MAX. Representing with u64 allows multiplication of any two
        // values without fears of overflow.

        // Compare two fractions whose parts fit into a u32.
        fn compare_fraction((an, ad): (u64, u64), (bn, bd): (u64, u64)) -> Ordering {
            (an*bd).cmp(&(bn*ad))
        }

        // Computes the nominator of the absolute difference between two such fractions.
        fn abs_diff_nom((an, ad): (u64, u64), (bn, bd): (u64, u64)) -> u64 {
            let c0 = an*bd;
            let c1 = ad*bn;

            let d0 = c0.max(c1);
            let d1 = c0.min(c1);
            d0 - d1
        }

        let exact = (u64::from(nom), u64::from(denom));
        // The lower bound fraction, numerator and denominator.
        let mut lower = (0u64, 1u64);
        // The upper bound fraction, numerator and denominator.
        let mut upper = (1u64, 1u64);
        // The closest approximation for now.
        let mut guess = (u64::from(nom*2 > denom), 1u64);

        // loop invariant: ad, bd <= denom_bound
        // iterates the Farey sequence.
        loop {
            // Break if we are done.
            if compare_fraction(guess, exact) == Equal {
                break;
            }

            // Break if next Farey number is out-of-range.
            if u64::from(denom_bound) - lower.1 < upper.1 {
                break;
            }

            // Next Farey approximation n between a and b
            let next = (lower.0 + upper.0, lower.1 + upper.1);
            // if F < n then replace the upper bound, else replace lower.
            if compare_fraction(exact, next) == Less {
                upper = next;
            } else {
                lower = next;
            }

            // Now correct the closest guess.
            // In other words, if |c - f| > |n - f| then replace it with the new guess.
            // This favors the guess with smaller denominator on equality.

            // |g - f| = |g_diff_nom|/(gd*fd);
            let g_diff_nom = abs_diff_nom(guess, exact);
            // |n - f| = |n_diff_nom|/(nd*fd);
            let n_diff_nom = abs_diff_nom(next, exact);

            // The difference |n - f| is smaller than |g - f| if either the integral part of the
            // fraction |n_diff_nom|/nd is smaller than the one of |g_diff_nom|/gd or if they are
            // the same but the fractional part is larger.
            if match (n_diff_nom/next.1).cmp(&(g_diff_nom/guess.1)) {
                Less => true,
                Greater => false,
                // Note that the nominator for the fractional part is smaller than its denominator
                // which is smaller than u32 and can't overflow the multiplication with the other
                // denominator, that is we can compare these fractions by multiplication with the
                // respective other denominator.
                Equal => compare_fraction((n_diff_nom%next.1, next.1), (g_diff_nom%guess.1, guess.1)) == Less,
            } {
                guess = next;
            }
        }

        (guess.0 as u32, guess.1 as u32)
    }
}

impl From<Delay> for Duration {
    fn from(delay: Delay) -> Self {
        let ratio = delay.into_ratio();
        let ms = ratio.to_integer();
        let rest = ratio.numer() % ratio.denom();
        let nanos = (u64::from(rest) * 1_000_000) / u64::from(*ratio.denom());
        Duration::from_millis(ms.into()) + Duration::from_nanos(nanos)
    }
}

#[cfg(test)]
mod tests {
    use super::{Delay, Duration, Ratio};

    #[test]
    fn simple() {
        let second = Delay::from_numer_denom_ms(1000, 1);
        assert_eq!(Duration::from(second), Duration::from_secs(1));
    }

    #[test]
    fn fps_30() {
        let thirtieth = Delay::from_numer_denom_ms(1000, 30);
        let duration = Duration::from(thirtieth);
        assert_eq!(duration.as_secs(), 0);
        assert_eq!(duration.subsec_millis(), 33);
        assert_eq!(duration.subsec_nanos(), 33_333_333);
    }

    #[test]
    fn duration_outlier() {
        let oob = Duration::from_secs(0xFFFF_FFFF);
        let delay = Delay::from_saturating_duration(oob);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));
    }

    #[test]
    fn duration_approx() {
        let oob = Duration::from_millis(0xFFFF_FFFF) + Duration::from_micros(1);
        let delay = Delay::from_saturating_duration(oob);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));

        let inbounds = Duration::from_millis(0xFFFF_FFFF) - Duration::from_micros(1);
        let delay = Delay::from_saturating_duration(inbounds);
        assert_eq!(delay.numer_denom_ms(), (0xFFFF_FFFF, 1));

        let fine = Duration::from_millis(0xFFFF_FFFF/1000) + Duration::from_micros(0xFFFF_FFFF%1000);
        let delay = Delay::from_saturating_duration(fine);
        // Funnily, 0xFFFF_FFFF is divisble by 5, thus we compare with a `Ratio`.
        assert_eq!(delay.into_ratio(), Ratio::new(0xFFFF_FFFF, 1000));
    }

    #[test]
    fn precise() {
        // The ratio has only 32 bits in the numerator, too imprecise to get more than 11 digits
        // correct. But it may be expressed as 1_000_000/3 instead.
        let exceed = Duration::from_secs(333) + Duration::from_nanos(333_333_333);
        let delay = Delay::from_saturating_duration(exceed);
        assert_eq!(Duration::from(delay), exceed);
    }

    #[test]
    fn small() {
        // Not quite a delay of `1 ms`.
        let delay = Delay::from_numer_denom_ms(1 << 16, (1 << 16) + 1);
        let duration = Duration::from(delay);
        assert_eq!(duration.as_millis(), 0);
        // Not precisely the original but should be smaller than 0.
        let delay = Delay::from_saturating_duration(duration);
        assert_eq!(delay.into_ratio().to_integer(), 0);
    }
}
<|endoftext|>


<commit_before>extern crate xml;
extern crate regex;

use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::io::BufReader;

use xml::reader::{EventReader, XmlEvent};
use xml::attribute::OwnedAttribute;

#[derive(Debug, Clone, Default)]
struct LineAttributes {
    top: i32,
    left: i32,
    height: i32,
    page: u32,
}

fn read_attributes(attr_list: &Vec<OwnedAttribute>) -> LineAttributes {
    let mut attributes : LineAttributes = Default::default();

    for attr in attr_list {
        match attr.name.local_name.as_ref() {
            "top" => attributes.top = attr.value.parse().unwrap(),
            "left" => attributes.left = attr.value.parse().unwrap(),
            "height" => attributes.height = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    attributes
}

#[derive(Debug, Clone, Default)]
struct ScriptProperties {
    direction_position: i32,
    dialog_position: i32,
    speaker_direction_position: i32,
    speaker_position: i32,
    intra_paragraph_line_height: i32,
}

fn read_and_analyze_script(reader: Box<Read>) -> (ScriptProperties, Vec<(LineAttributes, String)>) {
    let mut script_properties: ScriptProperties = Default::default();
    let mut lines: Vec<(LineAttributes, String)> = Vec::new();

    // these maps are used to heuristically determine the ScriptProperties
    let mut position_uses: HashMap<i32, u32> = HashMap::new();
    let mut line_height_uses: HashMap<i32, u32> = HashMap::new();

    // states for the streaming xml parsing
    let mut current_line_attributes: LineAttributes = Default::default();
    let mut current_text_buffer = String::new();
    let mut current_page_number = 0;
    let mut last_line_height = 0;

    let parser = EventReader::new(reader);
    for event in parser {
        match event {
            Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                match name.local_name.as_ref() {
                    "text" => {
                        current_line_attributes = read_attributes(&attributes);

                        current_text_buffer.clear();

                        // increase the count for the current left margin
                        *position_uses.entry(current_line_attributes.left)
                                      .or_insert(0) += 1;

                        // increase the count for the current top position diff
                        *line_height_uses.entry(current_line_attributes.top - last_line_height)
                                         .or_insert(0) += 1;
                        last_line_height = current_line_attributes.top;
                    }
                    "page" => {
                        last_line_height = 0;

                        for attr in attributes {
                            if "number" == attr.name.local_name {
                                current_page_number = attr.value.parse().unwrap();
                                break;
                            }
                        }
                    }
                    _ => {}
                }
            }
            Ok(XmlEvent::Characters(text)) => {
                if current_text_buffer.len() > 0 {
                    current_text_buffer.push(' ');
                }
                current_text_buffer.push_str(text.trim());
            }
            Ok(XmlEvent::EndElement { name, .. }) => {
                if name.local_name == "text" {
                    current_line_attributes.page = current_page_number;
                    lines.push((current_line_attributes.clone(), current_text_buffer.clone()));
                }
            }
            Ok(_) => {},
            Err(e) => panic!("Error parsing xml: {}", e),
        }
    }

    // the position_uses map should at least have 3 different entries
    if position_uses.len() < 3 {
        panic!("Script uses strange layout");
    }

    // copy the position uses map into a vector and sort by value desc
    let mut position_uses_vec = position_uses.into_iter().collect::<Vec<_>>();
    position_uses_vec.sort_by(|&a, &b| b.1.cmp(&a.1));

    // sort the top 3 entries by position again (right-exclusive range)
    position_uses_vec[0..3].sort_by(|&a, &b| b.0.cmp(&a.0));

    script_properties.speaker_position = position_uses_vec[0].0;
    script_properties.dialog_position = position_uses_vec[1].0;
    script_properties.direction_position = position_uses_vec[2].0;

    // take the next value between speaker and dialog as speaker_direction
    for &value in position_uses_vec.iter().skip(3) {
        let (position, _) = value;
        if position > script_properties.dialog_position &&
           position < script_properties.speaker_position {
            script_properties.speaker_direction_position = position;
            break;
        }
    }

    // use to most used line diff value to determine the specific sections
    let mut last_uses: u32 = 0;
    for (&line_height, &uses) in line_height_uses.iter() {
        if uses > last_uses {
            script_properties.intra_paragraph_line_height = line_height;
            last_uses = uses;
        }
    }

    (script_properties, lines)
}

#[derive(Debug, Clone)]
enum ScenePart {
    Direction {
        direction: String,
        page: u32,
    },
    Dialog {
        speaker: String,
        direction: String,
        dialog: String,
        page: u32,
    }
}

#[derive(Debug, Clone)]
enum ScriptPart {
    Separator,
    ScenePart(ScenePart),
    LocationChange(String),
    SceneChange,
}

fn is_location_change(line: &str) -> bool {
    line.starts_with("INT.") || line.starts_with("EXT.")
}

fn is_scene_change(line: &str) -> bool {
    line.starts_with("CUT TO")
}

fn extract_script_parts(properties: ScriptProperties, lines: &Vec<(LineAttributes, String)>)
    -> Vec<ScriptPart> {
    let mut script_parts: Vec<ScriptPart> = Vec::new();
    let mut last_top_position = 0;

    for line in lines.iter() {
        let &(ref attributes, ref line) = line;

        if line.len() == 0 {
            continue;
        }

        // check if a new section starts
        if attributes.top - last_top_position > 18 ||
           attributes.top - last_top_position < 0 {
            // used to separate two consecutive script parts of the
            // same type. this is just a implementation detail of
            // the parsing. the Separator can be ignored later.
            script_parts.push(ScriptPart::Separator);
        }

        if attributes.left == properties.direction_position {
            if is_location_change(line) {
                script_parts.push(ScriptPart::LocationChange(line.clone()));
            } else {
                // ensure the last script part is a direction
                if let Some(&ScriptPart::ScenePart(ScenePart::Direction{..})) = script_parts.last() {
                } else {
                    script_parts.push(ScriptPart::ScenePart(
                        ScenePart::Direction{
                            direction: String::new(),
                            page: attributes.page,
                        }));
                }

                if let Some(&mut ScriptPart::ScenePart(ScenePart::Direction{ref mut direction, ..})) = script_parts.last_mut() {
                    if direction.len() > 0 {
                        direction.push(' ');
                    }
                    direction.push_str(line);
                }
            }
        } else if attributes.left == properties.speaker_position ||
                  attributes.left == properties.speaker_direction_position ||
                  attributes.left == properties.dialog_position {
            // Ensure the last script part is a dialog
            if let Some(&ScriptPart::ScenePart(ScenePart::Dialog{..})) = script_parts.last() {
            } else {
                script_parts.push(ScriptPart::ScenePart(
                    ScenePart::Dialog{
                        speaker: String::new(),
                        direction: String::new(),
                        dialog: String::new(),
                        page: attributes.page,
                    }));
            }

            // get the dialog, should never fail (see above)
            if let Some(&mut ScriptPart::ScenePart(ScenePart::Dialog{ref mut speaker, ref mut direction, ref mut dialog, ..})) = script_parts.last_mut() {
                if attributes.left == properties.speaker_position {
                    // there is only one speaker per dialog
                    speaker.push_str(line);
                } else if attributes.left == properties.speaker_direction_position {
                    if direction.len() > 0 {
                        direction.push(' ');
                    }
                    direction.push_str(line);
                } else if attributes.left == properties.dialog_position {
                    if dialog.len() > 0 {
                        dialog.push(' ');
                    }
                    dialog.push_str(line);
                }
            }
        } else {
            if is_scene_change(line) {
                script_parts.push(ScriptPart::SceneChange);
            }
        }

        last_top_position = attributes.top;
    }

    script_parts
}

#[derive(Default, Clone, Debug)]
struct Location {
	internal: bool,
	name: String,
	parts: Vec<ScenePart>,
}

type Scene = Vec<Location>;

fn extract_scenes(script_parts: &Vec<ScriptPart>) -> Vec<Scene> {
	let mut scenes = Vec::new();

    // scene with default (empty) location
	let default_scene: Scene = vec![Default::default()];
	scenes.push(default_scene.clone());

	for script_part in script_parts.iter() {
		use ScriptPart::*;
		match script_part {
			&SceneChange => {
				// unwrap is save, see default_scene
				if scenes.last().unwrap().len() > 0 {
					scenes.push(default_scene.clone());
				}
			}
			&LocationChange(ref location) => {
				// unwraps are safe, see default_scene
				let mut current_scene = scenes.last_mut().unwrap();

				if current_scene.last().unwrap().parts.len() == 0 {
					current_scene.pop();
				}
                // TODO: Parse INT./EXT.
				current_scene.push(Location {name: location.clone(), ..Default::default()})
			}
            &ScenePart(ref scene_part) => {
                let scene_parts = &mut scenes.last_mut().unwrap().last_mut().unwrap().parts;
                scene_parts.push(scene_part.clone());
            }
			&Separator => {} //ignore
		}
	}

	scenes
}

#[allow(dead_code)]
fn condense_script_demo(properties: ScriptProperties, lines: &Vec<(LineAttributes, String)>) {
    let mut last_left_position = 0;
    let mut last_top_position = 0;

    for line in lines.iter() {
        let &(ref attributes, ref line) = line;

        if line.len() == 0 {
            continue;
        }

        // start new section
        if last_left_position != attributes.left ||
           attributes.top - last_top_position > 18 ||
           attributes.top - last_top_position < 0 {
            if ! (last_left_position == properties.speaker_direction_position ||
                  last_left_position == properties.speaker_position) {
                // empty line after last section
                println!("");
            }
        }

        match attributes.left {
            k if (k == properties.direction_position)
                => println!("{}", line),
            k if (k == properties.dialog_position)
                => println!("          {}", line),
            k if (k == properties.speaker_direction_position)
                => println!("               {}", line),
            k if (k == properties.speaker_position)
                => println!("                    {}", line),
            _   => println!("------- {}", line),
        }

        last_left_position = attributes.left;
        last_top_position = attributes.top;
    }
}

fn main() {
    let xml_file_name = env::args().skip(1).next().expect("No input file given");

    let file_reader = File::open(xml_file_name).expect("Could not open file");
    let buffered_file_reader = Box::new(BufReader::new(file_reader));

    let (properties, lines) = read_and_analyze_script(buffered_file_reader);

    //condense_script_demo(properties, &lines);
    println!("{:#?}", extract_scenes(&extract_script_parts(properties, &lines)));
}
<commit_msg>Implement output of dialog directions in correct order<commit_after>extern crate xml;
extern crate regex;

use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::io::BufReader;

use xml::reader::{EventReader, XmlEvent};
use xml::attribute::OwnedAttribute;

#[derive(Debug, Clone, Default)]
struct LineAttributes {
    top: i32,
    left: i32,
    height: i32,
    page: u32,
}

fn read_attributes(attr_list: &Vec<OwnedAttribute>) -> LineAttributes {
    let mut attributes : LineAttributes = Default::default();

    for attr in attr_list {
        match attr.name.local_name.as_ref() {
            "top" => attributes.top = attr.value.parse().unwrap(),
            "left" => attributes.left = attr.value.parse().unwrap(),
            "height" => attributes.height = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    attributes
}

#[derive(Debug, Clone, Default)]
struct ScriptProperties {
    direction_position: i32,
    dialog_position: i32,
    speaker_direction_position: i32,
    speaker_position: i32,
    intra_paragraph_line_height: i32,
}

fn read_and_analyze_script(reader: Box<Read>) -> (ScriptProperties, Vec<(LineAttributes, String)>) {
    let mut script_properties: ScriptProperties = Default::default();
    let mut lines: Vec<(LineAttributes, String)> = Vec::new();

    // these maps are used to heuristically determine the ScriptProperties
    let mut position_uses: HashMap<i32, u32> = HashMap::new();
    let mut line_height_uses: HashMap<i32, u32> = HashMap::new();

    // states for the streaming xml parsing
    let mut current_line_attributes: LineAttributes = Default::default();
    let mut current_text_buffer = String::new();
    let mut current_page_number = 0;
    let mut last_line_height = 0;

    let parser = EventReader::new(reader);
    for event in parser {
        match event {
            Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                match name.local_name.as_ref() {
                    "text" => {
                        current_line_attributes = read_attributes(&attributes);

                        current_text_buffer.clear();

                        // increase the count for the current left margin
                        *position_uses.entry(current_line_attributes.left)
                                      .or_insert(0) += 1;

                        // increase the count for the current top position diff
                        *line_height_uses.entry(current_line_attributes.top - last_line_height)
                                         .or_insert(0) += 1;
                        last_line_height = current_line_attributes.top;
                    }
                    "page" => {
                        last_line_height = 0;

                        for attr in attributes {
                            if "number" == attr.name.local_name {
                                current_page_number = attr.value.parse().unwrap();
                                break;
                            }
                        }
                    }
                    _ => {}
                }
            }
            Ok(XmlEvent::Characters(text)) => {
                if current_text_buffer.len() > 0 {
                    current_text_buffer.push(' ');
                }
                current_text_buffer.push_str(text.trim());
            }
            Ok(XmlEvent::EndElement { name, .. }) => {
                if name.local_name == "text" {
                    current_line_attributes.page = current_page_number;
                    lines.push((current_line_attributes.clone(), current_text_buffer.clone()));
                }
            }
            Ok(_) => {},
            Err(e) => panic!("Error parsing xml: {}", e),
        }
    }

    // the position_uses map should at least have 3 different entries
    if position_uses.len() < 3 {
        panic!("Script uses strange layout");
    }

    // copy the position uses map into a vector and sort by value desc
    let mut position_uses_vec = position_uses.into_iter().collect::<Vec<_>>();
    position_uses_vec.sort_by(|&a, &b| b.1.cmp(&a.1));

    // sort the top 3 entries by position again (right-exclusive range)
    position_uses_vec[0..3].sort_by(|&a, &b| b.0.cmp(&a.0));

    script_properties.speaker_position = position_uses_vec[0].0;
    script_properties.dialog_position = position_uses_vec[1].0;
    script_properties.direction_position = position_uses_vec[2].0;

    // take the next value between speaker and dialog as speaker_direction
    for &value in position_uses_vec.iter().skip(3) {
        let (position, _) = value;
        if position > script_properties.dialog_position &&
           position < script_properties.speaker_position {
            script_properties.speaker_direction_position = position;
            break;
        }
    }

    // use to most used line diff value to determine the specific sections
    let mut last_uses: u32 = 0;
    for (&line_height, &uses) in line_height_uses.iter() {
        if uses > last_uses {
            script_properties.intra_paragraph_line_height = line_height;
            last_uses = uses;
        }
    }

    (script_properties, lines)
}

#[derive(Debug, Clone)]
enum DialogPart {
    Dialog(String),
    Direction(String),
}

#[derive(Debug, Clone)]
enum ScenePart {
    Direction {
        direction: String,
        page: u32,
    },
    Dialog {
        speaker: String,
        dialog: Vec<DialogPart>,
        page: u32,
    }
}

#[derive(Debug, Clone)]
enum ScriptPart {
    Separator,
    ScenePart(ScenePart),
    LocationChange(String),
    SceneChange,
}

fn is_location_change(line: &str) -> bool {
    line.starts_with("INT.") || line.starts_with("EXT.")
}

fn is_scene_change(line: &str) -> bool {
    line.starts_with("CUT TO")
}

fn extract_script_parts(properties: ScriptProperties, lines: &Vec<(LineAttributes, String)>)
    -> Vec<ScriptPart> {
    let mut script_parts: Vec<ScriptPart> = Vec::new();
    let mut last_top_position = 0;

    for line in lines.iter() {
        let &(ref attributes, ref line) = line;

        if line.len() == 0 {
            continue;
        }

        // check if a new section starts
        if attributes.top - last_top_position > 18 ||
           attributes.top - last_top_position < 0 {
            // used to separate two consecutive script parts of the
            // same type. this is just a implementation detail of
            // the parsing. the Separator can be ignored later.
            script_parts.push(ScriptPart::Separator);
        }

        if attributes.left == properties.direction_position {
            if is_location_change(line) {
                script_parts.push(ScriptPart::LocationChange(line.clone()));
            } else {
                // ensure the last script part is a direction
                if let Some(&ScriptPart::ScenePart(ScenePart::Direction{..})) = script_parts.last() {
                } else {
                    script_parts.push(ScriptPart::ScenePart(
                        ScenePart::Direction{
                            direction: String::new(),
                            page: attributes.page,
                        }));
                }

                if let Some(&mut ScriptPart::ScenePart(ScenePart::Direction{ref mut direction, ..})) = script_parts.last_mut() {
                    if direction.len() > 0 {
                        direction.push(' ');
                    }
                    direction.push_str(line);
                }
            }
        } else if attributes.left == properties.speaker_position ||
                  attributes.left == properties.speaker_direction_position ||
                  attributes.left == properties.dialog_position {
            // Ensure the last script part is a dialog
            if let Some(&ScriptPart::ScenePart(ScenePart::Dialog{..})) = script_parts.last() {
            } else {
                script_parts.push(ScriptPart::ScenePart(
                    ScenePart::Dialog{
                        speaker: String::new(),
                        dialog: Vec::new(),
                        page: attributes.page,
                    }));
            }

            // get the dialog, should never fail (see above)
            if let Some(&mut ScriptPart::ScenePart(ScenePart::Dialog{ref mut speaker, ref mut dialog, ..})) = script_parts.last_mut() {
                if attributes.left == properties.speaker_position {
                    // there is only one speaker per dialog
                    speaker.push_str(line);
                } else if attributes.left == properties.speaker_direction_position {
                    if let Some(&DialogPart::Direction(_)) = dialog.last() {
                    } else {
                        dialog.push(DialogPart::Direction(String::new()));
                    }

                    if let Some(&mut DialogPart::Direction(ref mut direction)) = dialog.last_mut() {
                        if direction.len() > 0 {
                            direction.push(' ');
                        }
                        direction.push_str(line);
                    }
                } else if attributes.left == properties.dialog_position {
                    if let Some(&DialogPart::Dialog(_)) = dialog.last() {
                    } else {
                        dialog.push(DialogPart::Dialog(String::new()));
                    }

                    if let Some(&mut DialogPart::Dialog(ref mut dialog)) = dialog.last_mut() {
                        if dialog.len() > 0 {
                            dialog.push(' ');
                        }
                        dialog.push_str(line);
                    }
                }
            }
        } else {
            if is_scene_change(line) {
                script_parts.push(ScriptPart::SceneChange);
            }
        }

        last_top_position = attributes.top;
    }

    script_parts
}

#[derive(Default, Clone, Debug)]
struct Location {
	internal: bool,
	name: String,
	parts: Vec<ScenePart>,
}

type Scene = Vec<Location>;

fn extract_scenes(script_parts: &Vec<ScriptPart>) -> Vec<Scene> {
	let mut scenes = Vec::new();

    // scene with default (empty) location
	let default_scene: Scene = vec![Default::default()];
	scenes.push(default_scene.clone());

	for script_part in script_parts.iter() {
		use ScriptPart::*;
		match script_part {
			&SceneChange => {
				// unwrap is save, see default_scene
				if scenes.last().unwrap().len() > 0 {
					scenes.push(default_scene.clone());
				}
			}
			&LocationChange(ref location) => {
				// unwraps are safe, see default_scene
				let mut current_scene = scenes.last_mut().unwrap();

				if current_scene.last().unwrap().parts.len() == 0 {
					current_scene.pop();
				}
                // TODO: Parse INT./EXT.
				current_scene.push(Location {name: location.clone(), ..Default::default()})
			}
            &ScenePart(ref scene_part) => {
                let scene_parts = &mut scenes.last_mut().unwrap().last_mut().unwrap().parts;
                scene_parts.push(scene_part.clone());
            }
			&Separator => {} //ignore
		}
	}

	scenes
}

#[allow(dead_code)]
fn condense_script_demo(properties: ScriptProperties, lines: &Vec<(LineAttributes, String)>) {
    let mut last_left_position = 0;
    let mut last_top_position = 0;

    for line in lines.iter() {
        let &(ref attributes, ref line) = line;

        if line.len() == 0 {
            continue;
        }

        // start new section
        if last_left_position != attributes.left ||
           attributes.top - last_top_position > 18 ||
           attributes.top - last_top_position < 0 {
            if ! (last_left_position == properties.speaker_direction_position ||
                  last_left_position == properties.speaker_position) {
                // empty line after last section
                println!("");
            }
        }

        match attributes.left {
            k if (k == properties.direction_position)
                => println!("{}", line),
            k if (k == properties.dialog_position)
                => println!("          {}", line),
            k if (k == properties.speaker_direction_position)
                => println!("               {}", line),
            k if (k == properties.speaker_position)
                => println!("                    {}", line),
            _   => println!("------- {}", line),
        }

        last_left_position = attributes.left;
        last_top_position = attributes.top;
    }
}

fn main() {
    let xml_file_name = env::args().skip(1).next().expect("No input file given");

    let file_reader = File::open(xml_file_name).expect("Could not open file");
    let buffered_file_reader = Box::new(BufReader::new(file_reader));

    let (properties, lines) = read_and_analyze_script(buffered_file_reader);

    //condense_script_demo(properties, &lines);
    println!("{:#?}", extract_scenes(&extract_script_parts(properties, &lines)));
}
<|endoftext|>