<commit_before>use std::collections::HashMap;

pub struct Circuit {
    gates: HashMap<String, Gate>,
    cache: HashMap<String, u16>,
}

impl Circuit {
    pub fn new(input: &str) -> Self {
        let mut circuit: HashMap<String, Gate> = HashMap::new();

        for line in input.lines() {
            let (result, instruction) = parse_instruction(line);
            circuit.insert(result, instruction);
        }

        Circuit {
            gates: circuit,
            cache: HashMap::new(),
        }
    }

    pub fn resolve(&mut self, ident: &str) -> u16 {
        if let Some(value) = self.cache.get(ident) {
            return value.to_owned()
        }

        let instruction = self.gates[ident].clone();

        match instruction {
            Gate::And(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs & rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Or(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs | rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Not(rhs) => {
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = !rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::LShift(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs << rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::RShift(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs >> rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Signal(val) => {
                let result = match val {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                self.cache.insert(ident.to_owned(), result);

                result
            }
        }
    }

    #[allow(dead_code)]
    pub fn set_gate(&mut self, ident: &str, value: u16) {
        self.gates.remove(ident).unwrap();
        self.gates.insert(ident.to_owned(), Gate::Signal(Node::Value(value)));
    }
}

#[derive(Clone, Debug)]
enum Node {
    Reference(String),
    Value(u16),
}

#[derive(Clone, Debug)]
enum Gate {
    And(Node, Node),
    Or(Node, Node),
    Not(Node),
    RShift(Node, u16),
    LShift(Node, u16),
    Signal(Node),
}

fn parse_instruction(line: &str) -> (String, Gate) {
    let op: Vec<_> = line.split(" -> ").collect();
    let result = op[1];

    let instruction = {
        if line.contains("AND") {
            parse_and(line)
        } else if line.contains("OR") {
            parse_or(line)
        } else if line.contains("NOT") {
            parse_not(line)
        } else if line.contains("LSHIFT") {
            parse_lshift(line)
        } else if line.contains("RSHIFT") {
            parse_rshift(line)
        } else {
            parse_signal(line)
        }
    };

    (result.to_owned(), instruction)
}

fn parse_and(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" AND ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs = match ops[1].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::And(lhs, rhs)
}

fn parse_or(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" OR ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs = match ops[1].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::Or(lhs, rhs)
}

fn parse_not(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split("NOT ").collect();

    let rhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::Not(rhs)
}

fn parse_lshift(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" LSHIFT ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs: u16 = ops[1].parse().expect(format!("Invalid input: {}", ops[1]).as_ref());

    Gate::LShift(lhs, rhs)
}

fn parse_rshift(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" RSHIFT ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs: u16 = ops[1].parse().expect(format!("Invalid input: {}", ops[1]).as_ref());

    Gate::RShift(lhs, rhs)
}

fn parse_signal(line: &str) -> Gate {
    let ops: Vec<_> = line.split(" -> ").collect();
    let signal = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    Gate::Signal(signal)
}
<commit_msg>unecessary #[derive(Debug)]<commit_after>use std::collections::HashMap;

pub struct Circuit {
    gates: HashMap<String, Gate>,
    cache: HashMap<String, u16>,
}

impl Circuit {
    pub fn new(input: &str) -> Self {
        let mut circuit: HashMap<String, Gate> = HashMap::new();

        for line in input.lines() {
            let (result, instruction) = parse_instruction(line);
            circuit.insert(result, instruction);
        }

        Circuit {
            gates: circuit,
            cache: HashMap::new(),
        }
    }

    pub fn resolve(&mut self, ident: &str) -> u16 {
        if let Some(value) = self.cache.get(ident) {
            return value.to_owned()
        }

        let instruction = self.gates[ident].clone();

        match instruction {
            Gate::And(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs & rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Or(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs | rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Not(rhs) => {
                let rhs = match rhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = !rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::LShift(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs << rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::RShift(lhs, rhs) => {
                let lhs = match lhs {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                let result = lhs >> rhs;
                self.cache.insert(ident.to_owned(), result);

                result
            }
            Gate::Signal(val) => {
                let result = match val {
                    Node::Reference(ref ident) => self.resolve(ident),
                    Node::Value(sig) => sig,
                };

                self.cache.insert(ident.to_owned(), result);

                result
            }
        }
    }

    #[allow(dead_code)]
    pub fn set_gate(&mut self, ident: &str, value: u16) {
        self.gates.remove(ident).unwrap();
        self.gates.insert(ident.to_owned(), Gate::Signal(Node::Value(value)));
    }
}

#[derive(Clone)]
enum Node {
    Reference(String),
    Value(u16),
}

#[derive(Clone)]
enum Gate {
    And(Node, Node),
    Or(Node, Node),
    Not(Node),
    RShift(Node, u16),
    LShift(Node, u16),
    Signal(Node),
}

fn parse_instruction(line: &str) -> (String, Gate) {
    let op: Vec<_> = line.split(" -> ").collect();
    let result = op[1];

    let instruction = {
        if line.contains("AND") {
            parse_and(line)
        } else if line.contains("OR") {
            parse_or(line)
        } else if line.contains("NOT") {
            parse_not(line)
        } else if line.contains("LSHIFT") {
            parse_lshift(line)
        } else if line.contains("RSHIFT") {
            parse_rshift(line)
        } else {
            parse_signal(line)
        }
    };

    (result.to_owned(), instruction)
}

fn parse_and(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" AND ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs = match ops[1].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::And(lhs, rhs)
}

fn parse_or(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" OR ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs = match ops[1].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::Or(lhs, rhs)
}

fn parse_not(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split("NOT ").collect();

    let rhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[1].to_owned()),
    };

    Gate::Not(rhs)
}

fn parse_lshift(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" LSHIFT ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs: u16 = ops[1].parse().expect(format!("Invalid input: {}", ops[1]).as_ref());

    Gate::LShift(lhs, rhs)
}

fn parse_rshift(line: &str) -> Gate {
    let instruction: Vec<_> = line.split(" -> ").collect();
    let ops: Vec<_> = instruction[0].split(" RSHIFT ").collect();

    let lhs = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    let rhs: u16 = ops[1].parse().expect(format!("Invalid input: {}", ops[1]).as_ref());

    Gate::RShift(lhs, rhs)
}

fn parse_signal(line: &str) -> Gate {
    let ops: Vec<_> = line.split(" -> ").collect();
    let signal = match ops[0].parse::<u16>() {
        Ok(val) => Node::Value(val),
        Err(_) => Node::Reference(ops[0].to_owned()),
    };

    Gate::Signal(signal)
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod macros;
pub mod arguments;
pub mod configuration;
pub mod engines;
pub mod error;
pub mod network;

extern crate std;
extern crate toml;

use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Bin;
use hyper::Url;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::ops::Range;
use std::path::Path;
use toml::Value;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile {
      name: name,
      data: data
    }
  }
}

trait Join {
  fn join(&self) -> String;
}

impl Join for Vec<PasteFile> {
  fn join(&self) -> String {
    if self.len() == 1 {
      self.get(0).expect("len() == 1, but no first element").data.clone()
    } else {
      self.into_iter().map(|p| format!("--- {} ---\n\n{}", p.name, p.data)).collect::<Vec<String>>().join("\n\n")
    }
  }
}

pub struct Bins {
  pub config: Value,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Value, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<&Box<Bin>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into()),
    };
    match engines::get_bin_by_name(service) {
      Some(engine) => Ok(engine),
      None => Err(format!("unknown service \"{}\"", service).into()),
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = some_or_err!(path.to_str(), "file name was not valid unicode".into());
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => return Err(format!("could not open {}: {}", name, e).into()),
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = some_or_err!(path.file_name(), "not a valid file name".into());
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      }
      Err(s) => Err(s),
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if message.is_some() {
      vec![PasteFile::new(String::from("message"), message.clone().unwrap())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes =
        results.iter().cloned().map(|r| r.unwrap()).filter(|p| !p.data.trim().is_empty()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    if paste_files.iter().filter(|p| !p.data.trim().is_empty()).count() < 1 {
      return Err("no files (or all empty files) to paste".into());
    }
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let parts = name.rsplit('.');
        let (beginning, end) = if parts.clone().count() > 1 {
          let mut beginning_parts = parts.clone().skip(1).collect::<Vec<_>>();
          beginning_parts.reverse();
          let beginning = beginning_parts.join(".");
          let end = parts.take(1).next().map_or(String::new(), |s| String::from(".") + s);
          (beginning, end)
        } else {
          (name.clone(), String::from(""))
        };
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}{}", beginning, number, end);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }

  fn get_engine_for_url<'a>(&'a self, url: &'a Url) -> Result<&Box<Bin>> {
    let domain = some_or_err!(url.domain(), "input url had no domain".into());
    let engine = some_or_err!(engines::get_bin_by_domain(domain),
                              format!("could not find a bin for domain {}", domain).into());
    Ok(engine)
  }

  fn get_raw(&self, url_string: &str) -> Result<String> {
    let url = try!(network::parse_url(url_string.as_ref()));
    let url_clone = url.clone();
    let bin = try!(self.get_engine_for_url(&url_clone));
    let files = try!(bin.produce_raw_contents(self, &url));
    Ok(files.join())
  }

  pub fn get_output(&self) -> Result<String> {
    if let Some(ref input) = self.arguments.input {
      return self.get_raw(input);
    }
    let to_paste = try!(self.get_to_paste());
    let engine = try!(self.get_engine());
    let upload_url = if to_paste.len() > 1 {
      try!(engine.upload_all(self, to_paste))
    } else if to_paste.len() == 1 {
      let file = &to_paste[0];
      try!(engine.upload_paste(self, file.clone())) // FIXME: shouldn't have to use clone
    } else {
      return Err("no files to upload".into());
    };
    Ok(upload_url.as_str().to_owned())
  }
}

#[derive(Clone)]
pub struct FlexibleRange {
  pub ranges: Vec<Range<usize>>
}

impl FlexibleRange {
  pub fn parse<S: Into<String>>(string: S) -> Result<FlexibleRange> {
    let string = string.into();
    let parts = string.split(',').map(|s| s.trim());
    let mut range: Vec<Range<usize>> = Vec::new();
    for part in parts {
      let bounds = part.split('-').map(|s| s.trim()).collect::<Vec<_>>();
      match bounds.len() {
        1 => {
          let num = bounds[0];
          if num.is_empty() {
            return Err("empty part in range".into());
          }
          let num = try!(num.parse::<usize>());
          range.push(num..num + 1);
        }
        2 => {
          let lower = bounds[0];
          let upper = bounds[1];
          if lower.is_empty() || upper.is_empty() {
            return Err("incomplete part in range".into());
          }
          let lower: usize = try!(lower.parse());
          let upper: usize = try!(upper.parse());
          let r: Range<usize> = if lower > upper {
            lower + 1..upper
          } else {
            lower..upper + 1
          };
          range.push(r);
        }
        _ => return Err("too many dashes in range".into())
      }
    }
    Ok(FlexibleRange { ranges: range })
  }
}

impl Iterator for FlexibleRange {
  type Item = usize;

  fn next(&mut self) -> Option<Self::Item> {
    if self.ranges.len() < 1 {
      return None;
    }
    let n = {
      let mut range = &mut self.ranges[0];
      if range.start > range.end {
        let normalized = range.end..range.start;
        let ret = normalized.rev().next();
        if ret.is_some() {
          range.start -= 1;
        }
        ret
      } else {
        range.next()
      }
    };
    if n.is_none() {
      self.ranges.remove(0);
      return self.next();
    }
    n
  }
}
<commit_msg>fix: don't clone file<commit_after>#[macro_use]
pub mod macros;
pub mod arguments;
pub mod configuration;
pub mod engines;
pub mod error;
pub mod network;

extern crate std;
extern crate toml;

use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Bin;
use hyper::Url;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::ops::Range;
use std::path::Path;
use toml::Value;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile {
      name: name,
      data: data
    }
  }
}

trait Join {
  fn join(&self) -> String;
}

impl Join for Vec<PasteFile> {
  fn join(&self) -> String {
    if self.len() == 1 {
      self.get(0).expect("len() == 1, but no first element").data.clone()
    } else {
      self.into_iter().map(|p| format!("--- {} ---\n\n{}", p.name, p.data)).collect::<Vec<String>>().join("\n\n")
    }
  }
}

pub struct Bins {
  pub config: Value,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Value, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<&Box<Bin>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into()),
    };
    match engines::get_bin_by_name(service) {
      Some(engine) => Ok(engine),
      None => Err(format!("unknown service \"{}\"", service).into()),
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = some_or_err!(path.to_str(), "file name was not valid unicode".into());
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => return Err(format!("could not open {}: {}", name, e).into()),
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = some_or_err!(path.file_name(), "not a valid file name".into());
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      }
      Err(s) => Err(s),
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if message.is_some() {
      vec![PasteFile::new(String::from("message"), message.clone().unwrap())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes =
        results.iter().cloned().map(|r| r.unwrap()).filter(|p| !p.data.trim().is_empty()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    if paste_files.iter().filter(|p| !p.data.trim().is_empty()).count() < 1 {
      return Err("no files (or all empty files) to paste".into());
    }
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let parts = name.rsplit('.');
        let (beginning, end) = if parts.clone().count() > 1 {
          let mut beginning_parts = parts.clone().skip(1).collect::<Vec<_>>();
          beginning_parts.reverse();
          let beginning = beginning_parts.join(".");
          let end = parts.take(1).next().map_or(String::new(), |s| String::from(".") + s);
          (beginning, end)
        } else {
          (name.clone(), String::from(""))
        };
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}{}", beginning, number, end);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }

  fn get_engine_for_url<'a>(&'a self, url: &'a Url) -> Result<&Box<Bin>> {
    let domain = some_or_err!(url.domain(), "input url had no domain".into());
    let engine = some_or_err!(engines::get_bin_by_domain(domain),
                              format!("could not find a bin for domain {}", domain).into());
    Ok(engine)
  }

  fn get_raw(&self, url_string: &str) -> Result<String> {
    let url = try!(network::parse_url(url_string.as_ref()));
    let url_clone = url.clone();
    let bin = try!(self.get_engine_for_url(&url_clone));
    let files = try!(bin.produce_raw_contents(self, &url));
    Ok(files.join())
  }

  pub fn get_output(&self) -> Result<String> {
    if let Some(ref input) = self.arguments.input {
      return self.get_raw(input);
    }
    let mut to_paste = try!(self.get_to_paste());
    let engine = try!(self.get_engine());
    let upload_url = if to_paste.len() > 1 {
      try!(engine.upload_all(self, to_paste))
    } else if to_paste.len() == 1 {
      let file = to_paste.pop().expect("len() == 1 but no element from pop()");
      try!(engine.upload_paste(self, file))
    } else {
      return Err("no files to upload".into());
    };
    Ok(upload_url.as_str().to_owned())
  }
}

#[derive(Clone)]
pub struct FlexibleRange {
  pub ranges: Vec<Range<usize>>
}

impl FlexibleRange {
  pub fn parse<S: Into<String>>(string: S) -> Result<FlexibleRange> {
    let string = string.into();
    let parts = string.split(',').map(|s| s.trim());
    let mut range: Vec<Range<usize>> = Vec::new();
    for part in parts {
      let bounds = part.split('-').map(|s| s.trim()).collect::<Vec<_>>();
      match bounds.len() {
        1 => {
          let num = bounds[0];
          if num.is_empty() {
            return Err("empty part in range".into());
          }
          let num = try!(num.parse::<usize>());
          range.push(num..num + 1);
        }
        2 => {
          let lower = bounds[0];
          let upper = bounds[1];
          if lower.is_empty() || upper.is_empty() {
            return Err("incomplete part in range".into());
          }
          let lower: usize = try!(lower.parse());
          let upper: usize = try!(upper.parse());
          let r: Range<usize> = if lower > upper {
            lower + 1..upper
          } else {
            lower..upper + 1
          };
          range.push(r);
        }
        _ => return Err("too many dashes in range".into())
      }
    }
    Ok(FlexibleRange { ranges: range })
  }
}

impl Iterator for FlexibleRange {
  type Item = usize;

  fn next(&mut self) -> Option<Self::Item> {
    if self.ranges.len() < 1 {
      return None;
    }
    let n = {
      let mut range = &mut self.ranges[0];
      if range.start > range.end {
        let normalized = range.end..range.start;
        let ret = normalized.rev().next();
        if ret.is_some() {
          range.start -= 1;
        }
        ret
      } else {
        range.next()
      }
    };
    if n.is_none() {
      self.ranges.remove(0);
      return self.next();
    }
    n
  }
}
<|endoftext|>


<commit_before>use std::result::Result;
use std::ops::{Index, IndexMut};
use std::collections::HashMap;
use std::hash::Hash;
use std::any::Any;

//import and reexport dyn_property
use super::dyn_property::DynProperty;

/// zero sized type used as "is undefined" marker
pub struct UndefinedProperty;

pub fn undefined_property() -> DynProperty {
    //pointer to zero sized Type -> any non zero pointer is ok (test shows it uses 0x1) so no
    //allocation on heap is done
    DynProperty::new(Box::new(UndefinedProperty))
}

pub struct InnerDynObject<Key> {
    //initialise this allways with DynProperty::undefined();
    //FIXME move this as assoziated Konstant (with unsave) or static
    undefined_property: DynProperty,
    data: HashMap<Key, DynProperty>
}

/// The inner part of DynamicObject witch contains the data
///
/// This Trait provids a way to create, add, remove and
/// modify typed propertys defined by a given Key
///
impl<Key> InnerDynObject<Key> where Key: Eq + Hash {

    /// Creates a new empty InnerDynObject
    ///
    pub fn new() -> InnerDynObject<Key> {
        InnerDynObject {
            undefined_property: undefined_property(),
            data: HashMap::<Key, DynProperty>::new()
        }
    }

    /// sets the property defined by key
    ///
    /// If the property identified by key exists and the property has the type given by
    /// `T` this methode will set the value as new value and will return the old value
    /// as Ok(Box(T)). If the property does not exists or the type is wrong the passed
    /// value will be returned as Err(Box(T))
    ///
    /// This is mostly equivalent to using  `inner_dyn_object[key].set(value)`
    ///
    /// # Example
    ///
    #[unstable(reason="redundant, might be removed")]
    #[inline]
    pub fn set_property<T>(&mut self, key: &Key, value: Box<T>) -> Result<Box<T>,Box<T>>
        where T: Any + 'static
    {
        self.index_mut(key).set(value)
    }

    /// create a new property with a initial value
    ///
    /// Creaates a new property with given key and `initial_value setting` the type of
    /// the property to the type of `initial_value`. If the property already exists
    /// the given initialvalue will be returned as `Err(Box(T))` else `Ok( () )` will
    /// be returned.
    ///
    pub fn create_property<T>(&mut self, key: Key, init_value: Box<T>) -> Result<(),Box<T>>
        where T: Any + 'static
    {
        if self.data.contains_key(&key) {
            Err(init_value)
        } else {
            self.data.insert(key, DynProperty::new(init_value));
            Ok( () )
        }
    }

    /// removes a given property returning the old value of it
    ///
    /// If the property exists and the type match the old
    /// value will eb returned wraped in a Ok-Result and the
    /// property is removed. Else the property won't be changed
    /// and `Err( () )`. If you e.g. try to remove a given property
    /// not the using the right type the property will NOT be removed.
    ///
    pub fn remove_property<T>(&mut self, key: &Key) -> Result<Box<T>, ()>
        where T: Any + 'static
    {
        if !self.index(key).is_inner_type::<T>() {
            return Err( () );
        }
        Ok(self.data.remove(key).unwrap().destruct::<T>().unwrap())
    }

    /// returns true if a given property exists
    pub fn exists_property(&self, key: &Key) -> bool {
        self.data.contains_key(key)
    }

    /// returns true if a given property exists and has the given type
    pub fn exists_property_with_type<T>(&self, key: &Key) -> bool
        where T: Any + 'static
    {
        self.index(key).is_inner_type::<T>()
    }

    //TODO add remove_typeles to remove without knowing the type returning Box<Any>
}

impl<Key: Hash+Eq> Index<Key> for InnerDynObject<Key> {
    type Output = DynProperty;

    /// return a reference to a `DynProperty` for a given key
    ///
    /// If the key exists in this `InnerDynObject` a reference to
    /// the associated property will be returned. If not a reference to
    /// a property with the inner type `UndefinedProperty` will be returned.
    ///
    fn index<'a>(&'a self, index: &Key) -> &'a DynProperty {
        match self.data.get(index) {
            Some(data) => data,
            None => &self.undefined_property
        }
    }
}

impl<Key: Hash+Eq> IndexMut<Key> for InnerDynObject<Key> {

    /// return a mutable referenc to a `DynProperty` for a given key
    ///
    /// If the key exists in this `InnerDynObject` a reference to
    /// the associated property will be returned. If not a reference to
    /// a property with the inner type `UndefinedProperty` will be returned.
    ///
    /// Note: that it is not a problem to return a mutable reference to a UndefinedProperty
    /// because UndefinedProperty is a zero sized type and therfor has only one representation.
    ///
    fn index_mut<'a>(&'a mut self, index: &Key) -> &'a mut DynProperty {
        match self.data.get_mut(index) {
            Some(data) => data,
            None => &mut self.undefined_property
        }
    }
}

