<commit_before>// DOCS

#[macro_use] extern crate quick_error;
#[macro_use] extern crate string_cache;
extern crate mime;
extern crate hyper;
extern crate url;
extern crate kuchiki;
extern crate image;

mod strategies;
mod util;

use image::GenericImage;
use strategies::Strategy;
use std::io::Read;
use util::AsImageFormat;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Hyper(error: hyper::Error) { from() }
        Io(error: std::io::Error) { from() }
        Image(error: image::ImageError) { from() }
        Other(msg: String) {
            description(msg)
        }
    }
}

pub struct IconScraper {
    document_url: url::Url,
    dom: Option<kuchiki::NodeRef>,
}

impl IconScraper {
    pub fn from_url(url: url::Url) -> Self {
        let client = hyper::client::Client::new();
        let mut response = client.get(url.clone()).send().ok();
        IconScraper::from_url_and_stream(url, response.as_mut())
    }

    pub fn from_url_and_stream<R: Read>(url: url::Url, stream: Option<&mut R>) -> Self {
        IconScraper {
            document_url: url,
            dom: stream
                .and_then(|stream| kuchiki::Html::from_stream(stream).ok())
                .map(|x| x.parse())
        }
    }

    pub fn from_url_and_dom(url: url::Url, dom: kuchiki::NodeRef) -> Self {
        IconScraper {
            document_url: url,
            dom: Some(dom)
        }
    }

    /// Search the document for icon metadata, also brute-force some favicon paths.
    ///
    /// **Note:** This operation is fairly costly, it is recommended to cache the results!
    ///
    /// # Panics
    ///
    /// If the document is not fetched yet.
    pub fn fetch_icons(&mut self) -> IconCollection {
        let icons = strategies::LinkRelStrategy.get_guesses(self)
            .into_iter()
            .chain(strategies::DefaultFaviconPathStrategy.get_guesses(self).into_iter())
            .filter_map(|mut icon| if icon.fetch_dimensions().is_ok() { Some(icon) } else { None })
            .collect::<Vec<_>>();

        IconCollection::from_raw(icons)
    }
}

pub struct IconCollection {
    icons: Vec<Icon>
}

impl IconCollection {
    fn from_raw(mut icons: Vec<Icon>) -> Self {
        icons.sort_by(|a, b| {
            (a.width.unwrap() * a.height.unwrap())
                .cmp(&(b.width.unwrap() * b.height.unwrap()))
        });
        IconCollection {
            icons: icons
        }
    }

    /// Return an icon that is at least of the given dimensions
    ///
    /// If there's only one icon available, it will return that icon. If there's no icon available,
    /// None is returned.
    pub fn at_least(self, width: u32, height: u32) -> Option<Icon> {
        if self.icons.len() > 1 {
            self.icons
                .into_iter()
                .skip_while(|icon| icon.width.unwrap() < width || icon.height.unwrap() < height)
                .next()
        } else {
            self.largest()
        }
    }

    /// Return the largest icon
    pub fn largest(mut self) -> Option<Icon> {
        self.icons.pop()
    }

    /// [unstable] Give up ownership of the inner datastructure: A vector of icons, sorted
    /// ascendingly by size
    pub fn into_raw_parts(self) -> Vec<Icon> {
        self.icons
    }
}

pub struct Icon {
    pub url: url::Url,
    pub raw: Option<Vec<u8>>,
    pub mime_type: Option<mime::Mime>,
    pub width: Option<u32>,
    pub height: Option<u32>
}

impl Icon {
    pub fn from_url(url: url::Url) -> Self {
        Icon {
            url: url,
            raw: None,
            mime_type: None,
            width: None,
            height: None
        }
    }

    pub fn fetch(&mut self) -> Result<(), Error> {
        if self.raw.is_some() {
            return Ok(());
        };

        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.url.clone()).send());

        let mut bytes: Vec<u8> = vec![];
        try!(response.read_to_end(&mut bytes));
        if !response.status.is_success() {
            return Err(Error::Other(format!("Bad status code: {:?}", response.status)));
        }

        let mime_type: mime::Mime = match response.headers.get::<hyper::header::ContentType>() {
            Some(x) => x.clone().0,
            None => return Err(Error::Other("No Content-Type found.".to_owned()))
        };
        let image_format = match mime_type.as_image_format() {
            Some(x) => x,
            None => return Err(Error::Other(format!("Invalid image type: {:?}", mime_type)))
        };
        let image = try!(image::load_from_memory_with_format(&bytes, image_format));

        self.width = Some(image.width());
        self.height = Some(image.height());
        self.raw = Some(bytes);
        self.mime_type = Some(mime_type);
        Ok(())
    }

    pub fn fetch_dimensions(&mut self) -> Result<(), Error> {
        match (self.width, self.height) {
            (Some(_), Some(_)) => Ok(()),
            _ => self.fetch()
        }
    }
}
<commit_msg>improve at_least again<commit_after>// DOCS

#[macro_use] extern crate quick_error;
#[macro_use] extern crate string_cache;
extern crate mime;
extern crate hyper;
extern crate url;
extern crate kuchiki;
extern crate image;

mod strategies;
mod util;

use image::GenericImage;
use strategies::Strategy;
use std::io::Read;
use util::AsImageFormat;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Hyper(error: hyper::Error) { from() }
        Io(error: std::io::Error) { from() }
        Image(error: image::ImageError) { from() }
        Other(msg: String) {
            description(msg)
        }
    }
}

pub struct IconScraper {
    document_url: url::Url,
    dom: Option<kuchiki::NodeRef>,
}

impl IconScraper {
    pub fn from_url(url: url::Url) -> Self {
        let client = hyper::client::Client::new();
        let mut response = client.get(url.clone()).send().ok();
        IconScraper::from_url_and_stream(url, response.as_mut())
    }

    pub fn from_url_and_stream<R: Read>(url: url::Url, stream: Option<&mut R>) -> Self {
        IconScraper {
            document_url: url,
            dom: stream
                .and_then(|stream| kuchiki::Html::from_stream(stream).ok())
                .map(|x| x.parse())
        }
    }

    pub fn from_url_and_dom(url: url::Url, dom: kuchiki::NodeRef) -> Self {
        IconScraper {
            document_url: url,
            dom: Some(dom)
        }
    }

    /// Search the document for icon metadata, also brute-force some favicon paths.
    ///
    /// **Note:** This operation is fairly costly, it is recommended to cache the results!
    ///
    /// # Panics
    ///
    /// If the document is not fetched yet.
    pub fn fetch_icons(&mut self) -> IconCollection {
        let icons = strategies::LinkRelStrategy.get_guesses(self)
            .into_iter()
            .chain(strategies::DefaultFaviconPathStrategy.get_guesses(self).into_iter())
            .filter_map(|mut icon| if icon.fetch_dimensions().is_ok() { Some(icon) } else { None })
            .collect::<Vec<_>>();

        IconCollection::from_raw(icons)
    }
}

pub struct IconCollection {
    icons: Vec<Icon>
}

impl IconCollection {
    fn from_raw(mut icons: Vec<Icon>) -> Self {
        icons.sort_by(|a, b| {
            (a.width.unwrap() * a.height.unwrap())
                .cmp(&(b.width.unwrap() * b.height.unwrap()))
        });
        IconCollection {
            icons: icons
        }
    }

    /// Return an icon that is at least of the given dimensions
    ///
    /// If there's only one icon available, it will return that icon. If there's no icon available,
    /// None is returned.
    pub fn at_least(mut self, width: u32, height: u32) -> Option<Icon> {
        let largest = self.icons.pop();
        self.icons
            .into_iter()
            .skip_while(|icon| icon.width.unwrap() < width || icon.height.unwrap() < height)
            .next()
            .or(largest)
    }

    /// Return the largest icon
    pub fn largest(mut self) -> Option<Icon> {
        self.icons.pop()
    }

    /// [unstable] Give up ownership of the inner datastructure: A vector of icons, sorted
    /// ascendingly by size
    pub fn into_raw_parts(self) -> Vec<Icon> {
        self.icons
    }
}

