<commit_before>use combine::{Parser, Stream, ParseError, ParseResult};
use combine::{between, choice, many, many1, optional, parser, satisfy, satisfy_map, sep_by, try};
use combine::char::{alpha_num, digit, char, letter, spaces, string};

use token::{Literal, Token};

pub fn lex<'a>(line: &'a str) -> Result<(Vec<Token>, &'a str), ParseError<&'a str>> {
    spaces()
        .with(parser(token_stream))
        .parse(line)
}

fn literal<I>(input: I) -> ParseResult<Literal, I>
    where I: Stream<Item = char>
{
    let digits = many1::<String, _>(digit());
    let integer = optional(char('-'))
        .and(digits.clone())
        .map(|(sign, s)| {
            let magnitude = s.parse::<i64>().unwrap();
            if sign.is_some() {
                -magnitude
            } else {
                magnitude
            }
        })
        .map(Literal::from);

    let float = optional(char('-'))
        .and((digits.clone(), char('.'), digits.clone())
            .map(|(prefix, _, suffix)| format!("{}.{}", prefix, suffix)))
        .map(|(sign, s)| {
            let magnitude = s.parse::<f64>().unwrap();
            if sign.is_some() {
                -magnitude
            } else {
                magnitude
            }
        })
        .map(Literal::from);

    let num = try(float).or(try(integer));

    let boolean = char('#')
        .with(satisfy_map(|c| {
            match c {
                't' => Some(true),
                'f' => Some(false),
                _ => None,
            }
        }))
        .map(Literal::from);

    let escaped = char('\\')
        .with(satisfy_map(|c| {
            match c {
                '\"' => Some('\"'),
                '\\' => Some('\\'),
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                _ => None,
            }
        }));

    let non_quote = try(escaped).or(satisfy(|c| c != '"'));

    let string = between(char('"'), char('"'), many::<String, _>(non_quote)).map(Literal::from);

    boolean.or(string)
        .or(num)
        .parse_stream(input)
}

fn symbol<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    let first = letter().or(char('_'));
    let rest = many::<String, _>(alpha_num().or(char('_')));
    first.and(rest)
        .map(|(f, mut r)| {
            r.insert(0, f);
            r
        })
        .map(Token::Symbol)
        .parse_stream(input)
}

fn punctuation<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    let single_char_tokens = satisfy_map(|c| {
        match c {
            '(' => Some(Token::LParen),
            ')' => Some(Token::RParen),
            '[' => Some(Token::LBracket),
            ']' => Some(Token::RBracket),
            '+' => Some(Token::Plus),
            '-' => Some(Token::Minus),
            '*' => Some(Token::Star),
            '/' => Some(Token::Slash),
            '=' => Some(Token::Equal),
            '<' => Some(Token::Less),
            '>' => Some(Token::Greater),
            _ => None,
        }
    });

    let two_char_tokens = choice([string("<="), string(">=")]).map(|s| match s {
        "<=" => Token::LessEq,
        ">=" => Token::GreaterEq,
        _ => unreachable!(),
    });

    // Maximal munch: attempt parsing two-char tokens before one-char tokens
    two_char_tokens.or(single_char_tokens).parse_stream(input)
}

fn token<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    parser(symbol)
        .or(parser(literal).map(Token::Literal))
        .or(parser(symbol))
        .or(parser(punctuation))
        .parse_stream(input)
}

fn token_stream<I>(input: I) -> ParseResult<Vec<Token>, I>
    where I: Stream<Item = char>
{
    sep_by(parser(token), spaces()).parse_stream(input)
}

#[cfg(test)]
mod test {
    use float_cmp::ApproxEqUlps;
    use quickcheck::TestResult;
    use super::*;

    #[test]
    fn parse_bool_literal() {
        assert_eq!(Ok((Literal::Bool(true), "")), parser(literal).parse("#t"));
        assert_eq!(Ok((Literal::Bool(false), "")), parser(literal).parse("#f"));
    }

    #[test]
    fn parse_zero_literal() {
        // Integer case
        assert_eq!(Ok((Literal::Int(0i64), "")), parser(literal).parse("0"));

        // Float case
        match parser(literal).parse("0.0") {
            Ok((Literal::Flt(flt), _)) => assert!(flt.approx_eq_ulps(&0.0f64, 4)),
            Ok(x) => assert!(false, format!("0.0 parsed as {}", x.0)),
            Err(e) => assert!(false, format!("0.0 parsed as {}", e)),
        };
    }