#[cfg(test)]
mod test {
    use super::InnerDynObject;
    use super::UndefinedProperty;
    use super::undefined_property;

    fn create_dummy() -> InnerDynObject<&'static str> {
        InnerDynObject::<&'static str>::new()
    }

    #[test]
    fn exist_property_should_return_false_if_inexisting() {
        let obj = create_dummy();
        assert!( !obj.exists_property(&"hallo") );
    }

    #[test]
    fn after_creating_a_property_should_exist() {
        let mut obj = create_dummy();
        assert!(obj.create_property("hallo", Box::new(23i32)).is_ok());
        assert!(obj.exists_property(&"hallo"));
    }

    #[test]
    fn exist_property_with_type_should_return_true_if_property_exists_and_has_given_type() {
        let mut obj = create_dummy();
        assert!(obj.create_property("hallo", Box::new(23i32)).is_ok());
        assert!(obj.exists_property_with_type::<i32>(&"hallo"));
    }

    #[test]
    fn exists_property_with_type_should_return_false_if_property_is_undefined() {
        let mut obj = create_dummy();
        assert!(obj.create_property("hallo", Box::new(23i32)).is_ok());
        assert!(!obj.exists_property_with_type::<i32>(&"NOThallo"));
    }

    #[test]
    fn exists_property_with_type_should_return_fals_if_the_type_mismatches() {
        let mut obj = create_dummy();
        assert!(obj.create_property("hallo", Box::new(23i32)).is_ok());
        assert!(!obj.exists_property_with_type::<u16>(&"hallo"));
    }

    #[test]
    fn create_property_should_return_true_if_key_is_new() {
        let mut obj = create_dummy();
        assert!(obj.create_property("hallo", Box::new(23i32)).is_ok());
    }

    #[test]
    fn create_property_should_return_false_if_key_already_exists() {
        let mut obj = create_dummy();
        assert!(  obj.create_property("hallo", Box::new(23i32)).is_ok());
        assert!( !obj.create_property("hallo", Box::new(20i32)).is_ok());

    }

    #[test]
    fn set_property_should_err_if_property_does_not_exist() {
        let mut obj = create_dummy();
        assert!( !obj.exists_property(&"hallo") );
        let res = obj.set_property(&"hallo", Box::new(44i32));
        assert_eq!(res, Err(Box::new(44i32)));
    }

    #[test]
    fn set_property_should_err_if_property_type_is_wrong() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        let res = obj.set_property(&"hallo", Box::new("oh falsch"));
        assert_eq!(res, Err(Box::new("oh falsch")));
    }

    #[test]
    fn set_property_should_return_the_old_value_if_property_exists_and_type_matches() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        let res = obj.set_property(&"hallo", Box::new(44i32));
        assert_eq!(res, Ok(Box::new(23i32)));
        //obj["hallo"] expands to obj.index(&"hallo")
        assert_eq!(obj["hallo"].as_ref::<i32>().unwrap(), &44i32);
    }

    #[test]
    fn remove_property_should_fail_if_property_does_not_exists() {
        let mut obj = create_dummy();
        let res = obj.remove_property::<i32>(&"hallo");
        assert_eq!(res, Err( () ));
    }

    #[test]
    fn remove_property_should_fail_if_the_type_mismatches() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        let res = obj.remove_property::<u16>(&"hallo");
        assert_eq!(res, Err( () ));
        assert!(obj.exists_property(&"hallo"));
    }

    #[test]
    fn remove_property_should_return_the_property_value_if_succesful() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        let res = obj.remove_property::<i32>(&"hallo");
        assert_eq!(res, Ok(Box::new(23i32)));
    }

    //TODO test index
    #[test]
    fn index_should_return_the_property_if_existing() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        let ref res = obj["hallo"];
        assert!(res.is_inner_type::<i32>());
        match res.as_ref::<i32>() {
            Some(ref_val) => assert_eq!(ref_val, &23i32),
            None => panic!("expected to be borrowable in this situration")
        }
    }

    #[test]
    fn index_should_return_a_property_of_type_undefined_if_inexisting() {
        let obj = create_dummy();
        assert!(obj["hallo"].is_inner_type::<UndefinedProperty>());
    }

    #[test]
    fn index_should_also_allow_mutable_access() {
        let mut obj = create_dummy();
        assert!( obj.create_property("hallo", Box::new(23i32)).is_ok());
        match obj["hallo"].as_mut::<i32>() {
            Some(ref_val) => {
                let mut dummy = 23i32;
                assert_eq!(ref_val, &mut dummy)
            }
            None => panic!("expected to be borrowable in this situration")
        }
    }

    #[test]
    fn undefined_property_should_return_a_property_of_the_undefined_property_type() {
        let x = undefined_property();
        assert!(x.is_inner_type::<UndefinedProperty>());
    }
}
<commit_msg>fixed inner spacing in inner_dyn_object<commit_after>use std::result::Result;
use std::ops::{Index, IndexMut};
use std::collections::HashMap;
use std::hash::Hash;
use std::any::Any;