pub struct Icon {
    pub url: url::Url,
    pub raw: Option<Vec<u8>>,
    pub mime_type: Option<mime::Mime>,
    pub width: Option<u32>,
    pub height: Option<u32>
}

impl Icon {
    pub fn from_url(url: url::Url) -> Self {
        Icon {
            url: url,
            raw: None,
            mime_type: None,
            width: None,
            height: None
        }
    }

    pub fn fetch(&mut self) -> Result<(), Error> {
        if self.raw.is_some() {
            return Ok(());
        };

        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.url.clone()).send());

        let mut bytes: Vec<u8> = vec![];
        try!(response.read_to_end(&mut bytes));
        if !response.status.is_success() {
            return Err(Error::Other(format!("Bad status code: {:?}", response.status)));
        }

        let mime_type: mime::Mime = match response.headers.get::<hyper::header::ContentType>() {
            Some(x) => x.clone().0,
            None => return Err(Error::Other("No Content-Type found.".to_owned()))
        };
        let image_format = match mime_type.as_image_format() {
            Some(x) => x,
            None => return Err(Error::Other(format!("Invalid image type: {:?}", mime_type)))
        };
        let image = try!(image::load_from_memory_with_format(&bytes, image_format));

        self.width = Some(image.width());
        self.height = Some(image.height());
        self.raw = Some(bytes);
        self.mime_type = Some(mime_type);
        Ok(())
    }

    pub fn fetch_dimensions(&mut self) -> Result<(), Error> {
        match (self.width, self.height) {
            (Some(_), Some(_)) => Ok(()),
            _ => self.fetch()
        }
    }
}
<|endoftext|>


<commit_before>use ast::{Expr, BinOp, UnOp, Dec};
use lexer::{Lexer, Token};

struct Parser {
  lexer: Lexer,
  current_token: Token,
}

impl Parser {
  pub fn new(text: String) -> Parser {
    let mut lexer = Lexer::new(text);

    let token = lexer.get_next_token();

    Parser {
      lexer: lexer,
      current_token: token,
    }
  }

  fn eat(&mut self, expected: Token) {
    let actual = self.current_token.clone();

    if expected != actual {
      panic!("expected token: {:?} actual: {:?}", expected, actual)
    }

    self.current_token = self.lexer.get_next_token();
    debug!("new current token: {:?}", self.current_token);
  }

  fn ternary(&mut self, e1: Expr, e2: Expr, e3: Expr) -> Expr {
    Expr::Ternary(to_box(e1), to_box(e2), to_box(e3))
  }

  fn binop(&mut self, bop: BinOp, e1: Expr, e2: Expr) -> Expr {
    Expr::Bop(bop, to_box(e1), to_box(e2))
  }

  fn parse_var(&mut self) -> Expr {
    self.eat(Token::VarDecl);
    let var = self.term();
    self.eat(Token::Assign);
    let e2 = self.statement();
    self.eat(Token::Seq);
    let e3 = self.block();

    return Expr::Decl(Dec::DVar, to_box(var), to_box(e2), to_box(e3));
  }

  fn parse_let(&mut self) -> Expr {
    self.eat(Token::Let);
    let var = self.term();
    self.eat(Token::Assign);
    let e2 = self.statement();
    self.eat(Token::Seq);
    let e3 = self.block();

    return Expr::Decl(Dec::DConst, to_box(var), to_box(e2), to_box(e3));
  }

  fn parse_fn_params(&mut self) -> Vec<Expr> {
    let mut params = Vec::new();
    let mut token = self.current_token.clone();

    while token != Token::RParen {
      debug!("getting fn params");
      let term = self.binop_expr();

      params.push(term);

      if self.current_token == Token::Comma {
        self.eat(Token::Comma);
      }

      token = self.current_token.clone();
    }

    params
  }

  fn parse_fn_decl_params(&mut self) -> Vec<Expr> {
    let mut params = Vec::new();
    let mut token = self.current_token.clone();

    while token != Token::RParen {
      debug!("getting fn decl params");
      match token.clone() {
        Token::Var(s) => {
          self.eat(Token::Var(s.clone()));
          params.push(Expr::Var(s));
        },
        Token::Comma => self.eat(Token::Comma),
        _ => panic!()
      }

      token = self.current_token.clone();
    }

    params
  }