    #[test]
    fn parse_escape_chars() {
        assert_eq!(Ok((Literal::Str("\"".into()), "")), parser(literal).parse(r#""\"""#));
        assert_eq!(Ok((Literal::Str("\\".into()), "")), parser(literal).parse(r#""\\""#));
        assert_eq!(Ok((Literal::Str("\n".into()), "")), parser(literal).parse(r#""\n""#));
        assert_eq!(Ok((Literal::Str("\r".into()), "")), parser(literal).parse(r#""\r""#));
        assert_eq!(Ok((Literal::Str("\t".into()), "")), parser(literal).parse(r#""\t""#));
    }

    #[test]
    fn parse_empty() {
        assert_eq!(Ok((Vec::new(), "")), parser(token_stream).parse(""));
    }

    quickcheck!{
        fn parse_int_literal(x: i64) -> bool {
            match parser(literal).parse(&*x.to_string()) {
                Ok((Literal::Int(y), _)) => x == y,
                _ => false,
            }
        }

        fn parse_float_literal(x: f64) -> bool {
            let mut string = x.to_string();
            if x.trunc() == x {
                string.push_str(".0");
            }

            if let Ok((Literal::Flt(y), _)) = parser(literal).parse(&*string) {
                x.approx_eq_ulps(&y, 4)
            } else {
                false
            }
        }

        fn parse_str_literal(x: String) -> () {
            let has_escape_chars = x.contains('\\') || x.contains('\"');
            let string = if has_escape_chars {
                x.chars()
                    .map(char::escape_default)
                    .map(|x| x.to_string())
                    .inspect(|x| println!("{}", x))
                    .collect()
            } else {
                format!("\"{}\"", x)
            };
            match parser(literal).parse(&*string) {
                Ok((Literal::Str(result), _)) => assert_eq!(result, x),
                _ => (),
            }
        }

        fn parse_symbol(x: String) -> TestResult {
            if x.is_empty() {
                return TestResult::discard()
            }

            if !x.chars().next().unwrap().is_alphabetic() {
                return TestResult::discard()
            }

            // Test only valid symbols
            for c in x.chars() {
                if !(c.is_alphanumeric() || c == '_') {
                    return TestResult::discard()
                }
            }

            match parser(symbol).parse(&*x) {
                Ok((Token::Symbol(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }
    }
}
<commit_msg>Improve lexing<commit_after>use combine::{Parser, Stream, ParseError, ParseResult};
use combine::{between, choice, many, many1, optional, parser, satisfy, satisfy_map, sep_by, try};
use combine::char::{alpha_num, digit, char, letter, spaces, string};

use token::{Literal, Token};

pub fn lex<I>(input: I) -> Result<(Vec<Token>, I), ParseError<I>>
    where I: Stream<Item = char>
{
    spaces().with(sep_by(parser(token), spaces()))
        .parse(input)
}

fn literal<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    let sign = optional(char('-'));
    let digits = many1::<String, _>(digit());
    let integer = sign.clone()
        .and(digits.clone()
                .and_then(|s| s.parse::<i64>()))
        .map(|(sign, num)| {
            if sign.is_some() { -num } else { num }
        })
        .map(Literal::from);

    let float = sign.clone()
        .and((digits.clone(), char('.'), digits.clone())
            .map(|(prefix, _, suffix)| format!("{}.{}", prefix, suffix))
            .and_then(|num| num.parse::<f64>()))
        .map(|(sign, num)| {
            if sign.is_some() { -num } else { num }
        })
        .map(Literal::from);

    let num = try(float).or(try(integer));

    let boolean = char('#')
        .with(satisfy_map(|c| {
            match c {
                't' => Some(true),
                'f' => Some(false),
                _ => None,
            }
        }))
        .map(Literal::from);

    let escaped = char('\\')
        .with(satisfy_map(|c| {
            match c {
                '\"' => Some('\"'),
                '\\' => Some('\\'),
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                _ => None,
            }
        }));

    let non_quote = try(escaped).or(satisfy(|c| c != '"'));

    let string = between(char('"'), char('"'), many::<String, _>(non_quote)).map(Literal::from);

    choice!(boolean, string, num)
        .map(Token::from)
        .parse_stream(input)
}

fn symbol<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    let first = letter().or(char('_'));
    let rest = many::<String, _>(alpha_num().or(char('_')));
    first.and(rest)
        .map(|(f, mut r)| {
            r.insert(0, f);
            r
        })
        .map(Token::Symbol)
        .parse_stream(input)
}

fn punctuation<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    let single_char_tokens = satisfy_map(|c| {
        match c {
            '(' => Some(Token::LParen),
            ')' => Some(Token::RParen),
            '[' => Some(Token::LBracket),
            ']' => Some(Token::RBracket),
            '+' => Some(Token::Plus),
            '-' => Some(Token::Minus),
            '*' => Some(Token::Star),
            '/' => Some(Token::Slash),
            '=' => Some(Token::Equal),
            '<' => Some(Token::Less),
            '>' => Some(Token::Greater),
            _ => None,
        }
    });

    let two_char_tokens = choice([string("<="), string(">=")]).map(|s| match s {
        "<=" => Token::LessEq,
        ">=" => Token::GreaterEq,
        _ => unreachable!(),
    });

    // Maximal munch: attempt parsing two-char tokens before one-char tokens
    two_char_tokens.or(single_char_tokens).parse_stream(input)
}

fn token<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item = char>
{
    choice!(
        parser(symbol),
        parser(literal),
        parser(symbol),
        parser(punctuation)
    ).parse_stream(input)
}

#[cfg(test)]
mod test {
    use float_cmp::ApproxEqUlps;
    use quickcheck::TestResult;
    use super::*;

    #[test]
    fn parse_bool_literal() {
        assert_eq!(Ok((Token::from(true), "")), parser(literal).parse("#t"));
        assert_eq!(Ok((Token::from(false), "")), parser(literal).parse("#f"));
    }

    #[test]
    fn parse_zero_literal() {
        // Integer case
        assert_eq!(Ok((Token::from(0i64), "")), parser(literal).parse("0"));

        // Float case
        match parser(literal).parse("0.0") {
            Ok((Token::Literal(Literal::Flt(flt)), _)) => assert!(flt.approx_eq_ulps(&0.0f64, 4)),
            Ok(x) => assert!(false, format!("0.0 parsed as {}", x.0)),
            Err(e) => assert!(false, format!("0.0 parsed as {}", e)),
        };
    }

    #[test]
    fn parse_escape_chars() {
        assert_eq!(Ok((Token::from("\""), "")), parser(literal).parse(r#""\"""#));
        assert_eq!(Ok((Token::from("\\"), "")), parser(literal).parse(r#""\\""#));
        assert_eq!(Ok((Token::from("\n"), "")), parser(literal).parse(r#""\n""#));
        assert_eq!(Ok((Token::from("\r"), "")), parser(literal).parse(r#""\r""#));
        assert_eq!(Ok((Token::from("\t"), "")), parser(literal).parse(r#""\t""#));
    }

    #[test]
    fn parse_empty() {
        assert_eq!(Ok((Vec::new(), "")), lex(""));
    }

    quickcheck!{
        fn parse_int_literal(x: i64) -> () {
            assert_eq!(Ok((Token::from(x), "")), parser(literal).parse(&*x.to_string()));
        }

        fn parse_float_literal(x: f64) -> bool {
            let mut string = x.to_string();
            if x.trunc() == x {
                string.push_str(".0");
            }

            if let Ok((Token::Literal(Literal::Flt(y)), _)) = parser(literal).parse(&*string) {
                x.approx_eq_ulps(&y, 4)
            } else {
                false
            }
        }

        fn parse_str_literal(x: String) -> bool {
            let has_escape_chars = x.contains('\\') || x.contains('\"');
            let string = if has_escape_chars {
                x.chars()
                    .map(char::escape_default)
                    .map(|y| y.to_string())
                    .collect()
            } else {
                format!("\"{}\"", x)
            };
            Ok((Token::from(x.clone()), "")) == parser(literal).parse(&*string)
        }

        fn parse_symbol(x: String) -> TestResult {
            if x.is_empty() {
                return TestResult::discard()
            }

            if !x.chars().next().unwrap().is_alphabetic() {
                return TestResult::discard()
            }

            // Test only valid symbols
            for c in x.chars() {
                if !(c.is_alphanumeric() || c == '_') {
                    return TestResult::discard()
                }
            }

            match parser(symbol).parse(&*x) {
                Ok((Token::Symbol(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Shader module.
//!
//! Shader functions and declarations can be grouped in so-called *modules*. Modules structure is
//! inherently tied to the filesystem’s tree.
//!
//! You’re not supposed to use modules at the Rust level, even though you can. You’re supposed to
//! actually write modules that will be used by shader programs.

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

use render::shader::lang::parser;
use render::shader::lang::syntax::{Module as SyntaxModule};
use sys::resource::{CacheKey, Load, LoadError, LoadResult, Store, StoreKey};

/// Shader module.
///
/// A shader module is a piece of GLSL code with optional import lists (dependencies).
///
/// You’re not supposed to directly manipulate any object of this type. You just write modules on
/// disk and let everyting happen automatically for you.
#[derive(Clone, Debug, PartialEq)]
pub struct Module(SyntaxModule);

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ModuleKey(String);

impl ModuleKey {
  pub fn new(key: &str) -> Self {
    ModuleKey(key.to_owned())
  }
}

impl CacheKey for ModuleKey {
  type Target = Module;
}

impl StoreKey for ModuleKey {
  fn key_to_path(&self) -> PathBuf {
    self.0.clone().into()
  }
}

impl Load for Module {
  fn load<P>(path: P, _: &mut Store) -> Result<LoadResult<Self>, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    let mut fh = File::open(path).map_err(|_| LoadError::FileNotFound(path.to_owned()))?;
    let mut src = String::new();
    let _ = fh.read_to_string(&mut src);

    match parser::parse_str(&src[..], parser::module) {
      parser::ParseResult::Ok(module) => {
        Ok(Module(module).into())
      }
      parser::ParseResult::Err(e) => Err(LoadError::ConversionFailed(format!("{:?}", e))),
      _ => Err(LoadError::ConversionFailed("incomplete input".to_owned()))
    }
  }
}

<commit_msg>First shot at no-cycle shader modules.<commit_after>//! Shader module.
//!
//! Shader functions and declarations can be grouped in so-called *modules*. Modules structure is
//! inherently tied to the filesystem’s tree.
//!
//! You’re not supposed to use modules at the Rust level, even though you can. You’re supposed to
//! actually write modules that will be used by shader programs.

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

use render::shader::lang::parser;
use render::shader::lang::syntax::{Module as SyntaxModule, ModulePath};
use sys::resource::{CacheKey, Load, LoadError, LoadResult, Store, StoreKey};

// FIXME: see where to put that shit; especially, ModuleKey should be implemented with ModuleKe(ModulePath), LOL
fn module_path_to_module_key(mp: &ModulePath) -> ModuleKey {
  ModuleKey(mp.path.join("/") + ".spsl")
}

/// Shader module.
///
/// A shader module is a piece of GLSL code with optional import lists (dependencies).
///
/// You’re not supposed to directly manipulate any object of this type. You just write modules on
/// disk and let everyting happen automatically for you.
#[derive(Clone, Debug, PartialEq)]
pub struct Module(SyntaxModule);

impl Module {
  /// Retrieve all the modules this module depends on, without duplicates.
  pub fn deps(&self, store: &mut Store, path: &ModulePath) -> Result<Vec<ModulePath>, DepsError> {
    let mut deps = Vec::new();
    self.deps_no_cycle(store, &path, &mut Vec::new(), &mut deps).map(|_| deps)
  }

  fn deps_no_cycle(&self, store: &mut Store, path: &ModulePath, parents: &mut Vec<ModulePath>, deps: &mut Vec<ModulePath>) -> Result<(), DepsError> {
    let imports = self.0.imports.iter().map(|il| &il.module);

    parents.push(path.clone());

    for module_name in imports {
      // check whether it’s already in the deps
      if deps.contains(module_name) {
        continue;
      }

      // check whether the module was already visited
      if parents.contains(module_name) {
        return Err(DepsError::Cycle(path.clone(), module_name.clone()));
      }

      // get the dependency module
      let module = store.get(&module_path_to_module_key(&module_name)).ok_or_else(|| DepsError::LoadError(module_name.clone()))?;
      let r = module.borrow().deps_no_cycle(store, module_name, parents, deps)?;

      deps.push(module_name.clone());
      parents.pop();
    }

    Ok(())
  }
}

/// Class of errors that can happen in dependencies.
#[derive(Clone, Debug, PartialEq)]
pub enum DepsError {
  /// If a module’s dependencies has any cycle, the dependencies are unusable and the cycle is
  /// returned.
  Cycle(ModulePath, ModulePath),
  /// There was a loading error of a module.
  LoadError(ModulePath)
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ModuleKey(String);

impl ModuleKey {
  pub fn new(key: &str) -> Self {
    ModuleKey(key.to_owned())
  }
}

impl CacheKey for ModuleKey {
  type Target = Module;
}

impl StoreKey for ModuleKey {
  fn key_to_path(&self) -> PathBuf {
    self.0.clone().into()
  }
}

impl Load for Module {
  fn load<P>(path: P, _: &mut Store) -> Result<LoadResult<Self>, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    let mut fh = File::open(path).map_err(|_| LoadError::FileNotFound(path.to_owned()))?;
    let mut src = String::new();
    let _ = fh.read_to_string(&mut src);

    match parser::parse_str(&src[..], parser::module) {
      parser::ParseResult::Ok(module) => {
        Ok(Module(module).into())
      }
      parser::ParseResult::Err(e) => Err(LoadError::ConversionFailed(format!("{:?}", e))),
      _ => Err(LoadError::ConversionFailed("incomplete input".to_owned()))
    }
  }
}

<|endoftext|>


<commit_before>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use x11::xlib::{ Display, Window };
use super::WindowManager;
use super::workspace::Workspaces;
use super::layout;
use super::super::libx;
use super::super::libx::Context;

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: u64,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        println!("bind {} {}", mask, sym);
        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: layout::Direction,
}

pub struct WindowCloseHandler;

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("change focus in current workspace");
        let (window, _) = libx::get_input_focus(context);

        println!("window {}", window);
        let current = workspaces.current();
        match current.contain(window) {
            Some(i) => {
                let next = if (i+1) >= current.size() { 0 } else { i+1 };
                libx::set_input_focus(context, current.get(next));
            }
            None => {}
        }

    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle window move form {} to {}", workspaces.current_name(), self.key);

        let (window, _) = libx::get_input_focus(context);
        println!("window {}", window);

        // let mut root: Window = 0;
        // let mut parent: Window = window;
        // let mut children: *mut Window = ptr::null_mut();
        // let mut nchildren: libc::c_uint = 0;

        // while parent != root {
        //     window = parent;
        //     unsafe{
        //         let s = xlib::XQueryTree(context, window, &mut root, &mut parent, &mut children, &mut nchildren);
        //         if s > 0 {
        //             println!("parent {} root {}", parent, root);
        //             xlib::XFree(children as *mut libc::c_void);
        //         }
        //         else{
        //             println!("error");
        //         }
        //     }
        // }

        println!("focused window {}", window);
        let from = workspaces.current_name();
        let to = self.key;

        if !workspaces.contain(to) {
            workspaces.create(to, screen_num);
        }

        workspaces.move_window(window, from, to);
        match workspaces.get(from){
            Some(w) => { w.config(context)}
            None => {}
        };

        match workspaces.get(self.key) {
            Some(w) => {
                w.config(context)
            }
            None => {}
        };
    }
}

impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key, screen_num);
        }
        workspaces.switch_current(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle layout");
        let current = workspaces.current();
        let t = self.layout_type.clone();
        current.change_layout(t);
        current.config(context);
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);

        for arg in args {
            println!("{}", arg);
            cmd.arg(arg);
        }

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<commit_msg>use wrapper<commit_after>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use x11::xlib::{ Display, Window };
use super::WindowManager;
use super::Workspaces;
use super::layout;
use super::super::libx;
use super::super::libx::Context;

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: u64,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        println!("bind {} {}", mask, sym);
        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: layout::Direction,
}

pub struct WindowCloseHandler;

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("change focus in current workspace");
        let window = workspaces.get_focus(context);

        println!("window {}", window);
        let current = workspaces.current();
        match current.contain(window) {
            Some(i) => {
                let next = current.next_window(window);
                current.set_focus(Some(next), context);
            }
            None => {}
        }

    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        let window = workspaces.get_focus(context);
        debug!("handle window {} move form {} to {}", window, workspaces.current_name(), self.key);

        let from = workspaces.current_name();
        let to = self.key;
        workspaces.move_window(window, from, to, context);
        println!("focus {}", workspaces.get_focus(context));
    }
}

impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key, screen_num);
        }
        workspaces.switch_current(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context, screen_num: libc::c_int) {
        debug!("handle layout");
        let current = workspaces.current();
        let t = self.layout_type.clone();
        current.change_layout(t);
        current.config(context);
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);

        for arg in args {
            println!("{}", arg);
            cmd.arg(arg);
        }

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<|endoftext|>


<commit_before>mod quick_error;

use std::result::Result as StdResult;
use std::error::Error as StdError;

pub trait BuildChain<E> {
    fn new_chain(e: E) -> Self;
    fn extend_chain<SE>(e: E, c: SE) -> Self
        where SE: StdError + Send + 'static;
}

pub trait ChainError<T> {
    fn chain_error<F, E, EC>(self, callback: F) -> StdResult<T, EC>
        where F: FnOnce() -> E,
              E: StdError + Send + 'static,
              EC: BuildChain<E>;
}

impl<T, E> ChainError<T> for StdResult<T, E>
    where E: StdError + Send + 'static
{
    fn chain_error<F, E2, EC>(self, callback: F) -> StdResult<T, EC>
        where F: FnOnce() -> E2,
              E2: StdError + Send + 'static,
              EC: BuildChain<E2>
    {
        self.map_err(move |e| {
            BuildChain::extend_chain(callback(), e)
        })
    }
}

#[macro_export]
macro_rules! easy_error {
    (   $(#[$meta:meta])*
        pub enum $name:ident { $($chunks:tt)* }
    ) => {
        quick_error! {
            $(#[$meta])*
            pub enum $name {
                $($chunks)*
            }
        }

        impl $name {
            pub fn unchained(self) -> ErrorChain<$name> {
                $crate::BuildChain::new_chain(self)
            }

            pub fn chained<E>(self, e: E) -> ErrorChain<$name>
                where E: ::std::error::Error + Send + 'static
            {
                $crate::BuildChain::extend_chain(self, e)
            }
        }

        #[derive(Debug)]
        pub struct ErrorChain<E>(pub E, pub Option<Box<::std::error::Error + Send>>);

        impl<E> $crate::BuildChain<E> for ErrorChain<E> {
            fn new_chain(e: E) -> Self {
                ErrorChain(e, None)
            }

            fn extend_chain<SE>(e: E, c: SE) -> Self
                where SE: ::std::error::Error + Send + 'static
            {
                ErrorChain(e, Some(Box::new(c)))
            }
        }

        impl<E> ::std::error::Error for ErrorChain<E>
            where E: ::std::error::Error
        {
            fn description(&self) -> &str { self.0.description() }
            fn cause(&self) -> Option<&::std::error::Error> {
                match self.1 {
                    Some(ref c) => Some(&**c),
                    None => None
                }
            }
        }

        impl<E> ::std::fmt::Display for ErrorChain<E>
            where E: ::std::fmt::Display
        {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::Display::fmt(&self.0, f)
            }
        }

    };
    (   $(#[$meta:meta])*
        enum $name:ident { $($chunks:tt)* }
    ) => {
        quick_error! {
            $(#[$meta])*
            enum $name {
                $($chunks)*
            }
        }

        impl $name {
            fn unchained(self) -> ErrorChain<$name> {
                $crate::ErrorChain::new_chain(self)
            }

            fn chained<E>(self, e: E) -> ErrorChain<$name>
                where E: ::std::error::Error + Send + 'static
            {
                $crate::ErrorChain::extend_chain(self, e)
            }
        }
    };
}
<commit_msg>Remove the non-pub version of the macro. Bothersome to maintain<commit_after>mod quick_error;

use std::result::Result as StdResult;
use std::error::Error as StdError;

pub trait BuildChain<E> {
    fn new_chain(e: E) -> Self;
    fn extend_chain<SE>(e: E, c: SE) -> Self
        where SE: StdError + Send + 'static;
}

pub trait ChainError<T> {
    fn chain_error<F, E, EC>(self, callback: F) -> StdResult<T, EC>
        where F: FnOnce() -> E,
              E: StdError + Send + 'static,
              EC: BuildChain<E>;
}

impl<T, E> ChainError<T> for StdResult<T, E>
    where E: StdError + Send + 'static
{
    fn chain_error<F, E2, EC>(self, callback: F) -> StdResult<T, EC>
        where F: FnOnce() -> E2,
              E2: StdError + Send + 'static,
              EC: BuildChain<E2>
    {
        self.map_err(move |e| {
            BuildChain::extend_chain(callback(), e)
        })
    }
}

#[macro_export]
macro_rules! easy_error {
    (   $(#[$meta:meta])*
        pub enum $name:ident { $($chunks:tt)* }
    ) => {
        quick_error! {
            $(#[$meta])*
            pub enum $name {
                $($chunks)*
            }
        }

        impl $name {
            pub fn unchained(self) -> ErrorChain<$name> {
                $crate::BuildChain::new_chain(self)
            }

            pub fn chained<E>(self, e: E) -> ErrorChain<$name>
                where E: ::std::error::Error + Send + 'static
            {
                $crate::BuildChain::extend_chain(self, e)
            }
        }

        #[derive(Debug)]
        pub struct ErrorChain<E>(pub E, pub Option<Box<::std::error::Error + Send>>);

        impl<E> $crate::BuildChain<E> for ErrorChain<E> {
            fn new_chain(e: E) -> Self {
                ErrorChain(e, None)
            }

            fn extend_chain<SE>(e: E, c: SE) -> Self
                where SE: ::std::error::Error + Send + 'static
            {
                ErrorChain(e, Some(Box::new(c)))
            }
        }

        impl<E> ::std::error::Error for ErrorChain<E>
            where E: ::std::error::Error
        {
            fn description(&self) -> &str { self.0.description() }
            fn cause(&self) -> Option<&::std::error::Error> {
                match self.1 {
                    Some(ref c) => Some(&**c),
                    None => None
                }
            }
        }

        impl<E> ::std::fmt::Display for ErrorChain<E>
            where E: ::std::fmt::Display
        {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::Display::fmt(&self.0, f)
            }
        }

    };
}
<|endoftext|>


<commit_before>
//
//             MBAST: Mini B-language Abstract Syntax Tree
//
// It's a "mini" B-AST because the types allow more than legal B in order to
// simplify and factorize.

#![allow(dead_code)]

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Component {
    pub kind: ComponentKind,
    pub name: String,
    pub formal_param: Vec<String>,
    pub refines: Option<String>,

    pub imports: Vec< ( String, Option<Box<Expr>> ) >,
    pub includes: Vec< ( String, Option<Box<Expr>> ) >,
    pub extends: Vec< ( String, Option<Box<Expr>> ) >,

    pub sees: Vec<String>,
    pub promotes: Vec<String>,
    pub uses: Vec<String>,

    pub abstract_constants: Vec<String>,
    pub abstract_variables: Vec<String>,
    pub concrete_constants: Vec<String>,
    pub concrete_variables: Vec<String>,
    pub constants: Vec<String>,
    pub variables: Vec<String>,

    pub constraints: Option<Box<Expr>>,
    pub properties: Option<Box<Expr>>,
    pub invariant: Option<Box<Expr>>,

    pub sets: Vec<Box<Expr>>,
    pub values: Vec<Box<Expr>>,
    pub assertions: Vec<Box<Expr>>,

    pub initialisation: Option<Box<Sub>>,
    pub operations: Vec<Box<Ope>>,
    pub local_operations: Vec<Box<Ope>>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Ope{
    pub param_out: Vec<String>,
    pub name: String,
    pub param_in: Vec<String>,
    pub sub: Box<Sub>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Sub {
    Begin( Box<Sub> ),

    Bin(Box<Sub>, SubBinOpe, Box<Sub>),
    Simple(Box<Expr>, SubSimple, Box<Expr>),
    OpeCall(Vec<String>, String, Vec<Box<Expr>>),

    PreAssert( SubPreAssertOpe, Box<Expr>, Box<Sub> ),

    AnyLet( SubAnyLet, Vec<String>, Box<Expr>, Box<Sub> ),

    Var( Vec<String>, Box<Sub> ),

    Choice( Vec<Box<Sub>> ),

    IfSelect( SubIfSelect, Vec<( Box<Expr>, Box<Sub> )>, Option<Box<Sub>> ),

    Case( Box<Expr>, Vec<( Box<Expr>, Box<Sub> )>, Option<Box<Sub>> ),

    While( Box<Expr>, Box<Sub>, Box<Expr>, Box<Expr> ),
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Expr {
    Unary( ExprUnaryOpe, Box<Expr> ),

    Struct( Vec< ( String, Box<Expr> ) > ),
    Rec( Vec< ( Option<String>, Box<Expr> ) > ),

    Bin( Box<Expr>, ExprBinOpe, Box<Expr> ),

    Id(String),
    Num(String),

    QPred( ExprQPredOpe, Vec<String>, Box<Expr> ),
    Quant( ExprQuantOpe, Vec<String>, Box<Expr>, Box<Expr> ),
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ComponentKind{ Machine, Refinement, Implementation }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubSimple{
    Assign,         // expr := expr
    BecomeIn,       // expr :: expr
    BecomeSuchThat, // expr : ( expr )
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubBinOpe{
    Sequence,       // sub ; sub
    Parallel,       // sub || sub
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubPreAssertOpe{ Pre, Assert }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubAnyLet{ Any, Let }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubIfSelect{ If, Select }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprUnaryOpe
{   Minus               // -x
,   Inverse             // x~
,   Negate              // not(x)
,   Paren               // (x)
,   SetExtension        // {x}
,   ListExtension       // [x]
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprQPredOpe{ Forall, Exist }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprQuantOpe{ Lambda, Sigma, Pi, Union, Inter }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprBinOpe
{   Apply         // f(x)
,   Image         // r[x]
,   SetCompreh    // { x | P }
,   Mod           // x mod y
,   Or            // x or y
,   Comma         // ,
,   Maplet        // |->
,   Plus          // +
,   Minus         // -
,   Star          // *
,   Slash         // /
,   Pow           // **
,   And           // &
,   Imply         // =>
,   Equiv         // <=>
,   Barbar        // ||
,   Semicolon     // ;
,   Equal         // =
,   Neq           // /=
,   Lt            // <
,   Leq           // <=
,   Gt            // >
,   Geq           // >=
,   Colon         // :
,   Nin           // /:
,   Incl          // <:
,   Nincl         // /<:
,   Inclstr       // <<:
,   Ninclstr      // /<<:
,   Pfun          // +->
,   Pinj          // >+>
,   Psur          // +->>
,   Pbij          // >+>>
,   Tfun          // -->
,   Tinj          // >->
,   Tsur          // -->>
,   Tbij          // >->>
,   Sinter        // /\
,   Sunion        // \/
,   Overw         // <+
,   Rel           // <->
,   Reldprod      // ><
,   Interval      // ..
,   Domrestr      // <|
,   Domsub        // <<|
,   Ranrestr      // |>
,   Ransub        // |>>
,   Larw          // <-
,   Rarw          // ->
,   Uparrow       // /|\
,   Lowarrow      // \|/
,   Caret         // ^
}

pub struct ComponentBuilder {
    pub refines: Option<String>,

    pub imports: Vec< ( String, Option<Box<Expr>> ) >,
    pub includes: Vec< ( String, Option<Box<Expr>> ) >,
    pub extends: Vec< ( String, Option<Box<Expr>> ) >,

    pub sees: Vec<String>,
    pub promotes: Vec<String>,
    pub uses: Vec<String>,

    pub abstract_constants: Vec<String>,
    pub abstract_variables: Vec<String>,
    pub concrete_constants: Vec<String>,
    pub concrete_variables: Vec<String>,
    pub constants: Vec<String>,
    pub variables: Vec<String>,

    pub constraints: Option<Box<Expr>>,
    pub properties: Option<Box<Expr>>,
    pub invariant: Option<Box<Expr>>,

    pub sets: Vec<Box<Expr>>,
    pub values: Vec<Box<Expr>>,
    pub assertions: Vec<Box<Expr>>,

    pub initialisation: Option<Box<Sub>>,
    pub operations: Vec<Box<Ope>>,
    pub local_operations: Vec<Box<Ope>>,
}

impl ComponentBuilder {
    pub fn new() -> ComponentBuilder {
        ComponentBuilder {
            refines: None,

            imports: vec![],
            includes: vec![],
            extends: vec![],

            sees: vec![],
            promotes: vec![],
            uses: vec![],

            abstract_constants: vec![],
            abstract_variables: vec![],
            concrete_constants: vec![],
            concrete_variables: vec![],
            constants: vec![],
            variables: vec![],

            constraints: None,
            properties : None,
            invariant  : None,

            sets: vec![],
            values: vec![],
            assertions: vec![],

            initialisation: None,
            operations: vec![],
            local_operations: vec![],
        }
    }

    pub fn finalize(&self,
                    kind: ComponentKind,
                    name: String,
                    formal_param: Vec<String> ) -> Component {
        Component
        {   kind               : kind
        ,   name               : name
        ,   formal_param       : formal_param
        ,   refines            : self.refines.clone()
        ,   imports            : self.imports.clone()
        ,   includes           : self.includes.clone()
        ,   extends            : self.extends.clone()
        ,   sees               : self.sees.clone()
        ,   promotes           : self.promotes.clone()
        ,   uses               : self.uses.clone()
        ,   abstract_constants : self.abstract_constants.clone()
        ,   abstract_variables : self.abstract_variables.clone()
        ,   concrete_constants : self.concrete_constants.clone()
        ,   concrete_variables : self.concrete_variables.clone()
        ,   constants          : self.constants.clone()
        ,   variables          : self.variables.clone()
        ,   constraints        : self.constraints.clone()
        ,   properties         : self.properties.clone()
        ,   invariant          : self.invariant.clone()
        ,   sets               : self.sets.clone()
        ,   values             : self.values.clone()
        ,   assertions         : self.assertions.clone()
        ,   initialisation     : self.initialisation.clone()
        ,   operations         : self.operations.clone()
        ,   local_operations   : self.local_operations.clone()
        // TODO avoid the cloning
        }
    }
}
<commit_msg>switch to a consuming builder pattern<commit_after>
//
//             MBAST: Mini B-language Abstract Syntax Tree
//
// It's a "mini" B-AST because the types allow more than legal B in order to
// simplify and factorize.

#![allow(dead_code)]

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Component {
    pub kind: ComponentKind,
    pub name: String,
    pub formal_param: Vec<String>,
    pub refines: Option<String>,

    pub imports: Vec< ( String, Option<Box<Expr>> ) >,
    pub includes: Vec< ( String, Option<Box<Expr>> ) >,
    pub extends: Vec< ( String, Option<Box<Expr>> ) >,

    pub sees: Vec<String>,
    pub promotes: Vec<String>,
    pub uses: Vec<String>,

    pub abstract_constants: Vec<String>,
    pub abstract_variables: Vec<String>,
    pub concrete_constants: Vec<String>,
    pub concrete_variables: Vec<String>,
    pub constants: Vec<String>,
    pub variables: Vec<String>,

    pub constraints: Option<Box<Expr>>,
    pub properties: Option<Box<Expr>>,
    pub invariant: Option<Box<Expr>>,

    pub sets: Vec<Box<Expr>>,
    pub values: Vec<Box<Expr>>,
    pub assertions: Vec<Box<Expr>>,

    pub initialisation: Option<Box<Sub>>,
    pub operations: Vec<Box<Ope>>,
    pub local_operations: Vec<Box<Ope>>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Ope{
    pub param_out: Vec<String>,
    pub name: String,
    pub param_in: Vec<String>,
    pub sub: Box<Sub>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Sub {
    Begin( Box<Sub> ),

    Bin(Box<Sub>, SubBinOpe, Box<Sub>),
    Simple(Box<Expr>, SubSimple, Box<Expr>),
    OpeCall(Vec<String>, String, Vec<Box<Expr>>),

    PreAssert( SubPreAssertOpe, Box<Expr>, Box<Sub> ),

    AnyLet( SubAnyLet, Vec<String>, Box<Expr>, Box<Sub> ),

    Var( Vec<String>, Box<Sub> ),

    Choice( Vec<Box<Sub>> ),

    IfSelect( SubIfSelect, Vec<( Box<Expr>, Box<Sub> )>, Option<Box<Sub>> ),

    Case( Box<Expr>, Vec<( Box<Expr>, Box<Sub> )>, Option<Box<Sub>> ),

    While( Box<Expr>, Box<Sub>, Box<Expr>, Box<Expr> ),
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Expr {
    Unary( ExprUnaryOpe, Box<Expr> ),

    Struct( Vec< ( String, Box<Expr> ) > ),
    Rec( Vec< ( Option<String>, Box<Expr> ) > ),

    Bin( Box<Expr>, ExprBinOpe, Box<Expr> ),

    Id(String),
    Num(String),

    QPred( ExprQPredOpe, Vec<String>, Box<Expr> ),
    Quant( ExprQuantOpe, Vec<String>, Box<Expr>, Box<Expr> ),
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ComponentKind{ Machine, Refinement, Implementation }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubSimple{
    Assign,         // expr := expr
    BecomeIn,       // expr :: expr
    BecomeSuchThat, // expr : ( expr )
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubBinOpe{
    Sequence,       // sub ; sub
    Parallel,       // sub || sub
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubPreAssertOpe{ Pre, Assert }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubAnyLet{ Any, Let }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SubIfSelect{ If, Select }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprUnaryOpe
{   Minus               // -x
,   Inverse             // x~
,   Negate              // not(x)
,   Paren               // (x)
,   SetExtension        // {x}
,   ListExtension       // [x]
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprQPredOpe{ Forall, Exist }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprQuantOpe{ Lambda, Sigma, Pi, Union, Inter }

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExprBinOpe
{   Apply         // f(x)
,   Image         // r[x]
,   SetCompreh    // { x | P }
,   Mod           // x mod y
,   Or            // x or y
,   Comma         // ,
,   Maplet        // |->
,   Plus          // +
,   Minus         // -
,   Star          // *
,   Slash         // /
,   Pow           // **
,   And           // &
,   Imply         // =>
,   Equiv         // <=>
,   Barbar        // ||
,   Semicolon     // ;
,   Equal         // =
,   Neq           // /=
,   Lt            // <
,   Leq           // <=
,   Gt            // >
,   Geq           // >=
,   Colon         // :
,   Nin           // /:
,   Incl          // <:
,   Nincl         // /<:
,   Inclstr       // <<:
,   Ninclstr      // /<<:
,   Pfun          // +->
,   Pinj          // >+>
,   Psur          // +->>
,   Pbij          // >+>>
,   Tfun          // -->
,   Tinj          // >->
,   Tsur          // -->>
,   Tbij          // >->>
,   Sinter        // /\
,   Sunion        // \/
,   Overw         // <+
,   Rel           // <->
,   Reldprod      // ><
,   Interval      // ..
,   Domrestr      // <|
,   Domsub        // <<|
,   Ranrestr      // |>
,   Ransub        // |>>
,   Larw          // <-
,   Rarw          // ->
,   Uparrow       // /|\
,   Lowarrow      // \|/
,   Caret         // ^
}

pub struct ComponentBuilder {
    pub refines: Option<String>,

    pub imports: Vec< ( String, Option<Box<Expr>> ) >,
    pub includes: Vec< ( String, Option<Box<Expr>> ) >,
    pub extends: Vec< ( String, Option<Box<Expr>> ) >,

    pub sees: Vec<String>,
    pub promotes: Vec<String>,
    pub uses: Vec<String>,

    pub abstract_constants: Vec<String>,
    pub abstract_variables: Vec<String>,
    pub concrete_constants: Vec<String>,
    pub concrete_variables: Vec<String>,
    pub constants: Vec<String>,
    pub variables: Vec<String>,

    pub constraints: Option<Box<Expr>>,
    pub properties: Option<Box<Expr>>,
    pub invariant: Option<Box<Expr>>,

    pub sets: Vec<Box<Expr>>,
    pub values: Vec<Box<Expr>>,
    pub assertions: Vec<Box<Expr>>,

    pub initialisation: Option<Box<Sub>>,
    pub operations: Vec<Box<Ope>>,
    pub local_operations: Vec<Box<Ope>>,
}

impl ComponentBuilder {
    pub fn new() -> ComponentBuilder {
        ComponentBuilder {
            refines: None,

            imports: vec![],
            includes: vec![],
            extends: vec![],

            sees: vec![],
            promotes: vec![],
            uses: vec![],

            abstract_constants: vec![],
            abstract_variables: vec![],
            concrete_constants: vec![],
            concrete_variables: vec![],
            constants: vec![],
            variables: vec![],

            constraints: None,
            properties : None,
            invariant  : None,

            sets: vec![],
            values: vec![],
            assertions: vec![],

            initialisation: None,
            operations: vec![],
            local_operations: vec![],
        }
    }

    pub fn finalize(self,
                    kind: ComponentKind,
                    name: String,
                    formal_param: Vec<String> ) -> Component {
        Component
        {   kind               : kind
        ,   name               : name
        ,   formal_param       : formal_param
        ,   refines            : self.refines
        ,   imports            : self.imports
        ,   includes           : self.includes
        ,   extends            : self.extends
        ,   sees               : self.sees
        ,   promotes           : self.promotes
        ,   uses               : self.uses
        ,   abstract_constants : self.abstract_constants
        ,   abstract_variables : self.abstract_variables
        ,   concrete_constants : self.concrete_constants
        ,   concrete_variables : self.concrete_variables
        ,   constants          : self.constants
        ,   variables          : self.variables
        ,   constraints        : self.constraints
        ,   properties         : self.properties
        ,   invariant          : self.invariant
        ,   sets               : self.sets
        ,   values             : self.values
        ,   assertions         : self.assertions
        ,   initialisation     : self.initialisation
        ,   operations         : self.operations
        ,   local_operations   : self.local_operations
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::mem;
use std::os::unix::io::{RawFd, AsRawFd};
use std::io::{Read, Write, Error, ErrorKind};

use frame;

use super::{Blocking, NonBlocking};

const BUF_SIZE: usize = 1024;

pub struct Plain<T: Read + Write> {
    inner: T,
    rx_buf: Vec<u8>,
    tx_buf: Vec<u8>
}

impl<T: Read + Write> Plain<T> {
    pub fn new(stream: T) -> Plain<T> {
        Plain {
            inner: stream,
            rx_buf: Vec::<u8>::with_capacity(BUF_SIZE),
            tx_buf: Vec::<u8>::with_capacity(BUF_SIZE)
        }
    }
}

impl<T: Read + Write> Blocking for Plain<T> {
    fn b_recv(&mut self) -> Result<Vec<u8>, Error> {
        loop {
            let mut buf = [0u8; BUF_SIZE];
            let read_result = self.inner.read(&mut buf);
            if read_result.is_err() {
                let err = read_result.unwrap_err();
                return Err(err);
            }

            let num_read = read_result.unwrap();
            self.rx_buf.extend_from_slice(&buf[0..num_read]);

            match frame::from_raw_parts(&mut self.rx_buf) {
                Some(frame) => {
                    return Ok(frame);
                }
                None => { }
            };
        }
    }

    fn b_send(&mut self, buf: &[u8]) -> Result<(), Error> {
        let frame = frame::new(buf);
        let write_result = self.inner.write(&frame[..]);
        if write_result.is_err() {
            let err = write_result.unwrap_err();
            return Err(err);
        }

        Ok(())
    }
}

impl<T: Read + Write> NonBlocking for Plain<T> {
    fn nb_recv(&mut self) -> Result<Vec<Vec<u8>>, Error> {
        loop {
            let mut buf = [0u8; BUF_SIZE];
            let read_result = self.inner.read(&mut buf);
            if read_result.is_err() {
                let err = read_result.unwrap_err();
                if err.kind() == ErrorKind::WouldBlock {
                    break;
                }
                return Err(err);
            }

            let num_read = read_result.unwrap();
            self.rx_buf.extend_from_slice(&buf[0..num_read]);
        }

        let mut ret_buf = Vec::<Vec<u8>>::with_capacity(5);
        while let Some(frame) = frame::from_raw_parts(&mut self.rx_buf) {
            ret_buf.push(frame);
        }

        if ret_buf.len() > 0 {
            return Ok(ret_buf);
        }

        Err(Error::new(ErrorKind::WouldBlock, "WouldBlock"))
    }

    fn nb_send(&mut self, buf: &[u8]) -> Result<(), Error> {
        let frame = frame::new(buf);
        self.tx_buf.extend_from_slice(&frame[..]);

        let write_result = self.inner.write(&self.tx_buf[..]);
        if write_result.is_err() {
            let err = write_result.unwrap_err();
            return Err(err);
        }

        let num_written = write_result.unwrap();
        if num_written == 0 {
            return Err(Error::new(ErrorKind::Other, "Write returned zero"));
        }

        if num_written < self.tx_buf.len() {
            let tx_buf_len = self.tx_buf.len();
            let remaining_len = self.tx_buf.len() - num_written;

            let mut buf = Vec::<u8>::with_capacity(remaining_len);
            buf.extend_from_slice(&self.tx_buf[num_written..tx_buf_len]);

            mem::swap(&mut buf, &mut self.tx_buf);

            return Err(Error::new(ErrorKind::WouldBlock, "WouldBlock"));
        }

        Ok(())
    }
}

impl<T: Read + Write + AsRawFd> AsRawFd for Plain<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.inner.as_raw_fd()
    }
}
<commit_msg>Updates to stuff<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::mem;
use std::os::unix::io::{RawFd, AsRawFd};
use std::io::{Read, Write, Error, ErrorKind};

use frame;

use super::{Blocking, NonBlocking};

const BUF_SIZE: usize = 1024;

#[derive(Clone)]
pub struct Plain<T: Read + Write> {
    inner: T,
    rx_buf: Vec<u8>,
    tx_buf: Vec<u8>
}

impl<T: Read + Write> Plain<T> {
    pub fn new(stream: T) -> Plain<T> {
        Plain {
            inner: stream,
            rx_buf: Vec::<u8>::with_capacity(BUF_SIZE),
            tx_buf: Vec::<u8>::with_capacity(BUF_SIZE)
        }
    }
}

impl<T: Read + Write> Blocking for Plain<T> {
    fn b_recv(&mut self) -> Result<Vec<u8>, Error> {
        loop {
            let mut buf = [0u8; BUF_SIZE];
            let read_result = self.inner.read(&mut buf);
            if read_result.is_err() {
                let err = read_result.unwrap_err();
                return Err(err);
            }

            let num_read = read_result.unwrap();
            self.rx_buf.extend_from_slice(&buf[0..num_read]);

            match frame::from_raw_parts(&mut self.rx_buf) {
                Some(frame) => {
                    return Ok(frame);
                }
                None => { }
            };
        }
    }

    fn b_send(&mut self, buf: &[u8]) -> Result<(), Error> {
        let frame = frame::new(buf);
        let write_result = self.inner.write(&frame[..]);
        if write_result.is_err() {
            let err = write_result.unwrap_err();
            return Err(err);
        }

        Ok(())
    }
}

impl<T: Read + Write> NonBlocking for Plain<T> {
    fn nb_recv(&mut self) -> Result<Vec<Vec<u8>>, Error> {
        loop {
            let mut buf = [0u8; BUF_SIZE];
            let read_result = self.inner.read(&mut buf);
            if read_result.is_err() {
                let err = read_result.unwrap_err();
                if err.kind() == ErrorKind::WouldBlock {
                    break;
                }
                return Err(err);
            }

            let num_read = read_result.unwrap();
            self.rx_buf.extend_from_slice(&buf[0..num_read]);
        }

        let mut ret_buf = Vec::<Vec<u8>>::with_capacity(5);
        while let Some(frame) = frame::from_raw_parts(&mut self.rx_buf) {
            ret_buf.push(frame);
        }

        if ret_buf.len() > 0 {
            return Ok(ret_buf);
        }

        Err(Error::new(ErrorKind::WouldBlock, "WouldBlock"))
    }

    fn nb_send(&mut self, buf: &[u8]) -> Result<(), Error> {
        let frame = frame::new(buf);
        self.tx_buf.extend_from_slice(&frame[..]);

        let write_result = self.inner.write(&self.tx_buf[..]);
        if write_result.is_err() {
            let err = write_result.unwrap_err();
            return Err(err);
        }

        let num_written = write_result.unwrap();
        if num_written == 0 {
            return Err(Error::new(ErrorKind::Other, "Write returned zero"));
        }

        if num_written < self.tx_buf.len() {
            let tx_buf_len = self.tx_buf.len();
            let remaining_len = self.tx_buf.len() - num_written;

            let mut buf = Vec::<u8>::with_capacity(remaining_len);
            buf.extend_from_slice(&self.tx_buf[num_written..tx_buf_len]);

            mem::swap(&mut buf, &mut self.tx_buf);

            return Err(Error::new(ErrorKind::WouldBlock, "WouldBlock"));
        }

        Ok(())
    }
}

impl<T: Read + Write + AsRawFd> AsRawFd for Plain<T> {
    fn as_raw_fd(&self) -> RawFd {
        self.inner.as_raw_fd()
    }
}
<|endoftext|>


<commit_before>//! Basic point on a coordinate plane

use std::ops::{Add, Sub};

/// Basic point on a coordinate plane
///
/// The point contains three coordinates (QRS) to describe its position in
/// two dimensions and a fourth (T) to describe its third dimension.
/// The first three are "cube" coordinates as they describe a 2D hexagon as
/// if it were a cube in 3D space, making several algorithms easier to use.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct Point {

  /// This can also be considered axis X on a cube.
  pub q: i32,

  /// This can also be considered axis Z on a cube.
  pub r: i32,

  /// This can also be considered axis Y on a cube.
  pub s: i32,

  /// This is the height of the point in 3D space.
  pub t: i32,
}

impl Point {

  /// Factory function for making new points
  ///
  /// # Example
  ///
  /// ```
  /// # use hex_math::point::Point;
  /// #
  /// let spot: Point = Point::new(1, 2, 5);
  /// ```
  pub fn new(q: i32, r: i32, t: i32) -> Point {
    Point {q: q, r: r, s: -q - r, t: t}
  }

  /// Convenience function for making two-dimensional points
  ///
  /// # Example
  ///
  /// ```
  /// # use hex_math::point::Point;
  /// #
  /// let spot: Point = Point::new_2d(1, 2);
  /// ```
  pub fn new_2d(q: i32, r: i32) -> Point {
    Point::new(q, r, 0)
  }

  /// Convenient getter for the point's axial coordinate values
  ///
  /// # Example
  ///
  /// ```
  /// # use hex_math::point::Point;
  /// #
  /// let spot: Point = Point::new(1, 2, 5);
  ///
  /// assert_eq!((1, 2, 5), spot.values());
  /// ```
  ///
  /// Those using two-dimensional points may simply ignore a value.
  ///
  /// ```
  /// # use hex_math::point::Point;
  /// #
  /// let spot: Point = Point::new_2d(1, 2);
  /// let (q, r, _) = spot.values();
  ///
  /// assert_eq!((1, 2), (q, r));
  /// ```
  pub fn values(&self) -> (i32, i32, i32) {
    (self.q, self.r, self.t)
  }

  /// Convenient getter for the point's cube coordinate values
  ///
  /// # Exampes
  ///
  /// ```
  /// # use hex_math::point::Point;
  /// #
  /// let spot: Point = Point::new(1, 2, 5);
  ///
  /// assert_eq!((1, 2, -3, 5), spot.values_cube());
  /// ```
  pub fn values_cube(&self) -> (i32, i32, i32, i32) {
    (self.q, self.r, self.s, self.t)
  }

}

/// Add one point to another
///
/// # Example
///
/// ```
/// # use hex_math::point::Point;
/// #
/// let spot: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let result: Point = spot + other;
///
/// assert_eq!((4, 6, 15), result.values());
/// ```
impl Add for Point {

  type Output = Point;

  fn add(self, rhs: Point) -> Point {
    Point::new(self.q + rhs.q, self.r + rhs.r, self.t + rhs.t)
  }

}

/// Subtract one point from another
///
/// # Example
///
/// ```
/// # use hex_math::point::Point;
/// #
/// let spot: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let result: Point = spot - other;
///
/// assert_eq!((-2, -2, -5), result.values());
/// ```
impl Sub for Point {

  type Output = Point;

  fn sub(self, rhs: Point) -> Point {
    Point::new(self.q - rhs.q, self.r - rhs.r, self.t - rhs.t)
  }

}

<commit_msg>Uncommented use statements in examples.<commit_after>//! Basic point on a coordinate plane

use std::ops::{Add, Sub};

/// Basic point on a coordinate plane
///
/// The point contains three coordinates (QRS) to describe its position in
/// two dimensions and a fourth (T) to describe its third dimension.
/// The first three are "cube" coordinates as they describe a 2D hexagon as
/// if it were a cube in 3D space, making several algorithms easier to use.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct Point {

  /// This can also be considered axis X on a cube.
  pub q: i32,

  /// This can also be considered axis Z on a cube.
  pub r: i32,

  /// This can also be considered axis Y on a cube.
  pub s: i32,

  /// This is the height of the point in 3D space.
  pub t: i32,
}

impl Point {

  /// Factory function for making new points
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::point::Point;
  ///
  /// let spot: Point = Point::new(1, 2, 5);
  /// ```
  pub fn new(q: i32, r: i32, t: i32) -> Point {
    Point {q: q, r: r, s: -q - r, t: t}
  }

  /// Convenience function for making two-dimensional points
  ///
  /// Example
  ///
  /// ```
  /// use hex_math::point::Point;
  ///
  /// let spot: Point = Point::new_2d(1, 2);
  /// ```
  pub fn new_2d(q: i32, r: i32) -> Point {
    Point::new(q, r, 0)
  }

  /// Convenient getter for the point's axial coordinate values
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::point::Point;
  ///
  /// let spot: Point = Point::new(1, 2, 5);
  ///
  /// assert_eq!((1, 2, 5), spot.values());
  /// ```
  ///
  /// Those using two-dimensional points may simply ignore a value.
  ///
  /// ```
  /// use hex_math::point::Point;
  ///
  /// let spot: Point = Point::new_2d(1, 2);
  /// let (q, r, _) = spot.values();
  ///
  /// assert_eq!((1, 2), (q, r));
  /// ```
  pub fn values(&self) -> (i32, i32, i32) {
    (self.q, self.r, self.t)
  }

  /// Convenient getter for the point's cube coordinate values
  ///
  /// # Exampes
  ///
  /// ```
  /// use hex_math::point::Point;
  ///
  /// let spot: Point = Point::new(1, 2, 5);
  ///
  /// assert_eq!((1, 2, -3, 5), spot.values_cube());
  /// ```
  pub fn values_cube(&self) -> (i32, i32, i32, i32) {
    (self.q, self.r, self.s, self.t)
  }

}

/// Add one point to another
///
/// # Example
///
/// ```
/// use hex_math::point::Point;
///
/// let spot: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let result: Point = spot + other;
///
/// assert_eq!((4, 6, 15), result.values());
/// ```
impl Add for Point {

  type Output = Point;

  fn add(self, rhs: Point) -> Point {
    Point::new(self.q + rhs.q, self.r + rhs.r, self.t + rhs.t)
  }

}

/// Subtract one point from another
///
/// # Example
///
/// ```
/// use hex_math::point::Point;
///
/// let spot: Point = Point::new(1, 2, 5);
/// let other: Point = Point::new(3, 4, 10);
/// let result: Point = spot - other;
///
/// assert_eq!((-2, -2, -5), result.values());
/// ```
impl Sub for Point {

  type Output = Point;

  fn sub(self, rhs: Point) -> Point {
    Point::new(self.q - rhs.q, self.r - rhs.r, self.t - rhs.t)
  }

}

<|endoftext|>


<commit_before>use rustc_serialize::json::Json;

use super::Document;

#[derive(Debug, PartialEq)]
pub enum FilterParseError {
    ExpectedObject,
    ExpectedString,
    ExpectedArray,
    UnknownFilterType(String),
    NoFilter,
}

#[derive(Debug, PartialEq)]
pub enum Filter {
    Term{field: String, value: Json},
    Terms{field: String, values: Vec<Json>},
    Prefix{field: String, value: String},
    Missing{field: String},
    And{children: Vec<Filter>},
    Or{children: Vec<Filter>},
    Not{child: Box<Filter>},
}

#[derive(Debug, PartialEq)]
pub enum QueryParseError {
    ExpectedObject,
    ExpectedString,
    ExpectedArray,
    UnknownQueryType(String),
    NoQuery,
    FilteredNoFilter,
    FilteredNoQuery,
    FilterParseError(FilterParseError),
    MissingQueryString,
    MultiMatchMissingFields,
    InvalidQueryOperator,
}

#[derive(Debug, PartialEq)]
pub enum QueryOperator {
    Or,
    And,
}

impl Default for QueryOperator {
    fn default() -> QueryOperator {
        QueryOperator::Or
    }
}

#[derive(Debug, PartialEq)]
pub enum Query {
    MatchAll,
    Match{field: String, query: String, operator: QueryOperator},
    MultiMatch{fields: Vec<String>, query: String},
    Filtered{query: Box<Query>, filter: Box<Filter>},
}

impl Filter {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            Filter::Term{ref field, ref value} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    return field_value == value;
                }

                false
            }
            Filter::Terms{ref field, ref values} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    for value in values.iter() {
                        if field_value == value {
                            return true;
                        }
                    }
                }

                false
            }
            Filter::Prefix{ref field, ref value} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    if let Json::String(ref field_value) = *field_value {
                        return field_value.starts_with(value);
                    }
                }

                false
            }
            Filter::Missing{ref field} => {
                let obj = doc.data.as_object().unwrap();

                match obj.get(field) {
                    Some(&Json::Null) => true,
                    None => true,
                    _ => false,
                }
            }
            Filter::And{ref children} => {
                for child in children.iter() {
                    if !child.matches(doc) {
                        return false;
                    }
                }

                true
            }
            Filter::Or{ref children} => {
                for child in children.iter() {
                    if child.matches(doc) {
                        return true;
                    }
                }

                false
            }
            Filter::Not{ref child} => !child.matches(doc),
        }
    }
}

pub fn parse_filter(json: &Json) -> Result<Filter, FilterParseError> {
    let filter_json = try!(json.as_object().ok_or(FilterParseError::ExpectedObject));
    let first_key = try!(filter_json.keys().nth(0).ok_or(FilterParseError::NoFilter));

    if first_key == "term" {
        let filter_json = filter_json.get("term").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Term{
            field: first_key.clone(),
            value: filter_json.get(first_key).unwrap().clone()
        })
    } else if first_key == "terms" {
        let filter_json = filter_json.get("terms").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Terms{
            field: first_key.clone(),
            values: filter_json.get(first_key).unwrap().as_array().unwrap().clone()
        })
    } else if first_key == "prefix" {
        let filter_json = filter_json.get("prefix").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();
        let value = filter_json.get(first_key).unwrap().as_string().unwrap();

        Ok(Filter::Prefix{
            field: first_key.clone(),
            value: value.to_owned()
        })
    } else if first_key == "missing" {
        let filter_json = filter_json.get("missing").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Missing{
            field: first_key.clone()
        })
    } else if first_key == "and" {
        Ok(Filter::And{
            children: filter_json.get("and").unwrap()
                       .as_array().unwrap()
                       .iter().map(|f| parse_filter(f).unwrap())
                       .collect::<Vec<_>>()
        })
    } else if first_key == "or" {
        Ok(Filter::Or{
            children: filter_json.get("or").unwrap()
                       .as_array().unwrap()
                       .iter().map(|f| parse_filter(f).unwrap())
                       .collect::<Vec<_>>()
        })
    } else if first_key == "not" {
        Ok(Filter::Not{
            child: Box::new(parse_filter(filter_json.get("not").unwrap()).unwrap())
        })
    } else {
        Err(FilterParseError::UnknownFilterType(first_key.clone()))
    }
}

impl Query {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            Query::MatchAll => true,
            Query::Match{ref field, ref query, ref operator} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    let mut field_value = field_value.as_string().unwrap().to_lowercase();
                    let mut query = query.to_lowercase();

                    return field_value.contains(&query);
                }

                false
            }
            Query::MultiMatch{ref fields, ref query} => {
                let obj = doc.data.as_object().unwrap();

                for field in fields.iter() {
                    if let Some(field_value) = obj.get(field) {
                        let mut field_value = field_value.as_string().unwrap().to_lowercase();
                        let mut query = query.to_lowercase();

                        if field_value.contains(&query) {
                            return true;
                        }
                    }
                }

                false
            }
            Query::Filtered{ref query, ref filter} => {
                if filter.matches(doc) {
                    query.matches(doc)
                } else {
                    false
                }
            }
        }
    }
}

pub fn parse_query_operator(json: Option<&Json>) -> Result<QueryOperator, QueryParseError> {
    match json {
        Some(json) => {
            match *json {
                Json::String(ref value) => {
                    match value.as_ref() {
                        "or" => Ok(QueryOperator::Or),
                        "and" => Ok(QueryOperator::And),
                        _ => return Err(QueryParseError::InvalidQueryOperator),
                    }
                }
                _ => return Err(QueryParseError::InvalidQueryOperator),
            }
        }
        None => Ok(QueryOperator::default())
    }
}

pub fn parse_match_query(json: &Json) -> Result<Query, QueryParseError> {
    let json_object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));
    let first_key = try!(json_object.keys().nth(0).ok_or(QueryParseError::NoQuery));

    match json_object.get(first_key).unwrap() {
        &Json::String(ref query) => {
            Ok(Query::Match {
                field: first_key.clone(),
                query: query.to_owned(),
                operator: QueryOperator::default(),
            })
        }
        &Json::Object(ref object) => {
            Ok(Query::Match {
                field: first_key.clone(),
                query: object.get("query").unwrap().as_string().unwrap().to_owned(),
                operator: try!(parse_query_operator(object.get("operator"))),
            })
        }
        // TODO: We actually expect string or object
        _ => Err(QueryParseError::ExpectedString)
    }
}

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

    // Convert "fields" into a Vec<String>
    let fields_json = try!(json_object.get("fields").ok_or(QueryParseError::MultiMatchMissingFields));
    let fields = try!(fields_json.as_array().ok_or(QueryParseError::ExpectedArray))
                      .iter().map(|s| s.as_string().unwrap().to_owned())
                      .collect::<Vec<_>>();

    let query_json = try!(json_object.get("query").ok_or(QueryParseError::MissingQueryString));
    let query = try!(query_json.as_string().ok_or(QueryParseError::ExpectedString)).to_owned();

    Ok(Query::MultiMatch {
        fields: fields,
        query: query,
    })
}

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

    let filter_json = try!(json_object.get("filter").ok_or(QueryParseError::FilteredNoFilter));
    let filter = match parse_filter(filter_json) {
        Ok(filter) => filter,
        Err(err) => return Err(QueryParseError::FilterParseError(err)),
    };

    let query_json = try!(json_object.get("query").ok_or(QueryParseError::FilteredNoQuery));
    let query = try!(parse_query(query_json));

    Ok(Query::Filtered {
        filter: Box::new(filter),
        query: Box::new(query),
    })
}

pub fn parse_query(json: &Json) -> Result<Query, QueryParseError> {
    let json_object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));
    let first_key = try!(json_object.keys().nth(0).ok_or(QueryParseError::NoQuery));

    if first_key == "match_all" {
        Ok(Query::MatchAll)
    } else if first_key == "match" {
        let inner_query = json_object.get("match").unwrap();
        Ok(try!(parse_match_query(inner_query)))
    } else if first_key == "multi_match" {
        let inner_query = json_object.get("multi_match").unwrap();
        Ok(try!(parse_multi_match_query(inner_query)))
    } else if first_key == "filtered" {
        let inner_query = json_object.get("filtered").unwrap();
        Ok(try!(parse_filtered_query(inner_query)))
    } else {
        Err(QueryParseError::UnknownQueryType(first_key.clone()))
    }
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;
    use super::{Query, Filter, QueryParseError, QueryOperator, parse_query};

    #[test]
    fn test_match_all_query() {
        let query = parse_query(&Json::from_str("
            {
                \"match_all\": {}
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchAll))
    }

    #[test]
    fn test_match_query() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {
                    \"title\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Match{
            field: "title".to_owned(),
            query: "Hello world!".to_owned(),
            operator: QueryOperator::Or,
        }))
    }

    #[test]
    fn test_match_query_without_field() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {}
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::NoQuery))
    }

    #[test]
    fn test_multi_match_query() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"fields\": [\"title\", \"body\"],
                    \"query\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::MultiMatch{
            fields: vec!["title".to_owned(), "body".to_owned()],
            query: "Hello world!".to_owned(),
        }))
    }

    #[test]
    fn test_multi_match_query_without_fields() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"query\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::MultiMatchMissingFields))
    }

    #[test]
    fn test_multi_match_query_without_query() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"fields\": [\"title\", \"body\"]
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::MissingQueryString))
    }