//import and reexport dyn_property
use super::dyn_property::DynProperty;

/// zero sized type used as "is undefined" marker
pub struct UndefinedProperty;

pub fn undefined_property() -> DynProperty {
    //pointer to zero sized Type -> any non zero pointer is ok ( test shows it uses 0x1 ) so no
    //allocation on heap is done
    DynProperty::new( Box::new( UndefinedProperty ))
}

pub struct InnerDynObject<Key> {
    //initialise this allways with DynProperty::undefined();
    //FIXME move this as assoziated Konstant ( with unsave ) or static
    undefined_property: DynProperty,
    data: HashMap<Key, DynProperty>
}

/// The inner part of DynamicObject witch contains the data
///
/// This Trait provids a way to create, add, remove and
/// modify typed propertys defined by a given Key
///
impl<Key> InnerDynObject<Key> where Key: Eq + Hash {

    /// Creates a new empty InnerDynObject
    ///
    pub fn new() -> InnerDynObject<Key> {
        InnerDynObject {
            undefined_property: undefined_property(),
            data: HashMap::<Key, DynProperty>::new()
        }
    }

    /// sets the property defined by key
    ///
    /// If the property identified by key exists and the property has the type given by
    /// `T` this methode will set the value as new value and will return the old value
    /// as Ok( Box( T )). If the property does not exists or the type is wrong the passed
    /// value will be returned as Err( Box( T ))
    ///
    /// This is mostly equivalent to using  `inner_dyn_object[key].set( value )`
    ///
    /// # Example
    ///
    #[unstable( reason="redundant, might be removed" )]
    #[inline]
    pub fn set_property<T>( &mut self, key: &Key, value: Box<T> ) -> Result<Box<T>,Box<T>>
        where T: Any + 'static
    {
        self.index_mut( key ).set( value )
    }