  fn parse_fn(&mut self) -> Expr {
    debug!("parsing named fn...");
    self.eat(Token::FnDecl);

    let var = match self.current_token.clone() {
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()));
        Some(Expr::Var(s))
      },
      _ => None,
    };

    self.eat(Token::LParen);
    let params = self.parse_fn_decl_params();
    self.eat(Token::RParen);
    self.eat(Token::LBracket);
    let body = self.statement();
    self.eat(Token::RBracket);

    match var {
      Some(v) => {
        self.eat(Token::Seq);
        let e3 = self.statement();

        let func = Expr::Func(Some(to_box(v.clone())), to_box(body.clone()), params);

        Expr::Decl(Dec::DConst, to_box(v), to_box(func), to_box(e3))
      },
      None => {
        Expr::Func(None, to_box(body.clone()), params)
      }
    }
  }

  fn parse_if(&mut self) -> Expr {
    self.eat(Token::If);
    let e1 = self.binop_expr();
    let e2 = self.statement();
    let e3 = self.statement();
    return self.ternary(e1, e2, e3);
  }

  fn factor(&mut self) -> Expr {
    match self.current_token.clone() {
      Token::Int(n) => {
        self.eat(Token::Int(n.clone()));
        return Expr::Int(n);
      },
      Token::Bool(b) => {
        self.eat(Token::Bool(b.clone()));
        return Expr::Bool(b);
      },
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()));

        // fn call rule
        if self.current_token == Token::LParen {
          self.eat(Token::LParen);
          let params = self.parse_fn_params();
          self.eat(Token::RParen);

          return Expr::FnCall(to_box(Expr::Var(s)), params);
        }

        return Expr::Var(s);
      },
      Token::FnDecl => {
        return self.parse_fn();
      },
      Token::LParen => {
        self.eat(Token::LParen);
        let node = self.statement();
        self.eat(Token::RParen);
        return node;
      },
      Token::LBracket => {
        self.eat(Token::LBracket);
        let node = self.block();
        self.eat(Token::RBracket);
        return node;
      },
      Token::Not => {
        self.eat(Token::Not);
        return Expr::Uop(UnOp::Not, to_box(self.factor()));
      },
      Token::Minus => {
        self.eat(Token::Minus);
        return Expr::Uop(UnOp::Neg, to_box(self.factor()));
      },
      _ => {
        debug!("invalid factor: {:?}", self.current_token);
        panic!();
      },
    }
  }

  pub fn term(&mut self) -> Expr {
    let mut node = self.factor();

    let mut op = self.current_token.clone();

    while op.is_term_op() {
      self.eat(op.clone());
      let right_node = self.term();

      node = match op {
        Token::Times => self.binop(BinOp::Times, node, right_node),
        Token::Div => self.binop(BinOp::Div, node, right_node),
        _ => panic!(),
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn binop_expr(&mut self) -> Expr {
    let mut node = self.term();

    let mut op = self.current_token.clone();

    while op.is_expr_op() {
      debug!("expr looping on op {:?}", op);
      self.eat(op.clone());

      let right_node = self.term();

      node = match op {
        Token::Plus => self.binop(BinOp::Plus, node, right_node),
        Token::Minus => self.binop(BinOp::Minus, node, right_node),
        Token::Eq => self.binop(BinOp::Eq, node, right_node),
        Token::Ne => self.binop(BinOp::Ne, node, right_node),
        Token::Leq => self.binop(BinOp::Leq, node, right_node),
        Token::Geq => self.binop(BinOp::Geq, node, right_node),
        Token::Lt => self.binop(BinOp::Lt, node, right_node),
        Token::Gt => self.binop(BinOp::Gt, node, right_node),
        Token::And => self.binop(BinOp::And, node, right_node),
        Token::Or => self.binop(BinOp::Or, node, right_node),
        Token::Mod => self.binop(BinOp::Mod, node, right_node),
        Token::Assign => self.binop(BinOp::Assign, node, right_node),
        _ => panic!(),
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn statement(&mut self) -> Expr {
    if self.current_token == Token::Let {
      return self.parse_let();
    } else if self.current_token == Token::VarDecl {
      return self.parse_var();
    } else if self.current_token == Token::If {
      return self.parse_if();
    } else if self.current_token == Token::Else {
      self.eat(Token::Else);
      return self.statement();
    }

    let mut node = self.binop_expr();
    let mut op = self.current_token.clone();

    while op.is_statement_op() {
      self.eat(op.clone());

      node = match op {
        Token::Ternary => {
          let e2 = self.block();
          self.eat(Token::Else);
          let e3 = self.statement();
          self.ternary(node, e2, e3)
        },
        _ => panic!()
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn block(&mut self) -> Expr {
    let mut node = self.statement();
    let mut op = self.current_token.clone();

    while op.is_block_op() {
      self.eat(op.clone());
      let e2 = self.statement();

      node = match op {
        Token::Seq => self.binop(BinOp::Seq, node, e2),
        _ => panic!()
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn program(&mut self) -> Expr {
    self.block()
  }
}

fn to_box(e: Expr) -> Box<Expr> {
  Box::new(e)
}

pub fn parse(input: &str) -> Expr {
  let mut parser = Parser::new(input.to_string());
  let expr = parser.program();

  debug!("parsed expr: {:#?}", expr);
  debug!("original: {:#?}", input);

  expr
}
<commit_msg>move things from statements to factors<commit_after>use ast::{Expr, BinOp, UnOp, Dec};
use lexer::{Lexer, Token};

struct Parser {
  lexer: Lexer,
  current_token: Token,
}

impl Parser {
  pub fn new(text: String) -> Parser {
    let mut lexer = Lexer::new(text);

    let token = lexer.get_next_token();

    Parser {
      lexer: lexer,
      current_token: token,
    }
  }

  fn eat(&mut self, expected: Token) {
    let actual = self.current_token.clone();

    if expected != actual {
      panic!("expected token: {:?} actual: {:?}", expected, actual)
    }

    self.current_token = self.lexer.get_next_token();
    debug!("new current token: {:?}", self.current_token);
  }

  fn ternary(&mut self, e1: Expr, e2: Expr, e3: Expr) -> Expr {
    Expr::Ternary(to_box(e1), to_box(e2), to_box(e3))
  }

  fn binop(&mut self, bop: BinOp, e1: Expr, e2: Expr) -> Expr {
    Expr::Bop(bop, to_box(e1), to_box(e2))
  }

  fn parse_fn_params(&mut self) -> Vec<Expr> {
    let mut params = Vec::new();
    let mut token = self.current_token.clone();

    while token != Token::RParen {
      debug!("getting fn params");
      let term = self.binop_expr();

      params.push(term);

      if self.current_token == Token::Comma {
        self.eat(Token::Comma);
      }

      token = self.current_token.clone();
    }

    params
  }

  fn parse_fn_decl_params(&mut self) -> Vec<Expr> {
    let mut params = Vec::new();
    let mut token = self.current_token.clone();

    while token != Token::RParen {
      debug!("getting fn decl params");
      match token.clone() {
        Token::Var(s) => {
          self.eat(Token::Var(s.clone()));
          params.push(Expr::Var(s));
        },
        Token::Comma => self.eat(Token::Comma),
        _ => panic!()
      }

      token = self.current_token.clone();
    }

    params
  }

  fn parse_fn(&mut self) -> Expr {
    debug!("parsing named fn...");
    self.eat(Token::FnDecl);

    let var = match self.current_token.clone() {
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()));
        Some(Expr::Var(s))
      },
      _ => None,
    };

    self.eat(Token::LParen);
    let params = self.parse_fn_decl_params();
    self.eat(Token::RParen);
    self.eat(Token::LBracket);
    let body = self.statement();
    self.eat(Token::RBracket);

    match var {
      Some(v) => {
        self.eat(Token::Seq);
        let e3 = self.statement();

        let func = Expr::Func(Some(to_box(v.clone())), to_box(body.clone()), params);

        Expr::Decl(Dec::DConst, to_box(v), to_box(func), to_box(e3))
      },
      None => {
        Expr::Func(None, to_box(body.clone()), params)
      }
    }
  }

  fn parse_if(&mut self) -> Expr {
    self.eat(Token::If);
    let e1 = self.binop_expr();
    let e2 = self.statement();
    let e3 = self.statement();
    return self.ternary(e1, e2, e3);
  }

  fn factor(&mut self) -> Expr {
    match self.current_token.clone() {
      Token::Int(n) => {
        self.eat(Token::Int(n.clone()));
        return Expr::Int(n);
      },
      Token::Bool(b) => {
        self.eat(Token::Bool(b.clone()));
        return Expr::Bool(b);
      },
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()));

        // fn call rule
        if self.current_token == Token::LParen {
          self.eat(Token::LParen);
          let params = self.parse_fn_params();
          self.eat(Token::RParen);

          return Expr::FnCall(to_box(Expr::Var(s)), params);
        }

        return Expr::Var(s);
      },
      Token::FnDecl => {
        return self.parse_fn();
      },
      Token::VarDecl => {
        self.eat(Token::VarDecl);
        let var = self.term();
        self.eat(Token::Assign);
        let e2 = self.statement();
        self.eat(Token::Seq);
        let e3 = self.block();

        return Expr::Decl(Dec::DVar, to_box(var), to_box(e2), to_box(e3));
      },
      Token::Let => {
        self.eat(Token::Let);
        let var = self.term();
        self.eat(Token::Assign);
        let e2 = self.statement();
        self.eat(Token::Seq);
        let e3 = self.block();

        return Expr::Decl(Dec::DConst, to_box(var), to_box(e2), to_box(e3));
      },
      Token::If => {
        return self.parse_if();
      },
      Token::Else => {
        self.eat(Token::Else);
        return self.statement();
      },
      Token::LParen => {
        self.eat(Token::LParen);
        let node = self.statement();
        self.eat(Token::RParen);
        return node;
      },
      Token::LBracket => {
        self.eat(Token::LBracket);
        let node = self.block();
        self.eat(Token::RBracket);
        return node;
      },
      Token::Not => {
        self.eat(Token::Not);
        return Expr::Uop(UnOp::Not, to_box(self.factor()));
      },
      Token::Minus => {
        self.eat(Token::Minus);
        return Expr::Uop(UnOp::Neg, to_box(self.factor()));
      },
      _ => {
        debug!("invalid factor: {:?}", self.current_token);
        panic!();
      },
    }
  }

  pub fn term(&mut self) -> Expr {
    let mut node = self.factor();

    let mut op = self.current_token.clone();

    while op.is_term_op() {
      self.eat(op.clone());
      let right_node = self.term();

      node = match op {
        Token::Times => self.binop(BinOp::Times, node, right_node),
        Token::Div => self.binop(BinOp::Div, node, right_node),
        _ => panic!(),
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn binop_expr(&mut self) -> Expr {
    let mut node = self.term();

    let mut op = self.current_token.clone();

    while op.is_expr_op() {
      debug!("expr looping on op {:?}", op);
      self.eat(op.clone());

      let right_node = self.term();

      node = match op {
        Token::Plus => self.binop(BinOp::Plus, node, right_node),
        Token::Minus => self.binop(BinOp::Minus, node, right_node),
        Token::Eq => self.binop(BinOp::Eq, node, right_node),
        Token::Ne => self.binop(BinOp::Ne, node, right_node),
        Token::Leq => self.binop(BinOp::Leq, node, right_node),
        Token::Geq => self.binop(BinOp::Geq, node, right_node),
        Token::Lt => self.binop(BinOp::Lt, node, right_node),
        Token::Gt => self.binop(BinOp::Gt, node, right_node),
        Token::And => self.binop(BinOp::And, node, right_node),
        Token::Or => self.binop(BinOp::Or, node, right_node),
        Token::Mod => self.binop(BinOp::Mod, node, right_node),
        Token::Assign => self.binop(BinOp::Assign, node, right_node),
        _ => panic!(),
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn statement(&mut self) -> Expr {
    let mut node = self.binop_expr();
    let mut op = self.current_token.clone();

    while op.is_statement_op() {
      self.eat(op.clone());

      node = match op {
        Token::Ternary => {
          let e2 = self.block();
          self.eat(Token::Else);
          let e3 = self.statement();
          self.ternary(node, e2, e3)
        },
        _ => panic!()
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn block(&mut self) -> Expr {
    let mut node = self.statement();
    let mut op = self.current_token.clone();

    while op.is_block_op() {
      self.eat(op.clone());
      let e2 = self.statement();

      node = match op {
        Token::Seq => self.binop(BinOp::Seq, node, e2),
        _ => panic!()
      };

      op = self.current_token.clone();
    }

    node
  }

  pub fn program(&mut self) -> Expr {
    self.block()
  }
}

fn to_box(e: Expr) -> Box<Expr> {
  Box::new(e)
}

pub fn parse(input: &str) -> Expr {
  let mut parser = Parser::new(input.to_string());
  let expr = parser.program();

  debug!("parsed expr: {:#?}", expr);
  debug!("original: {:#?}", input);

  expr
}
<|endoftext|>


<commit_before>//  Copyright (C) 2015 Steven Allen
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//  This file is heavily based on the C header sys/acl.h
//  (C) 1999 Andreas Gruenbacher, <a.gruenbacher@computer.org>
#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_void, c_uint, c_int, c_char, ssize_t};

pub type acl_t = *mut c_void;
pub type acl_permset_t = *mut c_void;
pub type acl_entry_t = *mut c_void;

pub type acl_type_t = c_uint;
pub type acl_tag_t = c_int;
pub type acl_perm_t = c_uint;

pub const ACL_TYPE_ACCESS: acl_type_t = 0x8000;
pub const ACL_TYPE_DEFAULT: acl_type_t = 0x4000;

pub const ACL_READ: acl_perm_t = 0x04;
pub const ACL_WRITE: acl_perm_t = 0x02;
pub const ACL_EXECUTE: acl_perm_t = 0x01;

pub const ACL_UNDEFINED_TAG: acl_tag_t = 0x00;
pub const ACL_USER_OBJ: acl_tag_t = 0x01;
pub const ACL_USER: acl_tag_t = 0x02;
pub const ACL_GROUP_OBJ: acl_tag_t = 0x04;
pub const ACL_GROUP: acl_tag_t = 0x08;
pub const ACL_MASK: acl_tag_t = 0x10;
pub const ACL_OTHER: acl_tag_t = 0x20;

#[link(name = "acl")]
extern "C" {
    /*=== ACL manipulation ===*/

    pub fn acl_init(count: c_int) -> acl_t;
    pub fn acl_dup(acl: acl_t) -> acl_t;
    pub fn acl_free(data: *mut c_void) -> c_int;
    pub fn acl_valid(acl: acl_t) -> c_int;

    /*=== Entry manipulation ===*/

    pub fn acl_copy_entry(dest: acl_entry_t, src: acl_entry_t) -> c_int;
    pub fn acl_create_entry(acl: *mut acl_t, entry: *mut acl_entry_t) -> c_int;
    pub fn acl_delete_entry(acl: acl_t, entry: acl_entry_t) -> c_int;
    pub fn acl_get_entry(acl: acl_t, entry_id: c_int, entry: *mut acl_entry_t) -> c_int;

    /* Manipulate ACL entry permissions */

    pub fn acl_add_perm(permset: acl_permset_t, perm: acl_perm_t) -> c_int;
    pub fn acl_calc_mask(acl: *mut acl_t) -> c_int;
    pub fn acl_clear_perms(permset: acl_permset_t) -> c_int;
    pub fn acl_delete_perms(permset: acl_permset_t, perm: acl_perm_t) -> c_int;
    pub fn acl_get_permset(entry: acl_entry_t, permset: *mut acl_permset_t) -> c_int;
    pub fn acl_set_permset(entry: acl_entry_t, permset: acl_permset_t) -> c_int;

    /* Manipulate ACL entry tag type and qualifier */

    pub fn acl_get_qualifier(entry: acl_entry_t) -> *mut c_void;
    pub fn acl_get_tag_type(entry: acl_entry_t, tag_type: *const acl_tag_t) -> c_int;
    pub fn acl_set_qualifier(entry: acl_entry_t, tag_qualifier: *const c_void) -> c_int;
    pub fn acl_set_tag_type(entry: acl_entry_t, tag_type: acl_tag_t) -> c_int;

    /*=== Format translation ===*/

    pub fn acl_copy_ext(buf: *mut c_void, acl: acl_t, size: ssize_t) -> ssize_t;
    pub fn acl_copy_int(buf: *const c_void) -> acl_t;
    pub fn acl_from_text(buf: *const c_char) -> acl_t;
    pub fn acl_size(acl: acl_t) -> ssize_t;
    pub fn acl_to_text(acl: acl_t, len: *mut ssize_t) -> *mut c_char;

    /*=== Object manipulation ===*/

    pub fn acl_delete_def_file(path: *const c_char) -> c_int;
    pub fn acl_get_fd(fd: c_int) -> acl_t;
    pub fn acl_get_file(path: *const c_char, typ: acl_type_t) -> acl_t;
    pub fn acl_set_fd(fd: c_int, acl: acl_t) -> c_int;
    pub fn acl_set_file(path: *const c_char, typ: acl_type_t, acl: acl_t) -> c_int;
}
<commit_msg>Add ACL_*_ENTRY constants for acl_get_entry()<commit_after>//  Copyright (C) 2015 Steven Allen
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//  This file is heavily based on the C header sys/acl.h
//  (C) 1999 Andreas Gruenbacher, <a.gruenbacher@computer.org>
#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_void, c_uint, c_int, c_char, ssize_t};

pub type acl_t = *mut c_void;
pub type acl_permset_t = *mut c_void;
pub type acl_entry_t = *mut c_void;

pub type acl_type_t = c_uint;
pub type acl_tag_t = c_int;
pub type acl_perm_t = c_uint;

pub const ACL_TYPE_ACCESS: acl_type_t = 0x8000;
pub const ACL_TYPE_DEFAULT: acl_type_t = 0x4000;

pub const ACL_READ: acl_perm_t = 0x04;
pub const ACL_WRITE: acl_perm_t = 0x02;
pub const ACL_EXECUTE: acl_perm_t = 0x01;

pub const ACL_UNDEFINED_TAG: acl_tag_t = 0x00;
pub const ACL_USER_OBJ: acl_tag_t = 0x01;
pub const ACL_USER: acl_tag_t = 0x02;
pub const ACL_GROUP_OBJ: acl_tag_t = 0x04;
pub const ACL_GROUP: acl_tag_t = 0x08;
pub const ACL_MASK: acl_tag_t = 0x10;
pub const ACL_OTHER: acl_tag_t = 0x20;

pub const ACL_FIRST_ENTRY: c_int = 0;
pub const ACL_NEXT_ENTRY: c_int = 1;

#[link(name = "acl")]
extern "C" {
    /*=== ACL manipulation ===*/

    pub fn acl_init(count: c_int) -> acl_t;
    pub fn acl_dup(acl: acl_t) -> acl_t;
    pub fn acl_free(data: *mut c_void) -> c_int;
    pub fn acl_valid(acl: acl_t) -> c_int;

    /*=== Entry manipulation ===*/

    pub fn acl_copy_entry(dest: acl_entry_t, src: acl_entry_t) -> c_int;
    pub fn acl_create_entry(acl: *mut acl_t, entry: *mut acl_entry_t) -> c_int;
    pub fn acl_delete_entry(acl: acl_t, entry: acl_entry_t) -> c_int;
    pub fn acl_get_entry(acl: acl_t, entry_id: c_int, entry: *mut acl_entry_t) -> c_int;

    /* Manipulate ACL entry permissions */

    pub fn acl_add_perm(permset: acl_permset_t, perm: acl_perm_t) -> c_int;
    pub fn acl_calc_mask(acl: *mut acl_t) -> c_int;
    pub fn acl_clear_perms(permset: acl_permset_t) -> c_int;
    pub fn acl_delete_perms(permset: acl_permset_t, perm: acl_perm_t) -> c_int;
    pub fn acl_get_permset(entry: acl_entry_t, permset: *mut acl_permset_t) -> c_int;
    pub fn acl_set_permset(entry: acl_entry_t, permset: acl_permset_t) -> c_int;

    /* Manipulate ACL entry tag type and qualifier */

    pub fn acl_get_qualifier(entry: acl_entry_t) -> *mut c_void;
    pub fn acl_get_tag_type(entry: acl_entry_t, tag_type: *const acl_tag_t) -> c_int;
    pub fn acl_set_qualifier(entry: acl_entry_t, tag_qualifier: *const c_void) -> c_int;
    pub fn acl_set_tag_type(entry: acl_entry_t, tag_type: acl_tag_t) -> c_int;

    /*=== Format translation ===*/

    pub fn acl_copy_ext(buf: *mut c_void, acl: acl_t, size: ssize_t) -> ssize_t;
    pub fn acl_copy_int(buf: *const c_void) -> acl_t;
    pub fn acl_from_text(buf: *const c_char) -> acl_t;
    pub fn acl_size(acl: acl_t) -> ssize_t;
    pub fn acl_to_text(acl: acl_t, len: *mut ssize_t) -> *mut c_char;

    /*=== Object manipulation ===*/

    pub fn acl_delete_def_file(path: *const c_char) -> c_int;
    pub fn acl_get_fd(fd: c_int) -> acl_t;
    pub fn acl_get_file(path: *const c_char, typ: acl_type_t) -> acl_t;
    pub fn acl_set_fd(fd: c_int, acl: acl_t) -> c_int;
    pub fn acl_set_file(path: *const c_char, typ: acl_type_t, acl: acl_t) -> c_int;
}
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

#![cfg_attr(unix, no_std)]

#[cfg(unix)]
extern crate libc;
#[cfg(windows)]
extern crate winapi;
#[cfg(target_os = "redox")]
extern crate termion;

#[cfg(windows)]
use winapi::shared::minwindef::DWORD;

/// possible stream sources
#[derive(Clone, Copy, Debug)]
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(all(unix, not(target_arch = "wasm32")))]
pub fn is(stream: Stream) -> bool {
    extern crate libc;

    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    use winapi::um::winbase::{STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT,
                 STD_OUTPUT_HANDLE as STD_OUTPUT};

    let (fd, others) = match stream {
        Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]),
        Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]),
        Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]),
    };
    if unsafe { console_on_any(&[fd]) } {
        // False positives aren't possible. If we got a console then
        // we definitely have a tty on stdin.
        return true;
    }

    // At this point, we *could* have a false negative. We can determine that
    // this is true negative if we can detect the presence of a console on
    // any of the other streams. If another stream has a console, then we know
    // we're in a Windows console and can therefore trust the negative.
    if unsafe { console_on_any(&others) } {
        return false;
    }

    // Otherwise, we fall back to a very strange msys hack to see if we can
    // sneakily detect the presence of a tty.
    unsafe { msys_tty_on(fd) }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

/// Returns true if any of the given fds are on a console.
#[cfg(windows)]
unsafe fn console_on_any(fds: &[DWORD]) -> bool {
    use winapi::um::consoleapi::GetConsoleMode;
    use winapi::um::processenv::GetStdHandle;

    for &fd in fds {
        let mut out = 0;
        let handle = GetStdHandle(fd);
        if GetConsoleMode(handle, &mut out) != 0 {
            return true;
        }
    }
    false
}

/// Returns true if there is an MSYS tty on the given handle.
#[cfg(windows)]
unsafe fn msys_tty_on(fd: DWORD) -> bool {
    use std::ffi::OsString;
    use std::mem;
    use std::os::windows::ffi::OsStringExt;
    use std::slice;

    use winapi::ctypes::c_void;
    use winapi::um::winbase::GetFileInformationByHandleEx;
    use winapi::um::fileapi::FILE_NAME_INFO;
    use winapi::um::minwinbase::FileNameInfo;
    use winapi::um::processenv::GetStdHandle;
    use winapi::shared::minwindef::MAX_PATH;

    let size = mem::size_of::<FILE_NAME_INFO>();
    let mut name_info_bytes = vec![0u8; size + MAX_PATH];
    let res = GetFileInformationByHandleEx(
        GetStdHandle(fd),
        FileNameInfo,
        &mut *name_info_bytes as *mut _ as *mut c_void,
        name_info_bytes.len() as u32,
    );
    if res == 0 {
        return false;
    }
    let name_info: FILE_NAME_INFO = *(name_info_bytes[0..size].as_ptr() as
                                          *const FILE_NAME_INFO);
    let name_bytes =
        &name_info_bytes[size..size + name_info.FileNameLength as usize];
    let name_u16 = slice::from_raw_parts(
        name_bytes.as_ptr() as *const u16,
        name_bytes.len() / 2,
    );
    let name = OsString::from_wide(name_u16)
        .as_os_str()
        .to_string_lossy()
        .into_owned();
    // This checks whether 'pty' exists in the file name, which indicates that
    // a pseudo-terminal is attached. To mitigate against false positives
    // (e.g., an actual file name that contains 'pty'), we also require that
    // either the strings 'msys-' or 'cygwin-' are in the file name as well.)
    let is_msys = name.contains("msys-") || name.contains("cygwin-");
    let is_pty = name.contains("-pty");
    is_msys && is_pty
}

/// returns true if this is a tty
#[cfg(target_os = "redox")]
pub fn is(stream: Stream) -> bool {
    use std::io;
    use termion::is_tty;

    match stream {
        Stream::Stdin => is_tty(&io::stdin()),
        Stream::Stdout => is_tty(&io::stdout()),
        Stream::Stderr => is_tty(&io::stderr()),
    }
}

/// returns true if this is a tty
#[cfg(target_arch = "wasm32")]
pub fn is(_stream: Stream) -> bool {
    false
}

#[cfg(test)]
mod tests {
    use super::{Stream, is};

    #[test]
    #[cfg(windows)]
    fn is_err() {
        // appveyor pipes its output
        assert!(!is(Stream::Stderr))
    }

    #[test]
    #[cfg(windows)]
    fn is_out() {
        // appveyor pipes its output
        assert!(!is(Stream::Stdout))
    }

    #[test]
    #[cfg(windows)]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }

    #[test]
    #[cfg(unix)]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    #[cfg(unix)]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    #[cfg(target_os = "macos")]
    fn is_in() {
        // macos on travis seems to pipe its input
        assert!(is(Stream::Stdin))
    }

    #[test]
    #[cfg(all(not(target_os = "macos"), unix))]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<commit_msg>Fix msys detection with new winapi.<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

#![cfg_attr(unix, no_std)]

#[cfg(unix)]
extern crate libc;
#[cfg(windows)]
extern crate winapi;
#[cfg(target_os = "redox")]
extern crate termion;

#[cfg(windows)]
use winapi::shared::minwindef::DWORD;
#[cfg(windows)]
use winapi::shared::ntdef::WCHAR;

/// possible stream sources
#[derive(Clone, Copy, Debug)]
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(all(unix, not(target_arch = "wasm32")))]
pub fn is(stream: Stream) -> bool {
    extern crate libc;

    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    use winapi::um::winbase::{STD_ERROR_HANDLE as STD_ERROR, STD_INPUT_HANDLE as STD_INPUT,
                 STD_OUTPUT_HANDLE as STD_OUTPUT};

    let (fd, others) = match stream {
        Stream::Stdin => (STD_INPUT, [STD_ERROR, STD_OUTPUT]),
        Stream::Stderr => (STD_ERROR, [STD_INPUT, STD_OUTPUT]),
        Stream::Stdout => (STD_OUTPUT, [STD_INPUT, STD_ERROR]),
    };
    if unsafe { console_on_any(&[fd]) } {
        // False positives aren't possible. If we got a console then
        // we definitely have a tty on stdin.
        return true;
    }

    // At this point, we *could* have a false negative. We can determine that
    // this is true negative if we can detect the presence of a console on
    // any of the other streams. If another stream has a console, then we know
    // we're in a Windows console and can therefore trust the negative.
    if unsafe { console_on_any(&others) } {
        return false;
    }

    // Otherwise, we fall back to a very strange msys hack to see if we can
    // sneakily detect the presence of a tty.
    unsafe { msys_tty_on(fd) }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

/// Returns true if any of the given fds are on a console.
#[cfg(windows)]
unsafe fn console_on_any(fds: &[DWORD]) -> bool {
    use winapi::um::consoleapi::GetConsoleMode;
    use winapi::um::processenv::GetStdHandle;

    for &fd in fds {
        let mut out = 0;
        let handle = GetStdHandle(fd);
        if GetConsoleMode(handle, &mut out) != 0 {
            return true;
        }
    }
    false
}

/// Returns true if there is an MSYS tty on the given handle.
#[cfg(windows)]
unsafe fn msys_tty_on(fd: DWORD) -> bool {
    use std::mem;
    use std::slice;

    use winapi::ctypes::c_void;
    use winapi::um::winbase::GetFileInformationByHandleEx;
    use winapi::um::fileapi::FILE_NAME_INFO;
    use winapi::um::minwinbase::FileNameInfo;
    use winapi::um::processenv::GetStdHandle;
    use winapi::shared::minwindef::MAX_PATH;

    let size = mem::size_of::<FILE_NAME_INFO>();
    let mut name_info_bytes = vec![0u8; size + MAX_PATH * mem::size_of::<WCHAR>()];
    let res = GetFileInformationByHandleEx(
        GetStdHandle(fd),
        FileNameInfo,
        &mut *name_info_bytes as *mut _ as *mut c_void,
        name_info_bytes.len() as u32,
    );
    if res == 0 {
        return false;
    }
    let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO);
    let s = slice::from_raw_parts(
        name_info.FileName.as_ptr(),
        name_info.FileNameLength as usize / 2,
    );
    let name = String::from_utf16_lossy(s);
    // This checks whether 'pty' exists in the file name, which indicates that
    // a pseudo-terminal is attached. To mitigate against false positives
    // (e.g., an actual file name that contains 'pty'), we also require that
    // either the strings 'msys-' or 'cygwin-' are in the file name as well.)
    let is_msys = name.contains("msys-") || name.contains("cygwin-");
    let is_pty = name.contains("-pty");
    is_msys && is_pty
}

/// returns true if this is a tty
#[cfg(target_os = "redox")]
pub fn is(stream: Stream) -> bool {
    use std::io;
    use termion::is_tty;

    match stream {
        Stream::Stdin => is_tty(&io::stdin()),
        Stream::Stdout => is_tty(&io::stdout()),
        Stream::Stderr => is_tty(&io::stderr()),
    }
}

/// returns true if this is a tty
#[cfg(target_arch = "wasm32")]
pub fn is(_stream: Stream) -> bool {
    false
}

#[cfg(test)]
mod tests {
    use super::{Stream, is};

    #[test]
    #[cfg(windows)]
    fn is_err() {
        // appveyor pipes its output
        assert!(!is(Stream::Stderr))
    }

    #[test]
    #[cfg(windows)]
    fn is_out() {
        // appveyor pipes its output
        assert!(!is(Stream::Stdout))
    }

    #[test]
    #[cfg(windows)]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }

    #[test]
    #[cfg(unix)]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    #[cfg(unix)]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    #[cfg(target_os = "macos")]
    fn is_in() {
        // macos on travis seems to pipe its input
        assert!(is(Stream::Stdin))
    }

    #[test]
    #[cfg(all(not(target_os = "macos"), unix))]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<|endoftext|>


<commit_before>// TODO(nicholasbishop): remove this
#![allow(dead_code)]

mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

pub type VKey = Key;
pub type EKey = Key;
pub type FKey = Key;
pub type LKey = Key;
pub type FaceLen = u32;

pub struct Mesh {
    verts: HashMap<VKey, Vert>,
    edges: HashMap<EKey, Edge>,
    loops: HashMap<LKey, Loop>,
    faces: HashMap<FKey, Face>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            loops: HashMap::new(),
            faces: HashMap::new(),

            // TODO
            vert_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            edge_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            face_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1))
        }
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new());
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().edges.push(ekey);
                self.verts.get_mut(&vk1).unwrap().edges.push(ekey);
                self.edges.insert(ekey, Edge { verts: [vk0, vk1] });
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey]) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            if let Some(ek) = self.add_edge(vk0, vk1) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            self.faces.insert(fk, Face::new(loops));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert {
    edges: Vec<EKey>
}

impl Vert {
    fn new() -> Vert {
        Vert { edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge {
    verts: [VKey; 2],
    // faces: Vec<FKey>
}

impl Edge {
    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face {
    loops: Vec<Loop>
}

impl Face {
    fn new(loops: Vec<Loop>) -> Face {
        Face { loops: loops }
    }
}

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

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::new();
        assert!(mesh.add_vert().is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();
        let c = mesh.add_vert().unwrap();

        // Add a valid triangle
        mesh.add_face(&[a, b, c]).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        // TODO(nicholasbishop): check adj

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b]).is_none());
    }
}
<commit_msg>Checkpoint<commit_after>mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

pub type VKey = Key;
pub type EKey = Key;
pub type FKey = Key;
pub type FaceLen = u32;

pub struct Mesh {
    verts: HashMap<VKey, Vert>,
    edges: HashMap<EKey, Edge>,
    faces: HashMap<FKey, Face>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            faces: HashMap::new(),

            // TODO
            vert_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            edge_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1)),
            face_range_set: RangeSet::new(Range::new(0, 0xffffffff - 1))
        }
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new());
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().push_edge(ekey);
                self.verts.get_mut(&vk1).unwrap().push_edge(ekey);
                self.edges.insert(ekey, Edge::new(vk0, vk1));
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey]) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            if let Some(ek) = self.add_edge(vk0, vk1) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            self.faces.insert(fk, Face::new(loops));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert {
    edges: Vec<EKey>
}