    #[test]
    fn test_filtered_query() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"query\": {
                        \"match\": {
                            \"title\": \"Hello world!\"
                        }
                    },
                    \"filter\": {
                        \"term\": {
                            \"date\": \"2016-01-25\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Filtered{
            query: Box::new(Query::Match{
                field: "title".to_owned(),
                query: "Hello world!".to_owned(),
                operator: QueryOperator::Or,
            }),
            filter: Box::new(Filter::Term{
                field: "date".to_owned(),
                value: Json::from_str("\"2016-01-25\"").unwrap(),
            })
        }))
    }

    #[test]
    fn test_filtered_query_without_query() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"filter\": {
                        \"term\": {
                            \"date\": \"2016-01-25\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::FilteredNoQuery))
    }

    #[test]
    fn test_filtered_query_without_filter() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"query\": {
                        \"match\": {
                            \"title\": \"Hello world!\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::FilteredNoFilter))
    }
}
<commit_msg>Added a few more tests<commit_after>use rustc_serialize::json::Json;

use super::Document;

#[derive(Debug, PartialEq)]
pub enum FilterParseError {
    ExpectedObject,
    ExpectedString,
    ExpectedArray,
    UnknownFilterType(String),
    NoFilter,
}

#[derive(Debug, PartialEq)]
pub enum Filter {
    Term{field: String, value: Json},
    Terms{field: String, values: Vec<Json>},
    Prefix{field: String, value: String},
    Missing{field: String},
    And{children: Vec<Filter>},
    Or{children: Vec<Filter>},
    Not{child: Box<Filter>},
}