    /// create a new property with a initial value
    ///
    /// Creaates a new property with given key and `initial_value setting` the type of
    /// the property to the type of `initial_value`. If the property already exists
    /// the given initialvalue will be returned as `Err( Box( T ))` else `Ok( () )` will
    /// be returned.
    ///
    pub fn create_property<T>( &mut self, key: Key, init_value: Box<T> ) -> Result<(),Box<T>>
        where T: Any + 'static
    {
        if self.data.contains_key( &key ) {
            Err( init_value )
        } else {
            self.data.insert( key, DynProperty::new( init_value ));
            Ok( () )
        }
    }

    /// removes a given property returning the old value of it
    ///
    /// If the property exists and the type match the old
    /// value will eb returned wraped in a Ok-Result and the
    /// property is removed. Else the property won't be changed
    /// and `Err( () )`. If you e.g. try to remove a given property
    /// not the using the right type the property will NOT be removed.
    ///
    pub fn remove_property<T>( &mut self, key: &Key ) -> Result<Box<T>, ()>
        where T: Any + 'static
    {
        if !self.index( key ).is_inner_type::<T>() {
            return Err( () );
        }
        Ok( self.data.remove( key ).unwrap().destruct::<T>().unwrap() )
    }

    /// returns true if a given property exists
    pub fn exists_property( &self, key: &Key ) -> bool {
        self.data.contains_key( key )
    }

    /// returns true if a given property exists and has the given type
    pub fn exists_property_with_type<T>( &self, key: &Key ) -> bool
        where T: Any + 'static
    {
        self.index( key ).is_inner_type::<T>()
    }