impl Vert {
    fn new() -> Vert {
        Vert { edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge {
    verts: [VKey; 2],
    // faces: Vec<FKey>
}

impl Edge {
    fn new(vk0: VKey, vk1: VKey) -> Edge {
        Edge { verts: [vk0, vk1] }
    }

    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face {
    loops: Vec<Loop>
}

impl Face {
    fn new(loops: Vec<Loop>) -> Face {
        Face { loops: loops }
    }
}

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

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::new();
        assert!(mesh.add_vert().is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert().unwrap();
        let b = mesh.add_vert().unwrap();
        let c = mesh.add_vert().unwrap();

        // Add a valid triangle
        mesh.add_face(&[a, b, c]).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        // TODO(nicholasbishop): check adj

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b]).is_none());
    }
}
<|endoftext|>


<commit_before>
extern crate hyper;
extern crate url;

use std::io::{Read, Write};
use url::{Url, ParseError};
use hyper::error::Error;
use hyper::client::Request;
use hyper::method::Method;
pub use hyper::header::*;

pub struct Client<'a, H: Header + HeaderFormat> {
    url: Option<Url>,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<&'a str>,
    headers: Option<Vec<H>>,
}

impl<'a, H: Header + HeaderFormat> Client<'a, H> {
    pub fn new(url_str: &'a str) -> Result<Client<'a, H>, ParseError> {
        let url = try!(Url::parse(url_str));
        Ok(Client { url: Some(url), params: None, body: None, headers: None })
    }

    pub fn param(&'a mut self, param: (&'a str, &'a str)) -> &'a mut Client<'a, H> {
        if let Some(ref mut p) = self.params {
            p.push(param);
        }
        else
        {
            let mut v = Vec::new();
            v.push(param);
            self.params = Some(v);
        }
        self
    }

    pub fn body(&'a mut self, body: &'a str) -> &'a mut Client<'a, H> {
        self.body = Some(body);
        self
    }

    pub fn header(&'a mut self, header: H) -> &'a mut Client<'a, H> {
        if let Some(ref mut h) = self.headers {
            h.push(header);
        }
        else
        {
            let mut v = Vec::new();
            v.push(header);
            self.headers = Some(v);
        }
        self
    }

    pub fn get(&mut self) -> Result<String, Error> {
        let mut url = self.url.as_mut().expect("You must set a URL before sending request!");

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let mut req = try!(Request::new(Method::Get, url.clone()));

        if let Some(headers) = self.headers.as_ref() {
           for header in headers {
               req.headers_mut().set(header.clone());
           }
       }

        let mut req = try!(req.start());

        if let Some(body) = self.body {
           req.write(body.as_bytes());
       }

        let mut resp = try!(req.send());

        let mut response_string = String::new();
        resp.read_to_string(&mut response_string);
        Ok(response_string)
    }
}
<commit_msg>Move clone so that URL can be reused with other params.<commit_after>
extern crate hyper;
extern crate url;

use std::io::{Read, Write};
use url::{Url, ParseError};
use hyper::error::Error;
use hyper::client::Request;
use hyper::method::Method;
pub use hyper::header::*;

pub struct Client<'a, H: Header + HeaderFormat> {
    url: Option<Url>,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<&'a str>,
    headers: Option<Vec<H>>,
}