#[derive(Debug, PartialEq)]
pub enum QueryParseError {
    ExpectedObject,
    ExpectedString,
    ExpectedArray,
    UnknownQueryType(String),
    NoQuery,
    FilteredNoFilter,
    FilteredNoQuery,
    FilterParseError(FilterParseError),
    MissingQueryString,
    MultiMatchMissingFields,
    InvalidQueryOperator,
}

#[derive(Debug, PartialEq)]
pub enum QueryOperator {
    Or,
    And,
}

impl Default for QueryOperator {
    fn default() -> QueryOperator {
        QueryOperator::Or
    }
}

#[derive(Debug, PartialEq)]
pub enum Query {
    MatchAll,
    Match{field: String, query: String, operator: QueryOperator},
    MultiMatch{fields: Vec<String>, query: String},
    Filtered{query: Box<Query>, filter: Box<Filter>},
}

impl Filter {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            Filter::Term{ref field, ref value} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    return field_value == value;
                }

                false
            }
            Filter::Terms{ref field, ref values} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    for value in values.iter() {
                        if field_value == value {
                            return true;
                        }
                    }
                }

                false
            }
            Filter::Prefix{ref field, ref value} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    if let Json::String(ref field_value) = *field_value {
                        return field_value.starts_with(value);
                    }
                }

                false
            }
            Filter::Missing{ref field} => {
                let obj = doc.data.as_object().unwrap();

                match obj.get(field) {
                    Some(&Json::Null) => true,
                    None => true,
                    _ => false,
                }
            }
            Filter::And{ref children} => {
                for child in children.iter() {
                    if !child.matches(doc) {
                        return false;
                    }
                }

                true
            }
            Filter::Or{ref children} => {
                for child in children.iter() {
                    if child.matches(doc) {
                        return true;
                    }
                }

                false
            }
            Filter::Not{ref child} => !child.matches(doc),
        }
    }
}