    //TODO add remove_typeles to remove without knowing the type returning Box<Any>
}

impl<Key: Hash+Eq> Index<Key> for InnerDynObject<Key> {
    type Output = DynProperty;

    /// return a reference to a `DynProperty` for a given key
    ///
    /// If the key exists in this `InnerDynObject` a reference to
    /// the associated property will be returned. If not a reference to
    /// a property with the inner type `UndefinedProperty` will be returned.
    ///
    fn index<'a>( &'a self, index: &Key ) -> &'a DynProperty {
        match self.data.get( index ) {
            Some( data ) => data,
            None => &self.undefined_property
        }
    }
}

impl<Key: Hash+Eq> IndexMut<Key> for InnerDynObject<Key> {

    /// return a mutable referenc to a `DynProperty` for a given key
    ///
    /// If the key exists in this `InnerDynObject` a reference to
    /// the associated property will be returned. If not a reference to
    /// a property with the inner type `UndefinedProperty` will be returned.
    ///
    /// Note: that it is not a problem to return a mutable reference to a UndefinedProperty
    /// because UndefinedProperty is a zero sized type and therfor has only one representation.
    ///
    fn index_mut<'a>( &'a mut self, index: &Key ) -> &'a mut DynProperty {
        match self.data.get_mut( index ) {
            Some( data ) => data,
            None => &mut self.undefined_property
        }
    }
}

#[cfg( test )]
mod test {
    use super::InnerDynObject;
    use super::UndefinedProperty;
    use super::undefined_property;

    fn create_dummy() -> InnerDynObject<&'static str> {
        InnerDynObject::<&'static str>::new()
    }

    #[test]
    fn exist_property_should_return_false_if_inexisting() {
        let obj = create_dummy();
        assert!( !obj.exists_property( &"hallo" ) );
    }

    #[test]
    fn after_creating_a_property_should_exist() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        assert!( obj.exists_property( &"hallo" ));
    }

    #[test]
    fn exist_property_with_type_should_return_true_if_property_exists_and_has_given_type() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        assert!( obj.exists_property_with_type::<i32>( &"hallo" ));
    }

    #[test]
    fn exists_property_with_type_should_return_false_if_property_is_undefined() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        assert!( !obj.exists_property_with_type::<i32>( &"NOThallo" ));
    }

    #[test]
    fn exists_property_with_type_should_return_fals_if_the_type_mismatches() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        assert!( !obj.exists_property_with_type::<u16>( &"hallo" ));
    }

    #[test]
    fn create_property_should_return_true_if_key_is_new() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
    }

    #[test]
    fn create_property_should_return_false_if_key_already_exists() {
        let mut obj = create_dummy();
        assert!(  obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        assert!( !obj.create_property( "hallo", Box::new( 20i32 )).is_ok() );

    }

    #[test]
    fn set_property_should_err_if_property_does_not_exist() {
        let mut obj = create_dummy();
        assert!( !obj.exists_property( &"hallo" ) );
        let res = obj.set_property( &"hallo", Box::new( 44i32 ));
        assert_eq!( res, Err( Box::new( 44i32 )) );
    }

    #[test]
    fn set_property_should_err_if_property_type_is_wrong() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        let res = obj.set_property( &"hallo", Box::new( "oh falsch" ));
        assert_eq!( res, Err( Box::new( "oh falsch" )) );
    }

    #[test]
    fn set_property_should_return_the_old_value_if_property_exists_and_type_matches() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        let res = obj.set_property( &"hallo", Box::new( 44i32 ));
        assert_eq!( res, Ok( Box::new( 23i32 )) );
        //obj["hallo"] expands to obj.index( &"hallo" )
        assert_eq!( obj["hallo"].as_ref::<i32>().unwrap(), &44i32 );
    }

    #[test]
    fn remove_property_should_fail_if_property_does_not_exists() {
        let mut obj = create_dummy();
        let res = obj.remove_property::<i32>( &"hallo" );
        assert_eq!( res, Err( () ) );
    }

    #[test]
    fn remove_property_should_fail_if_the_type_mismatches() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        let res = obj.remove_property::<u16>( &"hallo" );
        assert_eq!( res, Err( () ) );
        assert!( obj.exists_property( &"hallo" ));
    }

    #[test]
    fn remove_property_should_return_the_property_value_if_succesful() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        let res = obj.remove_property::<i32>( &"hallo" );
        assert_eq!( res, Ok( Box::new( 23i32 )) );
    }

    //TODO test index
    #[test]
    fn index_should_return_the_property_if_existing() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        let ref res = obj["hallo"];
        assert!( res.is_inner_type::<i32>() );
        match res.as_ref::<i32>() {
            Some( ref_val ) => assert_eq!( ref_val, &23i32 ),
            None => panic!( "expected to be borrowable in this situration" )
        }
    }

    #[test]
    fn index_should_return_a_property_of_type_undefined_if_inexisting() {
        let obj = create_dummy();
        assert!( obj["hallo"].is_inner_type::<UndefinedProperty>() );
    }

    #[test]
    fn index_should_also_allow_mutable_access() {
        let mut obj = create_dummy();
        assert!( obj.create_property( "hallo", Box::new( 23i32 )).is_ok() );
        match obj["hallo"].as_mut::<i32>() {
            Some( ref_val ) => {
                let mut dummy = 23i32;
                assert_eq!( ref_val, &mut dummy )
            }
            None => panic!( "expected to be borrowable in this situration" )
        }
    }

    #[test]
    fn undefined_property_should_return_a_property_of_the_undefined_property_type() {
        let x = undefined_property();
        assert!( x.is_inner_type::<UndefinedProperty>() );
    }
}
<|endoftext|>


<commit_before>use std::cast;
use std::c_str::CString;
use std::i32;
use std::libc::*;
use std::num::Zero;
use std::ptr;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::events::*;

use ffi::*;

pub use self::display_flag::*;
pub use rust_util::c_bool;

pub mod external
{
	pub use super::display_flag::*;
	pub use super::{Display, DisplayOption, DisplayOptionImportance, DisplayOrientation, DisplayOptions};
}

flag_type!(
	mod display_flag
	{
		DisplayFlags
		{
			WINDOWED                  = ALLEGRO_WINDOWED,
			FULLSCREEN                = ALLEGRO_FULLSCREEN,
			OPENGL                    = ALLEGRO_OPENGL,
			DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
			RESIZABLE                 = ALLEGRO_RESIZABLE,
			FRAMELESS                 = ALLEGRO_FRAMELESS,
			GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
			OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
			OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
			FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
			MINIMIZED                 = ALLEGRO_MINIMIZED
		}
	}
)

pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct DisplayOptions<'m>
{
	flags: DisplayFlags,
	refresh_rate: Option<i32>,
	adapter: Option<i32>,
	window_position: Option<[i32, ..2]>,
	options: Option<&'m [(DisplayOption, i32, DisplayOptionImportance)]>
}

impl<'m> DisplayOptions<'m>
{
	pub fn new() -> DisplayOptions
	{
		DisplayOptions{ flags: Zero::zero(), refresh_rate: None, adapter: None, window_position: None, options: None }
	}
}

pub struct Display
{
	priv allegro_display: *mut ALLEGRO_DISPLAY,
	priv backbuffer: Bitmap,
	priv event_source: EventSource
}