impl<'a, H: Header + HeaderFormat> Client<'a, H> {
    pub fn new(url_str: &'a str) -> Result<Client<'a, H>, ParseError> {
        let url = try!(Url::parse(url_str));
        Ok(Client { url: Some(url), params: None, body: None, headers: None })
    }

    pub fn param(&'a mut self, param: (&'a str, &'a str)) -> &'a mut Client<'a, H> {
        if let Some(ref mut p) = self.params {
            p.push(param);
        }
        else
        {
            let mut v = Vec::new();
            v.push(param);
            self.params = Some(v);
        }
        self
    }

    pub fn body(&'a mut self, body: &'a str) -> &'a mut Client<'a, H> {
        self.body = Some(body);
        self
    }

    pub fn header(&'a mut self, header: H) -> &'a mut Client<'a, H> {
        if let Some(ref mut h) = self.headers {
            h.push(header);
        }
        else
        {
            let mut v = Vec::new();
            v.push(header);
            self.headers = Some(v);
        }
        self
    }

    pub fn get(&mut self) -> Result<String, Error> {
        let mut url = self.url.clone().expect("You must set a URL before sending request!");

        if let Some(ref params) = self.params {
            url.set_query_from_pairs(params.into_iter().map(|&x| x));
        }

        let mut req = try!(Request::new(Method::Get, url));

        if let Some(headers) = self.headers.as_ref() {
           for header in headers {
               req.headers_mut().set(header.clone());
           }
       }

        let mut req = try!(req.start());

        if let Some(body) = self.body {
           req.write(body.as_bytes());
       }

        let mut resp = try!(req.send());

        let mut response_string = String::new();
        resp.read_to_string(&mut response_string);
        Ok(response_string)
    }
}
<|endoftext|>


<commit_before>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! Attempt of creating a cheap drawing context.

use std::num::Float;

pub type Matrix2d = [f64, ..6];
pub type Color = [f64, ..4];
pub type Rectangle = [f64, ..4];

/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}