pub fn parse_filter(json: &Json) -> Result<Filter, FilterParseError> {
    let filter_json = try!(json.as_object().ok_or(FilterParseError::ExpectedObject));
    let first_key = try!(filter_json.keys().nth(0).ok_or(FilterParseError::NoFilter));

    if first_key == "term" {
        let filter_json = filter_json.get("term").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Term{
            field: first_key.clone(),
            value: filter_json.get(first_key).unwrap().clone()
        })
    } else if first_key == "terms" {
        let filter_json = filter_json.get("terms").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Terms{
            field: first_key.clone(),
            values: filter_json.get(first_key).unwrap().as_array().unwrap().clone()
        })
    } else if first_key == "prefix" {
        let filter_json = filter_json.get("prefix").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();
        let value = filter_json.get(first_key).unwrap().as_string().unwrap();

        Ok(Filter::Prefix{
            field: first_key.clone(),
            value: value.to_owned()
        })
    } else if first_key == "missing" {
        let filter_json = filter_json.get("missing").unwrap().as_object().unwrap();
        let first_key = filter_json.keys().nth(0).unwrap();

        Ok(Filter::Missing{
            field: first_key.clone()
        })
    } else if first_key == "and" {
        Ok(Filter::And{
            children: filter_json.get("and").unwrap()
                       .as_array().unwrap()
                       .iter().map(|f| parse_filter(f).unwrap())
                       .collect::<Vec<_>>()
        })
    } else if first_key == "or" {
        Ok(Filter::Or{
            children: filter_json.get("or").unwrap()
                       .as_array().unwrap()
                       .iter().map(|f| parse_filter(f).unwrap())
                       .collect::<Vec<_>>()
        })
    } else if first_key == "not" {
        Ok(Filter::Not{
            child: Box::new(parse_filter(filter_json.get("not").unwrap()).unwrap())
        })
    } else {
        Err(FilterParseError::UnknownFilterType(first_key.clone()))
    }
}