impl Display
{
	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			cast::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			cast::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> bool
	{
		unsafe
		{
			al_acknowledge_resize(self.allegro_display) != 0
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> bool
	{
		unsafe
		{
			al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<T: BitmapLike, U: Iterator<T>>(&self, icons: U)
	{
		let mut c_icons = icons.map(|ref b| b.get_bitmap()).to_owned_vec();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			title.with_ref(|c_str|
			{
				al_set_window_title(self.allegro_display, c_str);
			});
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn clone_convert<T: BitmapLike>(&self, bmp: &T) -> Option<Bitmap>
	{
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&'l self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}
}

impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_display(self.allegro_display);
		}
	}
}

fn new_display(w: i32, h: i32) -> Option<Display>
{
	unsafe
	{
		let d = al_create_display(w as c_int, h as c_int);
		if ptr::is_null(d)
		{
			None
		}
		else
		{
			Some(Display{ allegro_display: d, backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
			              event_source: new_event_source_ref(al_get_display_event_source(d)) })
		}
	}
}

fn new_display_with_options(w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
{
	unsafe
	{
		al_set_new_display_flags(opt.flags.get() as c_int);

		match opt.refresh_rate
		{
			Some(r) => al_set_new_display_refresh_rate(r as c_int),
			None => al_set_new_display_refresh_rate(0)
		}

		match opt.adapter
		{
			Some(a) => al_set_new_display_adapter(a as c_int),
			None => al_set_new_display_adapter(ALLEGRO_DEFAULT_DISPLAY_ADAPTER),
		}

		match opt.window_position
		{
			Some([x, y]) =>	al_set_new_window_position(x as c_int, y as c_int),
			None =>	al_set_new_window_position(i32::max_value, i32::max_value)
		}

		al_reset_new_display_options();

		match opt.options
		{
			Some(options) =>
			{
				for &(option, value, importance) in options.iter()
				{
					al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
				}
			},
			None => ()
		}
	}

	new_display(w, h)
}

impl ::internal::core::Core
{
	pub fn create_display(&self, w: i32, h: i32) -> Option<Display>
	{
		new_display(w, h)
	}

	pub fn create_display_with_options(&self, w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
	{
		new_display_with_options(w, h, opt)
	}

	pub fn flip_display(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_display_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> bool
	{
		unsafe
		{
			al_wait_for_vsync() != 0
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}
<commit_msg>Move the display creation into the Display struct<commit_after>use std::cast;
use std::c_str::CString;
use std::i32;
use std::libc::*;
use std::num::Zero;
use std::ptr;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::events::*;

use ffi::*;

pub use self::display_flag::*;
pub use rust_util::c_bool;

pub mod external
{
	pub use super::display_flag::*;
	pub use super::{Display, DisplayOption, DisplayOptionImportance, DisplayOrientation, DisplayOptions};
}

flag_type!(
	mod display_flag
	{
		DisplayFlags
		{
			WINDOWED                  = ALLEGRO_WINDOWED,
			FULLSCREEN                = ALLEGRO_FULLSCREEN,
			OPENGL                    = ALLEGRO_OPENGL,
			DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
			RESIZABLE                 = ALLEGRO_RESIZABLE,
			FRAMELESS                 = ALLEGRO_FRAMELESS,
			GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
			OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
			OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
			FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
			MINIMIZED                 = ALLEGRO_MINIMIZED
		}
	}
)

pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct DisplayOptions<'m>
{
	flags: DisplayFlags,
	refresh_rate: Option<i32>,
	adapter: Option<i32>,
	window_position: Option<[i32, ..2]>,
	options: Option<&'m [(DisplayOption, i32, DisplayOptionImportance)]>
}

impl<'m> DisplayOptions<'m>
{
	pub fn new() -> DisplayOptions
	{
		DisplayOptions{ flags: Zero::zero(), refresh_rate: None, adapter: None, window_position: None, options: None }
	}
}

pub struct Display
{
	priv allegro_display: *mut ALLEGRO_DISPLAY,
	priv backbuffer: Bitmap,
	priv event_source: EventSource
}

impl Display
{
	fn new(w: i32, h: i32) -> Option<Display>
	{
		unsafe
		{
			let d = al_create_display(w as c_int, h as c_int);
			if ptr::is_null(d)
			{
				None
			}
			else
			{
				Some(Display{ allegro_display: d, backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							  event_source: new_event_source_ref(al_get_display_event_source(d)) })
			}
		}
	}

	fn new_with_options(w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
	{
		unsafe
		{
			al_set_new_display_flags(opt.flags.get() as c_int);

			match opt.refresh_rate
			{
				Some(r) => al_set_new_display_refresh_rate(r as c_int),
				None => al_set_new_display_refresh_rate(0)
			}

			match opt.adapter
			{
				Some(a) => al_set_new_display_adapter(a as c_int),
				None => al_set_new_display_adapter(ALLEGRO_DEFAULT_DISPLAY_ADAPTER),
			}

			match opt.window_position
			{
				Some([x, y]) =>	al_set_new_window_position(x as c_int, y as c_int),
				None =>	al_set_new_window_position(i32::max_value, i32::max_value)
			}

			al_reset_new_display_options();

			match opt.options
			{
				Some(options) =>
				{
					for &(option, value, importance) in options.iter()
					{
						al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
					}
				},
				None => ()
			}
		}

		Display::new(w, h)
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			cast::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			cast::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> bool
	{
		unsafe
		{
			al_acknowledge_resize(self.allegro_display) != 0
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> bool
	{
		unsafe
		{
			al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<T: BitmapLike, U: Iterator<T>>(&self, icons: U)
	{
		let mut c_icons = icons.map(|ref b| b.get_bitmap()).to_owned_vec();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			title.with_ref(|c_str|
			{
				al_set_window_title(self.allegro_display, c_str);
			});
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn clone_convert<T: BitmapLike>(&self, bmp: &T) -> Option<Bitmap>
	{
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&'l self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}
}

impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			al_destroy_display(self.allegro_display);
		}
	}
}

impl ::internal::core::Core
{
	pub fn create_display(&self, w: i32, h: i32) -> Option<Display>
	{
		Display::new(w, h)
	}

	pub fn create_display_with_options(&self, w: i32, h: i32, opt: &DisplayOptions) -> Option<Display>
	{
		Display::new_with_options(w, h, opt)
	}

	pub fn flip_display(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_display_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> bool
	{
		unsafe
		{
			al_wait_for_vsync() != 0
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

/*!
 * Methods for the various MIR types. These are intended for use after
 * building is complete.
 */

use mir::repr::*;
use ty::subst::{Subst, Substs};
use ty::{self, AdtDef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use hir;

#[derive(Copy, Clone, Debug)]
pub enum LvalueTy<'tcx> {
    /// Normal type.
    Ty { ty: Ty<'tcx> },

    /// Downcast to a particular variant of an enum.
    Downcast { adt_def: AdtDef<'tcx>,
               substs: &'tcx Substs<'tcx>,
               variant_index: usize },
}

impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
    pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
        LvalueTy::Ty { ty: ty }
    }

    pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
        match *self {
            LvalueTy::Ty { ty } =>
                ty,
            LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
                tcx.mk_enum(adt_def, substs),
        }
    }

    pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         elem: &LvalueElem<'tcx>)
                         -> LvalueTy<'tcx>
    {
        match *elem {
            ProjectionElem::Deref =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
                                          .unwrap()
                                          .ty
                },
            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_index().unwrap()
                },
            ProjectionElem::Subslice { from, to } => {
                let ty = self.to_ty(tcx);
                LvalueTy::Ty {
                    ty: match ty.sty {
                        ty::TyArray(inner, size) => {
                            tcx.mk_array(inner, size-(from as usize)-(to as usize))
                        }
                        ty::TySlice(..) => ty,
                        _ => {
                            bug!("cannot subslice non-array type: `{:?}`", self)
                        }
                    }
                }
            }
            ProjectionElem::Downcast(adt_def1, index) =>
                match self.to_ty(tcx).sty {
                    ty::TyEnum(adt_def, substs) => {
                        assert!(index < adt_def.variants.len());
                        assert_eq!(adt_def, adt_def1);
                        LvalueTy::Downcast { adt_def: adt_def,
                                             substs: substs,
                                             variant_index: index }
                    }
                    _ => {
                        bug!("cannot downcast non-enum type: `{:?}`", self)
                    }
                },
            ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        match *self {
            LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.fold_with(folder) },
            LvalueTy::Downcast { adt_def, substs, variant_index } => {
                LvalueTy::Downcast {
                    adt_def: adt_def,
                    substs: substs.fold_with(folder),
                    variant_index: variant_index
                }
            }
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        match *self {
            LvalueTy::Ty { ty } => ty.visit_with(visitor),
            LvalueTy::Downcast { substs, .. } => substs.visit_with(visitor)
        }
    }
}

impl<'tcx> Lvalue<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
        match self {
            &Lvalue::Var(index) =>
                LvalueTy::Ty { ty: mir.var_decls[index].ty },
            &Lvalue::Temp(index) =>
                LvalueTy::Ty { ty: mir.temp_decls[index].ty },
            &Lvalue::Arg(index) =>
                LvalueTy::Ty { ty: mir.arg_decls[index].ty },
            &Lvalue::Static(def_id) =>
                LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
            &Lvalue::ReturnPointer =>
                LvalueTy::Ty { ty: mir.return_ty.unwrap() },
            &Lvalue::Projection(ref proj) =>
                proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
        }
    }
}

impl<'tcx> Rvalue<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
    {
        match self {
            &Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
            &Rvalue::Repeat(ref operand, ref count) => {
                let op_ty = operand.ty(mir, tcx);
                let count = count.value.as_u64(tcx.sess.target.uint_type);
                assert_eq!(count as usize as u64, count);
                Some(tcx.mk_array(op_ty, count as usize))
            }
            &Rvalue::Ref(reg, bk, ref lv) => {
                let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
                Some(tcx.mk_ref(
                    tcx.mk_region(reg),
                    ty::TypeAndMut {
                        ty: lv_ty,
                        mutbl: bk.to_mutbl_lossy()
                    }
                ))
            }
            &Rvalue::Len(..) => Some(tcx.types.usize),
            &Rvalue::Cast(_, _, ty) => Some(ty),
            &Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
                let lhs_ty = lhs.ty(mir, tcx);
                let rhs_ty = rhs.ty(mir, tcx);
                Some(op.ty(tcx, lhs_ty, rhs_ty))
            }
            &Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
                let lhs_ty = lhs.ty(mir, tcx);
                let rhs_ty = rhs.ty(mir, tcx);
                let ty = op.ty(tcx, lhs_ty, rhs_ty);
                let ty = tcx.mk_tup(vec![ty, tcx.types.bool]);
                Some(ty)
            }
            &Rvalue::UnaryOp(_, ref operand) => {
                Some(operand.ty(mir, tcx))
            }
            &Rvalue::Box(t) => {
                Some(tcx.mk_box(t))
            }
            &Rvalue::Aggregate(ref ak, ref ops) => {
                match *ak {
                    AggregateKind::Vec => {
                        if let Some(operand) = ops.get(0) {
                            let ty = operand.ty(mir, tcx);
                            Some(tcx.mk_array(ty, ops.len()))
                        } else {
                            None
                        }
                    }
                    AggregateKind::Tuple => {
                        Some(tcx.mk_tup(
                            ops.iter().map(|op| op.ty(mir, tcx)).collect()
                        ))
                    }
                    AggregateKind::Adt(def, _, substs) => {
                        Some(tcx.lookup_item_type(def.did).ty.subst(tcx, substs))
                    }
                    AggregateKind::Closure(did, substs) => {
                        Some(tcx.mk_closure_from_closure_substs(did, substs))
                    }
                }
            }
            &Rvalue::InlineAsm { .. } => None
        }
    }
}

impl<'tcx> Operand<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
        match self {
            &Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
            &Operand::Constant(ref c) => c.ty,
        }
    }
}

impl<'tcx> BinOp {
      pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    lhs_ty: Ty<'tcx>,
                    rhs_ty: Ty<'tcx>)
                    -> Ty<'tcx>
    {
        // FIXME: handle SIMD correctly
        match self {
            &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
            &BinOp::BitXor | &BinOp::BitAnd | &BinOp::BitOr => {
                // these should be integers or floats of the same size.
                assert_eq!(lhs_ty, rhs_ty);
                lhs_ty
            }
            &BinOp::Shl | &BinOp::Shr => {
                lhs_ty // lhs_ty can be != rhs_ty
            }
            &BinOp::Eq | &BinOp::Lt | &BinOp::Le |
            &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
                tcx.types.bool
            }
        }
    }
}

impl BorrowKind {
    pub fn to_mutbl_lossy(self) -> hir::Mutability {
        match self {
            BorrowKind::Mut => hir::MutMutable,
            BorrowKind::Shared => hir::MutImmutable,

            // We have no type corresponding to a unique imm borrow, so
            // use `&mut`. It gives all the capabilities of an `&uniq`
            // and hence is a safe "over approximation".
            BorrowKind::Unique => hir::MutMutable,
        }
    }
}

impl BinOp {
    pub fn to_hir_binop(self) -> hir::BinOp_ {
        match self {
            BinOp::Add => hir::BinOp_::BiAdd,
            BinOp::Sub => hir::BinOp_::BiSub,
            BinOp::Mul => hir::BinOp_::BiMul,
            BinOp::Div => hir::BinOp_::BiDiv,
            BinOp::Rem => hir::BinOp_::BiRem,
            BinOp::BitXor => hir::BinOp_::BiBitXor,
            BinOp::BitAnd => hir::BinOp_::BiBitAnd,
            BinOp::BitOr => hir::BinOp_::BiBitOr,
            BinOp::Shl => hir::BinOp_::BiShl,
            BinOp::Shr => hir::BinOp_::BiShr,
            BinOp::Eq => hir::BinOp_::BiEq,
            BinOp::Ne => hir::BinOp_::BiNe,
            BinOp::Lt => hir::BinOp_::BiLt,
            BinOp::Gt => hir::BinOp_::BiGt,
            BinOp::Le => hir::BinOp_::BiLe,
            BinOp::Ge => hir::BinOp_::BiGe
        }
    }
}
<commit_msg>make tidy<commit_after>// Copyright 2015 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.

/*!
 * Methods for the various MIR types. These are intended for use after
 * building is complete.
 */

use mir::repr::*;
use ty::subst::{Subst, Substs};
use ty::{self, AdtDef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use hir;

#[derive(Copy, Clone, Debug)]
pub enum LvalueTy<'tcx> {
    /// Normal type.
    Ty { ty: Ty<'tcx> },

    /// Downcast to a particular variant of an enum.
    Downcast { adt_def: AdtDef<'tcx>,
               substs: &'tcx Substs<'tcx>,
               variant_index: usize },
}

impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
    pub fn from_ty(ty: Ty<'tcx>) -> LvalueTy<'tcx> {
        LvalueTy::Ty { ty: ty }
    }

    pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
        match *self {
            LvalueTy::Ty { ty } =>
                ty,
            LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
                tcx.mk_enum(adt_def, substs),
        }
    }

    pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         elem: &LvalueElem<'tcx>)
                         -> LvalueTy<'tcx>
    {
        match *elem {
            ProjectionElem::Deref =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_deref(true, ty::LvaluePreference::NoPreference)
                                          .unwrap()
                                          .ty
                },
            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
                LvalueTy::Ty {
                    ty: self.to_ty(tcx).builtin_index().unwrap()
                },
            ProjectionElem::Subslice { from, to } => {
                let ty = self.to_ty(tcx);
                LvalueTy::Ty {
                    ty: match ty.sty {
                        ty::TyArray(inner, size) => {
                            tcx.mk_array(inner, size-(from as usize)-(to as usize))
                        }
                        ty::TySlice(..) => ty,
                        _ => {
                            bug!("cannot subslice non-array type: `{:?}`", self)
                        }
                    }
                }
            }
            ProjectionElem::Downcast(adt_def1, index) =>
                match self.to_ty(tcx).sty {
                    ty::TyEnum(adt_def, substs) => {
                        assert!(index < adt_def.variants.len());
                        assert_eq!(adt_def, adt_def1);
                        LvalueTy::Downcast { adt_def: adt_def,
                                             substs: substs,
                                             variant_index: index }
                    }
                    _ => {
                        bug!("cannot downcast non-enum type: `{:?}`", self)
                    }
                },
            ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
        }
    }
}

impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
        match *self {
            LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.fold_with(folder) },
            LvalueTy::Downcast { adt_def, substs, variant_index } => {
                LvalueTy::Downcast {
                    adt_def: adt_def,
                    substs: substs.fold_with(folder),
                    variant_index: variant_index
                }
            }
        }
    }

    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
        match *self {
            LvalueTy::Ty { ty } => ty.visit_with(visitor),
            LvalueTy::Downcast { substs, .. } => substs.visit_with(visitor)
        }
    }
}