/// Implemented by contexts that can transform.
pub trait Transform<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;
}

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> [f64, ..6] {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Drawing 2d context.
pub struct Context<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

impl<'a> Transform<'a> for Context<'a> {
    /// Returns a translated context.
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans: [f64, ..6] = [1.0, 0.0, x,
                                         0.0, 1.0, y];
                 multiply(&trans, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            color: Value([0.0, 0.0, 0.0, 1.0]),
        }
    }

    /// Rotates with degrees.
    #[inline(always)]
    pub fn rot_deg(&'a self, angle: f64) -> Context<'a> {
        let pi: f64 = Float::pi();
        self.rot(angle * pi / 180.0)
    }

    /// Returns a rotated context.
    #[inline(always)]
    pub fn rot(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let c = angle.cos();
                let s = angle.sin();
                let rot: [f64, ..6] = [c, s, 0.0,
                                      -s, c, 0.0];
                multiply(&rot, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }

    /// Returns a scaled context.
    #[inline(always)]
    pub fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale: [f64, ..6] = [sx, 0.0, 0.0,
                                         0.0, sy, 0.0];
                multiply(&scale, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }

    /// Returns a sheared context.
    #[inline(always)]
    pub fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear: [f64, ..6] = [1.0, sx, 0.0,
                                         sy, 1.0, 0.0];
            multiply(&shear, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }
}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

/// A context with color information.
pub struct ColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

/// A rectangle context.
pub struct RectangleContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
}

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
    color: Field<'a, Color>,
}