impl Query {
    pub fn matches(&self, doc: &Document) -> bool {
        match *self {
            Query::MatchAll => true,
            Query::Match{ref field, ref query, ref operator} => {
                let obj = doc.data.as_object().unwrap();

                if let Some(field_value) = obj.get(field) {
                    let mut field_value = field_value.as_string().unwrap().to_lowercase();
                    let mut query = query.to_lowercase();

                    return field_value.contains(&query);
                }

                false
            }
            Query::MultiMatch{ref fields, ref query} => {
                let obj = doc.data.as_object().unwrap();

                for field in fields.iter() {
                    if let Some(field_value) = obj.get(field) {
                        let mut field_value = field_value.as_string().unwrap().to_lowercase();
                        let mut query = query.to_lowercase();

                        if field_value.contains(&query) {
                            return true;
                        }
                    }
                }

                false
            }
            Query::Filtered{ref query, ref filter} => {
                if filter.matches(doc) {
                    query.matches(doc)
                } else {
                    false
                }
            }
        }
    }
}

pub fn parse_query_operator(json: Option<&Json>) -> Result<QueryOperator, QueryParseError> {
    match json {
        Some(json) => {
            match *json {
                Json::String(ref value) => {
                    match value.as_ref() {
                        "or" => Ok(QueryOperator::Or),
                        "and" => Ok(QueryOperator::And),
                        _ => return Err(QueryParseError::InvalidQueryOperator),
                    }
                }
                _ => return Err(QueryParseError::InvalidQueryOperator),
            }
        }
        None => Ok(QueryOperator::default())
    }
}