impl<'tcx> Lvalue<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
        match self {
            &Lvalue::Var(index) =>
                LvalueTy::Ty { ty: mir.var_decls[index].ty },
            &Lvalue::Temp(index) =>
                LvalueTy::Ty { ty: mir.temp_decls[index].ty },
            &Lvalue::Arg(index) =>
                LvalueTy::Ty { ty: mir.arg_decls[index].ty },
            &Lvalue::Static(def_id) =>
                LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
            &Lvalue::ReturnPointer =>
                LvalueTy::Ty { ty: mir.return_ty.unwrap() },
            &Lvalue::Projection(ref proj) =>
                proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
        }
    }
}

impl<'tcx> Rvalue<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
    {
        match self {
            &Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
            &Rvalue::Repeat(ref operand, ref count) => {
                let op_ty = operand.ty(mir, tcx);
                let count = count.value.as_u64(tcx.sess.target.uint_type);
                assert_eq!(count as usize as u64, count);
                Some(tcx.mk_array(op_ty, count as usize))
            }
            &Rvalue::Ref(reg, bk, ref lv) => {
                let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
                Some(tcx.mk_ref(
                    tcx.mk_region(reg),
                    ty::TypeAndMut {
                        ty: lv_ty,
                        mutbl: bk.to_mutbl_lossy()
                    }
                ))
            }
            &Rvalue::Len(..) => Some(tcx.types.usize),
            &Rvalue::Cast(_, _, ty) => Some(ty),
            &Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
                let lhs_ty = lhs.ty(mir, tcx);
                let rhs_ty = rhs.ty(mir, tcx);
                Some(op.ty(tcx, lhs_ty, rhs_ty))
            }
            &Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
                let lhs_ty = lhs.ty(mir, tcx);
                let rhs_ty = rhs.ty(mir, tcx);
                let ty = op.ty(tcx, lhs_ty, rhs_ty);
                let ty = tcx.mk_tup(vec![ty, tcx.types.bool]);
                Some(ty)
            }
            &Rvalue::UnaryOp(_, ref operand) => {
                Some(operand.ty(mir, tcx))
            }
            &Rvalue::Box(t) => {
                Some(tcx.mk_box(t))
            }
            &Rvalue::Aggregate(ref ak, ref ops) => {
                match *ak {
                    AggregateKind::Vec => {
                        if let Some(operand) = ops.get(0) {
                            let ty = operand.ty(mir, tcx);
                            Some(tcx.mk_array(ty, ops.len()))
                        } else {
                            None
                        }
                    }
                    AggregateKind::Tuple => {
                        Some(tcx.mk_tup(
                            ops.iter().map(|op| op.ty(mir, tcx)).collect()
                        ))
                    }
                    AggregateKind::Adt(def, _, substs) => {
                        Some(tcx.lookup_item_type(def.did).ty.subst(tcx, substs))
                    }
                    AggregateKind::Closure(did, substs) => {
                        Some(tcx.mk_closure_from_closure_substs(did, substs))
                    }
                }
            }
            &Rvalue::InlineAsm { .. } => None
        }
    }
}