<commit_msg>Moved transformations to trait<commit_after>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! Attempt of creating a cheap drawing context.

use std::num::Float;

pub type Matrix2d = [f64, ..6];
pub type Color = [f64, ..4];
pub type Rectangle = [f64, ..4];

/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}

/// Implemented by contexts that can transform.
pub trait Transform2d<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;
    /// Rotate degrees.
    fn rot_deg(&'a self, angle: f64) -> Self;
    /// Rotate radians.
    fn rot_rad(&'a self, angle: f64) -> Self;
    /// Scale.
    fn scale(&'a self, sx: f64, sy: f64) -> Self;
    /// Shear.
    fn shear(&'a self, sx: f64, sy: f64) -> Self;
}

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> [f64, ..6] {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Drawing 2d context.
pub struct Context<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans: [f64, ..6] = [1.0, 0.0, x,
                                         0.0, 1.0, y];
                 multiply(&trans, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_deg(&'a self, angle: f64) -> Context<'a> {
        let pi: f64 = Float::pi();
        self.rot_rad(angle * pi / 180.0)
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let c = angle.cos();
                let s = angle.sin();
                let rot: [f64, ..6] = [c, s, 0.0,
                                      -s, c, 0.0];
                multiply(&rot, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale: [f64, ..6] = [sx, 0.0, 0.0,
                                         0.0, sy, 0.0];
                multiply(&scale, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear: [f64, ..6] = [1.0, sx, 0.0,
                                         sy, 1.0, 0.0];
            multiply(&shear, self.transform.get())
            }),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            color: Value([0.0, 0.0, 0.0, 1.0]),
        }
    }

}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

/// A context with color information.
pub struct ColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

/// A rectangle context.
pub struct RectangleContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
}

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
    color: Field<'a, Color>,
}

<|endoftext|>


<commit_before>// Systray Lib

extern crate log;
#[cfg(target_os = "linux")]
extern crate glib;
#[cfg(target_os = "linux")]
extern crate gtk;
#[cfg(target_os = "linux")]
extern crate libappindicator;
#[cfg(target_os = "windows")]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate winapi;

pub mod api;

use std::{
    collections::HashMap,
    error, fmt,
    sync::mpsc::{channel, Receiver},
};

type BoxedError = Box<dyn error::Error + Send + Sync + 'static>;

#[derive(Debug)]
pub enum Error {
    OsError(String),
    NotImplementedError,
    UnknownError,
    Error(BoxedError),
}

impl From<BoxedError> for Error {
    fn from(value: BoxedError) -> Self {
        Error::Error(value)
    }
}

pub struct SystrayEvent {
    menu_index: u32,
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use self::Error::*;

        match *self {
            OsError(ref err_str) => write!(f, "OsError: {}", err_str),
            NotImplementedError => write!(f, "Functionality is not implemented yet"),
            UnknownError => write!(f, "Unknown error occurrred"),
            Error(ref e) => write!(f, "Error: {}", e),
        }
    }
}

pub struct Application {
    window: api::api::Window,
    menu_idx: u32,
    callback: HashMap<u32, Callback>,
    // Each platform-specific window module will set up its own thread for
    // dealing with the OS main loop. Use this channel for receiving events from
    // that thread.
    rx: Receiver<SystrayEvent>,
}

type Callback = Box<(dyn Fn(&mut Application) -> Result<(), BoxedError> + Send + Sync + 'static)>;

fn make_callback<F, E>(f: F) -> Callback
where
    F: Fn(&mut Application) -> Result<(), E> + Send + Sync + 'static,
    E: error::Error + Send + Sync + 'static,
{
    Box::new(move |a: &mut Application| match f(a) {
        Ok(()) => Ok(()),
        Err(e) => Err(Box::new(e) as BoxedError),
    }) as Callback
}

impl Application {
    pub fn new() -> Result<Application, Error> {
        let (event_tx, event_rx) = channel();
        match api::api::Window::new(event_tx) {
            Ok(w) => Ok(Application {
                window: w,
                menu_idx: 0,
                callback: HashMap::new(),
                rx: event_rx,
            }),
            Err(e) => Err(e),
        }
    }

    pub fn add_menu_item<F, E>(&mut self, item_name: &str, f: F) -> Result<u32, Error>
    where
        F: Fn(&mut Application) -> Result<(), E> + Send + Sync + 'static,
        E: error::Error + Send + Sync + 'static,
    {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_entry(idx, item_name) {
            return Err(e);
        }
        self.callback.insert(idx, make_callback(f));
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn add_menu_separator(&mut self) -> Result<u32, Error> {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_separator(idx) {
            return Err(e);
        }
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn set_icon_from_file(&self, file: &str) -> Result<(), Error> {
        self.window.set_icon_from_file(file)
    }

    pub fn set_icon_from_resource(&self, resource: &str) -> Result<(), Error> {
        self.window.set_icon_from_resource(resource)
    }

    #[cfg(target_os = "windows")]
    pub fn set_icon_from_buffer(
        &self,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Result<(), Error> {
        self.window.set_icon_from_buffer(buffer, width, height)
    }

    pub fn shutdown(&self) -> Result<(), Error> {
        self.window.shutdown()
    }

    pub fn set_tooltip(&self, tooltip: &str) -> Result<(), Error> {
        self.window.set_tooltip(tooltip)
    }

    pub fn quit(&mut self) {
        self.window.quit()
    }

    pub fn wait_for_message(&mut self) -> Result<(), Error> {
        loop {
            let msg;
            match self.rx.recv() {
                Ok(m) => msg = m,
                Err(_) => {
                    self.quit();
                    break;
                }
            }
            if self.callback.contains_key(&msg.menu_index) {
                if let Some(f) = self.callback.remove(&msg.menu_index) {
                    f(self)?;
                    self.callback.insert(msg.menu_index, f);
                }
            }
        }

        Ok(())
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        self.shutdown().ok();
    }
}
<commit_msg>Make callback FnMut<commit_after>// Systray Lib

extern crate log;
#[cfg(target_os = "linux")]
extern crate glib;
#[cfg(target_os = "linux")]
extern crate gtk;
#[cfg(target_os = "linux")]
extern crate libappindicator;
#[cfg(target_os = "windows")]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate winapi;

pub mod api;

use std::{
    collections::HashMap,
    error, fmt,
    sync::mpsc::{channel, Receiver},
};

type BoxedError = Box<dyn error::Error + Send + Sync + 'static>;

#[derive(Debug)]
pub enum Error {
    OsError(String),
    NotImplementedError,
    UnknownError,
    Error(BoxedError),
}

impl From<BoxedError> for Error {
    fn from(value: BoxedError) -> Self {
        Error::Error(value)
    }
}

pub struct SystrayEvent {
    menu_index: u32,
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        use self::Error::*;

        match *self {
            OsError(ref err_str) => write!(f, "OsError: {}", err_str),
            NotImplementedError => write!(f, "Functionality is not implemented yet"),
            UnknownError => write!(f, "Unknown error occurrred"),
            Error(ref e) => write!(f, "Error: {}", e),
        }
    }
}

pub struct Application {
    window: api::api::Window,
    menu_idx: u32,
    callback: HashMap<u32, Callback>,
    // Each platform-specific window module will set up its own thread for
    // dealing with the OS main loop. Use this channel for receiving events from
    // that thread.
    rx: Receiver<SystrayEvent>,
}

type Callback =
    Box<(dyn FnMut(&mut Application) -> Result<(), BoxedError> + Send + Sync + 'static)>;

fn make_callback<F, E>(mut f: F) -> Callback
where
    F: FnMut(&mut Application) -> Result<(), E> + Send + Sync + 'static,
    E: error::Error + Send + Sync + 'static,
{
    Box::new(move |a: &mut Application| match f(a) {
        Ok(()) => Ok(()),
        Err(e) => Err(Box::new(e) as BoxedError),
    }) as Callback
}

impl Application {
    pub fn new() -> Result<Application, Error> {
        let (event_tx, event_rx) = channel();
        match api::api::Window::new(event_tx) {
            Ok(w) => Ok(Application {
                window: w,
                menu_idx: 0,
                callback: HashMap::new(),
                rx: event_rx,
            }),
            Err(e) => Err(e),
        }
    }

    pub fn add_menu_item<F, E>(&mut self, item_name: &str, f: F) -> Result<u32, Error>
    where
        F: FnMut(&mut Application) -> Result<(), E> + Send + Sync + 'static,
        E: error::Error + Send + Sync + 'static,
    {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_entry(idx, item_name) {
            return Err(e);
        }
        self.callback.insert(idx, make_callback(f));
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn add_menu_separator(&mut self) -> Result<u32, Error> {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_separator(idx) {
            return Err(e);
        }
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn set_icon_from_file(&self, file: &str) -> Result<(), Error> {
        self.window.set_icon_from_file(file)
    }

    pub fn set_icon_from_resource(&self, resource: &str) -> Result<(), Error> {
        self.window.set_icon_from_resource(resource)
    }

    #[cfg(target_os = "windows")]
    pub fn set_icon_from_buffer(
        &self,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Result<(), Error> {
        self.window.set_icon_from_buffer(buffer, width, height)
    }

    pub fn shutdown(&self) -> Result<(), Error> {
        self.window.shutdown()
    }

    pub fn set_tooltip(&self, tooltip: &str) -> Result<(), Error> {
        self.window.set_tooltip(tooltip)
    }

    pub fn quit(&mut self) {
        self.window.quit()
    }

    pub fn wait_for_message(&mut self) -> Result<(), Error> {
        loop {
            let msg;
            match self.rx.recv() {
                Ok(m) => msg = m,
                Err(_) => {
                    self.quit();
                    break;
                }
            }
            if self.callback.contains_key(&msg.menu_index) {
                if let Some(mut f) = self.callback.remove(&msg.menu_index) {
                    f(self)?;
                    self.callback.insert(msg.menu_index, f);
                }
            }
        }

        Ok(())
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        self.shutdown().ok();
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An ordered map and set based on a trie.

#![feature(core)]
#![cfg_attr(test, feature(hash, step_by, test, unboxed_closures))]

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

pub use map::Map;
pub use set::Set;

#[cfg(test)] #[macro_use] mod bench;

pub mod map;
pub mod set;

#[cfg(feature="ordered_iter")]
mod ordered_iter;
<commit_msg>update to Rust master<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An ordered map and set based on a trie.

#![feature(iter_order, num_bits_bytes)]
#![cfg_attr(test, feature(core, hash_default, step_by, test, unboxed_closures))]

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate test;

pub use map::Map;
pub use set::Set;

#[cfg(test)] #[macro_use] mod bench;

pub mod map;
pub mod set;

#[cfg(feature="ordered_iter")]
mod ordered_iter;
<|endoftext|>