pub fn parse_match_query(json: &Json) -> Result<Query, QueryParseError> {
    let json_object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));
    let first_key = try!(json_object.keys().nth(0).ok_or(QueryParseError::NoQuery));

    match json_object.get(first_key).unwrap() {
        &Json::String(ref query) => {
            Ok(Query::Match {
                field: first_key.clone(),
                query: query.to_owned(),
                operator: QueryOperator::default(),
            })
        }
        &Json::Object(ref object) => {
            Ok(Query::Match {
                field: first_key.clone(),
                query: object.get("query").unwrap().as_string().unwrap().to_owned(),
                operator: try!(parse_query_operator(object.get("operator"))),
            })
        }
        // TODO: We actually expect string or object
        _ => Err(QueryParseError::ExpectedString)
    }
}

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

    // Convert "fields" into a Vec<String>
    let fields_json = try!(json_object.get("fields").ok_or(QueryParseError::MultiMatchMissingFields));
    let fields = try!(fields_json.as_array().ok_or(QueryParseError::ExpectedArray))
                      .iter().map(|s| s.as_string().unwrap().to_owned())
                      .collect::<Vec<_>>();

    let query_json = try!(json_object.get("query").ok_or(QueryParseError::MissingQueryString));
    let query = try!(query_json.as_string().ok_or(QueryParseError::ExpectedString)).to_owned();

    Ok(Query::MultiMatch {
        fields: fields,
        query: query,
    })
}

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

    let filter_json = try!(json_object.get("filter").ok_or(QueryParseError::FilteredNoFilter));
    let filter = match parse_filter(filter_json) {
        Ok(filter) => filter,
        Err(err) => return Err(QueryParseError::FilterParseError(err)),
    };

    let query_json = try!(json_object.get("query").ok_or(QueryParseError::FilteredNoQuery));
    let query = try!(parse_query(query_json));

    Ok(Query::Filtered {
        filter: Box::new(filter),
        query: Box::new(query),
    })
}