impl<'tcx> Operand<'tcx> {
    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
        match self {
            &Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
            &Operand::Constant(ref c) => c.ty,
        }
    }
}

impl<'tcx> BinOp {
      pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    lhs_ty: Ty<'tcx>,
                    rhs_ty: Ty<'tcx>)
                    -> Ty<'tcx>
    {
        // FIXME: handle SIMD correctly
        match self {
            &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
            &BinOp::BitXor | &BinOp::BitAnd | &BinOp::BitOr => {
                // these should be integers or floats of the same size.
                assert_eq!(lhs_ty, rhs_ty);
                lhs_ty
            }
            &BinOp::Shl | &BinOp::Shr => {
                lhs_ty // lhs_ty can be != rhs_ty
            }
            &BinOp::Eq | &BinOp::Lt | &BinOp::Le |
            &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
                tcx.types.bool
            }
        }
    }
}

impl BorrowKind {
    pub fn to_mutbl_lossy(self) -> hir::Mutability {
        match self {
            BorrowKind::Mut => hir::MutMutable,
            BorrowKind::Shared => hir::MutImmutable,

            // We have no type corresponding to a unique imm borrow, so
            // use `&mut`. It gives all the capabilities of an `&uniq`
            // and hence is a safe "over approximation".
            BorrowKind::Unique => hir::MutMutable,
        }
    }
}

impl BinOp {
    pub fn to_hir_binop(self) -> hir::BinOp_ {
        match self {
            BinOp::Add => hir::BinOp_::BiAdd,
            BinOp::Sub => hir::BinOp_::BiSub,
            BinOp::Mul => hir::BinOp_::BiMul,
            BinOp::Div => hir::BinOp_::BiDiv,
            BinOp::Rem => hir::BinOp_::BiRem,
            BinOp::BitXor => hir::BinOp_::BiBitXor,
            BinOp::BitAnd => hir::BinOp_::BiBitAnd,
            BinOp::BitOr => hir::BinOp_::BiBitOr,
            BinOp::Shl => hir::BinOp_::BiShl,
            BinOp::Shr => hir::BinOp_::BiShr,
            BinOp::Eq => hir::BinOp_::BiEq,
            BinOp::Ne => hir::BinOp_::BiNe,
            BinOp::Lt => hir::BinOp_::BiLt,
            BinOp::Gt => hir::BinOp_::BiGt,
            BinOp::Le => hir::BinOp_::BiLe,
            BinOp::Ge => hir::BinOp_::BiGe
        }
    }
}
<|endoftext|>