pub fn parse_query(json: &Json) -> Result<Query, QueryParseError> {
    let json_object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));
    let first_key = try!(json_object.keys().nth(0).ok_or(QueryParseError::NoQuery));

    if first_key == "match_all" {
        Ok(Query::MatchAll)
    } else if first_key == "match" {
        let inner_query = json_object.get("match").unwrap();
        Ok(try!(parse_match_query(inner_query)))
    } else if first_key == "multi_match" {
        let inner_query = json_object.get("multi_match").unwrap();
        Ok(try!(parse_multi_match_query(inner_query)))
    } else if first_key == "filtered" {
        let inner_query = json_object.get("filtered").unwrap();
        Ok(try!(parse_filtered_query(inner_query)))
    } else {
        Err(QueryParseError::UnknownQueryType(first_key.clone()))
    }
}

#[cfg(test)]
mod tests {
    use rustc_serialize::json::Json;
    use super::{Query, Filter, QueryParseError, QueryOperator, parse_query};

    #[test]
    fn test_match_all_query() {
        let query = parse_query(&Json::from_str("
            {
                \"match_all\": {}
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::MatchAll))
    }

    #[test]
    fn test_match_query() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {
                    \"title\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Match{
            field: "title".to_owned(),
            query: "Hello world!".to_owned(),
            operator: QueryOperator::Or,
        }))
    }

    #[test]
    fn test_match_dict_config() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {
                    \"title\": {
                        \"query\": \"Hello world!\"
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Match{
            field: "title".to_owned(),
            query: "Hello world!".to_owned(),
            operator: QueryOperator::Or,
        }))
    }

    #[test]
    fn test_match_and_operator() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {
                    \"title\": {
                        \"query\": \"Hello world!\",
                        \"operator\": \"and\"
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Match{
            field: "title".to_owned(),
            query: "Hello world!".to_owned(),
            operator: QueryOperator::And,
        }))
    }

    #[test]
    fn test_match_invalid_operator() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {
                    \"title\": {
                        \"query\": \"Hello world!\",
                        \"operator\": \"invalid\"
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::InvalidQueryOperator))
    }

    #[test]
    fn test_match_query_without_field() {
        let query = parse_query(&Json::from_str("
            {
                \"match\": {}
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::NoQuery))
    }

    #[test]
    fn test_multi_match_query() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"fields\": [\"title\", \"body\"],
                    \"query\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::MultiMatch{
            fields: vec!["title".to_owned(), "body".to_owned()],
            query: "Hello world!".to_owned(),
        }))
    }

    #[test]
    fn test_multi_match_query_without_fields() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"query\": \"Hello world!\"
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::MultiMatchMissingFields))
    }

    #[test]
    fn test_multi_match_query_without_query() {
        let query = parse_query(&Json::from_str("
            {
                \"multi_match\": {
                    \"fields\": [\"title\", \"body\"]
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::MissingQueryString))
    }

    #[test]
    fn test_filtered_query() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"query\": {
                        \"match\": {
                            \"title\": \"Hello world!\"
                        }
                    },
                    \"filter\": {
                        \"term\": {
                            \"date\": \"2016-01-25\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Ok(Query::Filtered{
            query: Box::new(Query::Match{
                field: "title".to_owned(),
                query: "Hello world!".to_owned(),
                operator: QueryOperator::Or,
            }),
            filter: Box::new(Filter::Term{
                field: "date".to_owned(),
                value: Json::from_str("\"2016-01-25\"").unwrap(),
            })
        }))
    }

    #[test]
    fn test_filtered_query_without_query() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"filter\": {
                        \"term\": {
                            \"date\": \"2016-01-25\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::FilteredNoQuery))
    }

    #[test]
    fn test_filtered_query_without_filter() {
        let query = parse_query(&Json::from_str("
            {
                \"filtered\": {
                    \"query\": {
                        \"match\": {
                            \"title\": \"Hello world!\"
                        }
                    }
                }
            }
        ").unwrap());

        assert_eq!(query, Err(QueryParseError::FilteredNoFilter))
    }
}
<|endoftext|>