<commit_before>extern crate mp4parse;

use std::env;
use std::fs::File;
use std::io::BufReader;

fn dump_file(filename: &String, verbose: bool) {
    let file = match File::open(filename) {
        Ok(file) => file,
        _ => {
            println!("ERROR: invalid path '{}'", filename);
            return;
        }
    };
    let mut reader = BufReader::new(file);
    let mut context = mp4parse::MediaContext::new();
    // Turn on debug output.
    if verbose {
        context.trace(true);
    }
    // Read all boxes.
    match mp4parse::read_mp4(&mut reader, &mut context) {
        Ok(_) => {},
        Err(mp4parse::Error::Io(e)) => {
            println!("I/O ERROR: {:?} in '{}'", e, filename);
            panic!(e);
        },
        Err(e) => {
            println!("ERROR: {:?} in '{}'", e, filename);
        },
    }
    if verbose {
        println!("-- result of parsing '{}' --\n{:?}", filename, context);
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return;
    }
    let (skip, verbose) = if args[1] == "-v" {
        (2, true)
    } else {
        (1, false)
    };
    for filename in args.iter().skip(skip) {
        if verbose {
            println!("-- dump of '{}' --", filename);
        }
        dump_file(&filename, verbose);
        if verbose {
            println!("-- end of '{}' --", filename);
        }
    }
}
<commit_msg>Include the file offset when reporting errors from dump.rs.<commit_after>extern crate mp4parse;

use std::env;
use std::fs::File;
use std::io::{Seek, SeekFrom};

fn dump_file(filename: &String, verbose: bool) {
    let mut reader = match File::open(filename) {
        Ok(reader) => reader,
        _ => {
            println!("ERROR: invalid path '{}'", filename);
            return;
        }
    };
    let mut context = mp4parse::MediaContext::new();
    // Turn on debug output.
    if verbose {
        context.trace(true);
    }
    // Read all boxes.
    match mp4parse::read_mp4(&mut reader, &mut context) {
        Ok(_) => {},
        Err(mp4parse::Error::Io(e)) => {
            println!("I/O ERROR: {:?} in '{}'", e, filename);
            panic!(e);
        },
        Err(e) => {
            let offset = reader.seek(SeekFrom::Current(0)).unwrap();
            println!("ERROR: {:?} in '{}' @ {}", e, filename, offset);
        },
    }
    if verbose {
        println!("-- result of parsing '{}' --\n{:?}", filename, context);
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return;
    }
    let (skip, verbose) = if args[1] == "-v" {
        (2, true)
    } else {
        (1, false)
    };
    for filename in args.iter().skip(skip) {
        if verbose {
            println!("-- dump of '{}' --", filename);
        }
        dump_file(&filename, verbose);
        if verbose {
            println!("-- end of '{}' --", filename);
        }
    }
}
<|endoftext|>


<commit_before>// TODO: whilst developing, suppress unused warnings
#![allow(dead_code)]

extern crate dialoguer;
#[macro_use]
extern crate quote;

use dialoguer::Input;
use std::path::PathBuf;
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

mod api_generator;
mod error;
mod rest_spec;

fn main() {
    let download_dir = fs::canonicalize(PathBuf::from("./rest_specs")).unwrap();
    let generated_dir = fs::canonicalize(PathBuf::from("./../elasticsearch/src")).unwrap();
    let last_downloaded_version = "last_downloaded_version";

    let mut download_specs = false;
    let mut answer = String::new();
    let mut branch = String::new();
    let default_branch = if Path::new(last_downloaded_version).exists() {
        fs::read_to_string(last_downloaded_version).expect("Could not read branch into string")
    } else {
        String::from("master")
    };

    while answer != "y" && answer != "n" {
        answer = Input::new()
            .default(String::from("n"))
            .show_default(false)
            .with_prompt("Download rest specifications [y/N]")
            .interact()
            .unwrap()
            .to_lowercase();
        download_specs = answer == "y";
    }

    if download_specs {
        branch = Input::new()
            .default(default_branch.clone())
            .show_default(false)
            .with_prompt(
                format!(
                    "Branch to download specification from [default {}]",
                    default_branch
                )
                .as_str(),
            )
            .interact()
            .unwrap();

        fs::remove_dir_all(&download_dir).unwrap();
        rest_spec::download_specs(&branch, &download_dir);

        File::create(last_downloaded_version)
            .expect("failed to create last_downloaded_version file")
            .write_all(branch.as_bytes())
            .expect("unable to write branch to last_downloaded_version file");
    }

    // only offer to generate if there are downloaded specs
    if download_dir
        .read_dir()
        .map(|mut r| r.next().is_some())
        .unwrap_or(false)
    {
        let mut generate_code = true;
        answer = String::new();
        while answer != "y" && answer != "n" {
            answer = Input::new()
                .default(String::from("y"))
                .show_default(false)
                .with_prompt(
                    format!(
                        "Generate code from rest specifications {} [Y/n]",
                        default_branch
                    )
                    .as_str(),
                )
                .interact()
                .unwrap()
                .to_lowercase();
            generate_code = answer == "y";
        }

        if generate_code {
            api_generator::generate(&branch, &download_dir, &generated_dir).unwrap();
        }
    }
}
<commit_msg>Run api_generator from workspace directory<commit_after>// TODO: whilst developing, suppress unused warnings
#![allow(dead_code)]

extern crate dialoguer;
#[macro_use]
extern crate quote;

use dialoguer::Input;
use std::path::PathBuf;
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

mod api_generator;
mod error;
mod rest_spec;

fn main() {
    // This must be run from the src root directory, with cargo run -p api_generator
    let download_dir = fs::canonicalize(PathBuf::from("./api_generator/rest_specs")).unwrap();
    let generated_dir = fs::canonicalize(PathBuf::from("./elasticsearch/src")).unwrap();
    let last_downloaded_version = "./api_generator/last_downloaded_version";

    let mut download_specs = false;
    let mut answer = String::new();
    let mut branch = String::new();
    let default_branch = if Path::new(last_downloaded_version).exists() {
        fs::read_to_string(last_downloaded_version).expect("Could not read branch into string")
    } else {
        String::from("master")
    };

    while answer != "y" && answer != "n" {
        answer = Input::new()
            .default(String::from("n"))
            .show_default(false)
            .with_prompt("Download rest specifications [y/N]")
            .interact()
            .unwrap()
            .to_lowercase();
        download_specs = answer == "y";
    }

    if download_specs {
        branch = Input::new()
            .default(default_branch.clone())
            .show_default(false)
            .with_prompt(
                format!(
                    "Branch to download specification from [default {}]",
                    default_branch
                )
                .as_str(),
            )
            .interact()
            .unwrap();

        fs::remove_dir_all(&download_dir).unwrap();
        rest_spec::download_specs(&branch, &download_dir);

        File::create(last_downloaded_version)
            .expect("failed to create last_downloaded_version file")
            .write_all(branch.as_bytes())
            .expect("unable to write branch to last_downloaded_version file");
    }

    // only offer to generate if there are downloaded specs
    if download_dir
        .read_dir()
        .map(|mut r| r.next().is_some())
        .unwrap_or(false)
    {
        let mut generate_code = true;
        answer = String::new();
        while answer != "y" && answer != "n" {
            answer = Input::new()
                .default(String::from("y"))
                .show_default(false)
                .with_prompt(
                    format!(
                        "Generate code from rest specifications {} [Y/n]",
                        default_branch
                    )
                    .as_str(),
                )
                .interact()
                .unwrap()
                .to_lowercase();
            generate_code = answer == "y";
        }

        if generate_code {
            api_generator::generate(&branch, &download_dir, &generated_dir).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use libc::{c_uchar, c_void, c_int, c_char, free};
use std::slice::raw::buf_as_slice;
use std::io::File;
use std::mem;

#[link(name="stb")]
extern {
    fn stbi_load_from_memory(
        buffer: *const c_uchar, len: c_int, x: *mut c_int, y: *mut c_int,
        comp: *mut c_int, req_comp: c_int) -> *const c_uchar;

    fn stbi_write_png(
        filename: *const c_char, w: c_int, h: c_int, comp: c_int,
        data: *const c_void, stride_in_bytes: c_int);
}

pub struct Image {
    pub width: uint,
    pub height: uint,
    pub bpp: uint,
    pub pixels: Vec<u8>,
}

impl Image {
    pub fn load(path: &str, force_channels: uint) -> Option<Image> {
        let path = Path::new(path);
        if !path.exists() { return None; }
        let data = File::open(&path).read_to_end().unwrap();
        Image::load_from_memory(data.as_slice(), force_channels)
    }

    pub fn load_from_memory(data: &[u8], force_channels: uint) -> Option<Image> {
        unsafe {
            let mut w = 0 as c_int;
            let mut h = 0 as c_int;
            let mut bpp = 0 as c_int;

            let buffer = stbi_load_from_memory(
                data.as_ptr(), data.len() as c_int,
                &mut w, &mut h, &mut bpp, force_channels as c_int);

            if buffer.is_null() {
                return None
            }

            let bpp = if force_channels != 0 { force_channels } else { bpp as uint };

            let ret = Some(Image{
                width: w as uint,
                height: h as uint,
                bpp: bpp,
                pixels: buf_as_slice(
                    mem::transmute(buffer), (w * h) as uint * bpp, |s| Vec::from_slice(s)),
            });
            free(buffer as *mut c_void);
            ret
        }
    }

    pub fn new(width: uint, height: uint, bpp: uint) -> Image {
        assert!(bpp <= 4);
        Image{
            width: width,
            height: height,
            bpp: bpp,
            pixels: Vec::from_elem(width * height * bpp, 0u8),
        }
    }

    pub fn save_png(&self, path: &str) {
        unsafe {
            stbi_write_png(
                path.to_c_str().as_ptr(), self.width as c_int, self.height as c_int,
                self.bpp as c_int, self.pixels.as_ptr() as *const c_void, 0);
        }
    }
}
<commit_msg>Upgrade to Rust 0.11.0<commit_after>use std::vec::Vec;
use libc::{c_uchar, c_void, c_int, c_char, free};
use std::slice::raw::buf_as_slice;
use std::io::File;
use std::mem;

#[link(name="stb")]
extern {
    fn stbi_load_from_memory(
        buffer: *const c_uchar, len: c_int, x: *mut c_int, y: *mut c_int,
        comp: *mut c_int, req_comp: c_int) -> *const c_uchar;

    fn stbi_write_png(
        filename: *const c_char, w: c_int, h: c_int, comp: c_int,
        data: *const c_void, stride_in_bytes: c_int);
}

pub struct Image {
    pub width: uint,
    pub height: uint,
    pub bpp: uint,
    pub pixels: Vec<u8>,
}

impl Image {
    pub fn load(path: &str, force_channels: uint) -> Option<Image> {
        let path = Path::new(path);
        if !path.exists() { return None; }
        let data = File::open(&path).read_to_end().unwrap();
        Image::load_from_memory(data.as_slice(), force_channels)
    }

    pub fn load_from_memory(data: &[u8], force_channels: uint) -> Option<Image> {
        unsafe {
            let mut w = 0 as c_int;
            let mut h = 0 as c_int;
            let mut bpp = 0 as c_int;

            let buffer = stbi_load_from_memory(
                data.as_ptr(), data.len() as c_int,
                &mut w, &mut h, &mut bpp, force_channels as c_int);

            if buffer.is_null() {
                return None
            }

            let bpp = if force_channels != 0 { force_channels } else { bpp as uint };

            let ret = Some(Image{
                width: w as uint,
                height: h as uint,
                bpp: bpp,
                pixels: buf_as_slice(
                    mem::transmute(buffer), (w * h) as uint * bpp, |s| Vec::from_slice(s)),
            });
            free(buffer as *mut c_void);
            ret
        }
    }

    pub fn new(width: uint, height: uint, bpp: uint) -> Image {
        assert!(bpp <= 4);
        Image{
            width: width,
            height: height,
            bpp: bpp,
            pixels: Vec::from_elem(width * height * bpp, 0u8),
        }
    }

    pub fn save_png(&self, path: &str) {
        unsafe {
            path.with_c_str(|cstr|
                stbi_write_png(
                    cstr, self.width as c_int, self.height as c_int,
                    self.bpp as c_int, self.pixels.as_ptr() as *const c_void, 0));
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(asm)]
#![crate_type="staticlib"]
#![no_std]

extern crate core;
extern crate zinc;

use core::intrinsics::volatile_load;

use core::option::Some;
use zinc::hal::k20::{pin, watchdog};
use zinc::hal::pin::Gpio;
use zinc::hal::cortex_m4::systick;
use zinc::util::support::wfi;

static mut i: u32 = 0;
static mut global_on: u32 = 0;

#[allow(dead_code)]
#[no_mangle]
pub unsafe extern fn isr_systick() {
    i += 1;
    if i > 100 {
      i = 0;
      global_on = !global_on;
    }
}

#[no_mangle]
#[allow(dead_code)]
pub fn main() {
  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();
  watchdog::init(watchdog::Disabled);

  // Pins for MC HCK (http://www.mchck.org/)
  let led1 = pin::Pin::new(pin::PortB, 16, pin::Gpio, Some(zinc::hal::pin::Out));

  systick::setup(systick::ten_ms().unwrap_or(480000));
  systick::enable();
  systick::enable_irq();

  loop {
    let on: bool = unsafe { volatile_load(&global_on as *const u32) == 0 };
      match on {
        true  => led1.set_high(),
        false => led1.set_low(),
      }
      wfi();
  }
}
<commit_msg>k20 - ISR app enum namespace fix<commit_after>#![feature(phase)]
#![feature(asm)]
#![crate_type="staticlib"]
#![no_std]

extern crate core;
extern crate zinc;

use core::intrinsics::volatile_load;

use core::option::Some;
use zinc::hal::k20::{pin, watchdog};
use zinc::hal::pin::Gpio;
use zinc::hal::cortex_m4::systick;
use zinc::util::support::wfi;

static mut i: u32 = 0;
static mut global_on: u32 = 0;

#[allow(dead_code)]
#[no_mangle]
pub unsafe extern fn isr_systick() {
    i += 1;
    if i > 100 {
      i = 0;
      global_on = !global_on;
    }
}

#[no_mangle]
#[allow(dead_code)]
pub fn main() {
  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();
  watchdog::init(watchdog::State::Disabled);

  // Pins for MC HCK (http://www.mchck.org/)
  let led1 = pin::Pin::new(pin::Port::PortB, 16, pin::Function::Gpio, Some(zinc::hal::pin::Out));

  systick::setup(systick::ten_ms().unwrap_or(480000));
  systick::enable();
  systick::enable_irq();

  loop {
    let on: bool = unsafe { volatile_load(&global_on as *const u32) == 0 };
      match on {
        true  => led1.set_high(),
        false => led1.set_low(),
      }
      wfi();
  }
}
<|endoftext|>


<commit_before>#[deriving(PartialEq, Show)]
pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

pub fn tokenize(input: &str) -> Tokenizer {
    Tokenizer {text: String::from_str(input)}
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-'           => true,
        _                   => false,
    }
}

struct Tokenizer {
    text: String
}

impl Iterator<Token> for Tokenizer {
    fn next(&mut self) -> Option<Token> {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return None
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let number = c.to_string() + self.read_until_whitespace().as_slice();
                let x: f64 = number.parse().unwrap();
                Some(Token::Number(x))
            }
            c => {
                let word = c.to_string() + self.read_until_whitespace().as_slice();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokenizer {
    fn pop_char(&mut self) -> Option<char> {
        if self.text.is_empty() {
            None
        } else {
            self.text.remove(0)
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return "".to_string()
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + self.read_until_whitespace().as_slice(),
        }
    }
}

#[test]
fn test_tokenizer_empty() {
    let test_str = "";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![]);
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
    ]);
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
        Token::Word("world".to_string()),
    ]);
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".4 -2";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(0.4),
        Token::Number(-2.0),
    ]);
}

#[test]
fn test_tokenizer_point() {
    let test_str = "POINT (10 -20)";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("POINT".to_string()),
        Token::ParenOpen,
        Token::Number(10.0),
        Token::Number(-20.0),
        Token::ParenClose,
    ]);
}
<commit_msg>Better error handling for number parsing<commit_after>#[deriving(PartialEq, Show)]
pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

pub fn tokenize(input: &str) -> Tokenizer {
    Tokenizer {text: String::from_str(input)}
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-'           => true,
        _                   => false,
    }
}

struct Tokenizer {
    text: String
}

impl Iterator<Token> for Tokenizer {
    fn next(&mut self) -> Option<Token> {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return None
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let number = c.to_string() + self.read_until_whitespace().as_slice();
                match number.parse::<f64>() {
                    Some(parsed_num) => Some(Token::Number(parsed_num)),
                    None => panic!("Could not parse number: {}", number),
                }
            }
            c => {
                let word = c.to_string() + self.read_until_whitespace().as_slice();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokenizer {
    fn pop_char(&mut self) -> Option<char> {
        if self.text.is_empty() {
            None
        } else {
            self.text.remove(0)
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return "".to_string()
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + self.read_until_whitespace().as_slice(),
        }
    }
}

#[test]
fn test_tokenizer_empty() {
    let test_str = "";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![]);
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
    ]);
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
        Token::Word("world".to_string()),
    ]);
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".4 -2";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(0.4),
        Token::Number(-2.0),
    ]);
}

#[test]
fn test_tokenizer_point() {
    let test_str = "POINT (10 -20)";
    let tokens: Vec<Token> = tokenize(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("POINT".to_string()),
        Token::ParenOpen,
        Token::Number(10.0),
        Token::Number(-20.0),
        Token::ParenClose,
    ]);
}
<|endoftext|>


<commit_before>//! Various trait aliases to simplify generics in other modules. Every trait in this module is
//! implemented for all possible valid types.
use num_traits::float;
use num_traits::identities::Zero;
use num_traits::cast::FromPrimitive;
use std::fmt::Debug;
use std::ops::{Add, Sub, Mul, Div, Neg};

pub trait Float: float::Float + FromPrimitive + Debug {}
impl<F> Float for F where F: float::Float + FromPrimitive + Debug {}

pub trait PVOps<F>:
		Add<Self, Output = Self> +
		Sub<Self, Output = Self> +
		Mul<F, Output = Self> +
		Div<F, Output = Self> +
		Neg<Output = Self> +
		Zero

		where Self: Sized,
			  F: Float {}

impl<F: Float, PV> PVOps<F> for PV
		where PV:
			Add<PV, Output = PV> +
			Sub<PV, Output = PV> +
			Mul<F, Output = PV> +
			Div<F, Output = PV> +
			Neg<Output = PV> +
			Zero {}

pub trait Point<F, V>:
		Into<V> +
		Clone +
		Copy +
		PVOps<F>

		where Self: Sized,
			  F: Float,
			  V: Vector<F> {}

impl<F, P, V> Point<F, V> for P
        where F: Float,
        	  V: Vector<F>,
              P: Into<V> + Clone + Copy + PVOps<F> {}

pub trait Vector<F: Float>:
		Clone +
		Copy +
		PVOps<F> {}

impl<F, V> Vector<F> for V
        where F: Float,
              V: Clone + Copy + PVOps<F> {}<commit_msg>Simplified PVOps trait slightly<commit_after>//! Various trait aliases to simplify generics in other modules. Every trait in this module is
//! implemented for all possible valid types.
use num_traits::float;
use num_traits::identities::Zero;
use num_traits::cast::FromPrimitive;
use std::fmt::Debug;
use std::ops::{Add, Sub, Mul, Div};

pub trait Float: float::Float + FromPrimitive + Debug {}
impl<F> Float for F where F: float::Float + FromPrimitive + Debug {}

pub trait PVOps<F>:
		Add<Self, Output = Self> +
		Sub<Self, Output = Self> +
		Mul<F, Output = Self> +
		Div<F, Output = Self> +
		Zero

		where Self: Sized,
			  F: Float {}

impl<F: Float, PV> PVOps<F> for PV
		where PV:
			Add<PV, Output = PV> +
			Sub<PV, Output = PV> +
			Mul<F, Output = PV> +
			Div<F, Output = PV> +
			Zero {}

pub trait Point<F, V>:
		Into<V> +
		Clone +
		Copy +
		PVOps<F>

		where Self: Sized,
			  F: Float,
			  V: Vector<F> {}

impl<F, P, V> Point<F, V> for P
        where F: Float,
        	  V: Vector<F>,
              P: Into<V> + Clone + Copy + PVOps<F> {}

pub trait Vector<F: Float>:
		Clone +
		Copy +
		PVOps<F> {}

impl<F, V> Vector<F> for V
        where F: Float,
              V: Clone + Copy + PVOps<F> {}<|endoftext|>


<commit_before>use Result;
use std::fmt;

/// A scale and an offset that transforms xyz coordinates.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Transform {
    /// The scale.
    pub scale: f64,
    /// The offset.
    pub offset: f64,
}

impl Transform {
    /// Applies this transform to an i32, returning a float.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Transform;
    /// let transform = Transform { scale: 2., offset: 1. };
    /// assert_eq!(3., transform.direct(1));
    /// ```
    pub fn direct(&self, n: i32) -> f64 {
        self.scale * n as f64 + self.offset
    }

    /// Applies the inverse transform, and rounds the result.
    ///
    /// Returns an error if the resultant value can't be represented as an i32.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Transform;
    /// let transform = Transform { scale: 2., offset: 1. };
    /// assert_eq!(1, transform.inverse(2.9).unwrap());
    /// ```
    pub fn inverse(&self, n: f64) -> Result<i32> {
        use Error;
        use std::i32;

        let n = ((n - self.offset) / self.scale).round();
        if n > i32::MAX as f64 {
            Err(Error::InverseTransform(n, *self))
        } else {
            Ok(n as i32)
        }
    }
}

impl Default for Transform {
    fn default() -> Transform {
        Transform {
            scale: 0.001,
            offset: 0.,
        }
    }
}

impl fmt::Display for Transform {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "`{} * x + {}`", self.scale, self.offset)
    }
}
<commit_msg>Check for too-small inverse transforms as well<commit_after>use Result;
use std::fmt;

/// A scale and an offset that transforms xyz coordinates.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Transform {
    /// The scale.
    pub scale: f64,
    /// The offset.
    pub offset: f64,
}

impl Transform {
    /// Applies this transform to an i32, returning a float.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Transform;
    /// let transform = Transform { scale: 2., offset: 1. };
    /// assert_eq!(3., transform.direct(1));
    /// ```
    pub fn direct(&self, n: i32) -> f64 {
        self.scale * n as f64 + self.offset
    }

    /// Applies the inverse transform, and rounds the result.
    ///
    /// Returns an error if the resultant value can't be represented as an i32.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Transform;
    /// let transform = Transform { scale: 2., offset: 1. };
    /// assert_eq!(1, transform.inverse(2.9).unwrap());
    /// ```
    pub fn inverse(&self, n: f64) -> Result<i32> {
        use Error;
        use std::i32;

        let n = ((n - self.offset) / self.scale).round();
        if n > i32::MAX as f64 || n < i32::MIN as f64 {
            Err(Error::InverseTransform(n, *self))
        } else {
            Ok(n as i32)
        }
    }
}

impl Default for Transform {
    fn default() -> Transform {
        Transform {
            scale: 0.001,
            offset: 0.,
        }
    }
}

impl fmt::Display for Transform {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "`{} * x + {}`", self.scale, self.offset)
    }
}

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

    #[test]
    fn too_large() {
        let transform = Transform::default();
        let n = i32::MAX as f64 * transform.scale + 1.;
        assert!(transform.inverse(n).is_err());
    }

    #[test]
    fn too_small() {
        let transform = Transform::default();
        let n = i32::MIN as f64 * transform.scale - 1.;
        assert!(transform.inverse(n).is_err());
    }
}
<|endoftext|>


<commit_before>use vec3;
use num::Num;
use length::length_values;

#[inline(always)]
pub fn transform_angle<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], angle: T) -> &'a mut [T; 2] {
    let c = angle.cos();
    let s = angle.sin();

    out[0] = a[0] * c - a[1] * s;
    out[1] = a[0] * s + a[1] * c;
    out
}

#[inline(always)]
pub fn transform_mat2<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 4]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[2];
    out[1] = a[0] * m[1] + a[1] * m[3];
    out
}

#[inline(always)]
pub fn transform_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 6]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[2] + m[4];
    out[1] = a[0] * m[1] + a[1] * m[3] + m[5];
    out
}

#[inline(always)]
pub fn transform_mat3<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 9]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[3] + m[6];
    out[1] = a[0] * m[1] + a[1] * m[4] + m[7];
    out
}

#[inline(always)]
pub fn transform_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 16]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[4] + m[12];
    out[1] = a[0] * m[1] + a[1] * m[5] + m[13];
    out
}

#[inline(always)]
pub fn transform_projection<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 16]) -> &'a mut [T; 2] {
    let mut d = a[0] * m[3] + a[1] * m[7] + m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13]) * d;
    out
}

#[inline(always)]
pub fn transform_projection_no_position<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: [T; 16]) -> &'a mut [T; 2] {
    let mut d = a[0] * m[3] + a[1] * m[7] + m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9]) * d;
    out
}

#[inline(always)]
pub fn position_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 6]) -> &'a mut [T; 2] {
    out[0] = m[4];
    out[1] = m[5];
    out
}

#[inline(always)]
pub fn position_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 16]) -> &'a mut [T; 2] {
    out[0] = m[12];
    out[1] = m[13];
    out
}

#[inline(always)]
pub fn scale_mat2<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 4]) -> &'a mut [T; 2] {
    out[0] = length_values(m[0], m[2]);
    out[1] = length_values(m[1], m[3]);
    out
}

#[inline(always)]
pub fn scale_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 6]) -> &'a mut [T; 2] {
    out[0] = length_values(m[0], m[2]);
    out[1] = length_values(m[1], m[3]);
    out
}

#[inline(always)]
pub fn scale_mat3<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 9]) -> &'a mut [T; 2] {
    out[0] = vec3::length_values(m[0], m[3], m[6]);
    out[1] = vec3::length_values(m[1], m[4], m[7]);
    out
}

#[inline(always)]
pub fn scale_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], m: [T; 16]) -> &'a mut [T; 2] {
    out[0] = vec3::length_values(m[0], m[4], m[8]);
    out[1] = vec3::length_values(m[1], m[5], m[9]);
    out
}
<commit_msg>updates<commit_after>use vec3;
use num::Num;
use length::length_values;

#[inline(always)]
pub fn transform_angle<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], angle: T) -> &'a mut [T; 2] {
    let c = angle.cos();
    let s = angle.sin();

    out[0] = a[0] * c - a[1] * s;
    out[1] = a[0] * s + a[1] * c;
    out
}

#[inline(always)]
pub fn transform_mat2<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 4]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[2];
    out[1] = a[0] * m[1] + a[1] * m[3];
    out
}

#[inline(always)]
pub fn transform_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 6]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[2] + m[4];
    out[1] = a[0] * m[1] + a[1] * m[3] + m[5];
    out
}

#[inline(always)]
pub fn transform_mat3<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 9]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[3] + m[6];
    out[1] = a[0] * m[1] + a[1] * m[4] + m[7];
    out
}

#[inline(always)]
pub fn transform_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 16]) -> &'a mut [T; 2] {
    out[0] = a[0] * m[0] + a[1] * m[4] + m[12];
    out[1] = a[0] * m[1] + a[1] * m[5] + m[13];
    out
}

#[inline(always)]
pub fn transform_projection<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 16]) -> &'a mut [T; 2] {
    let mut d = a[0] * m[3] + a[1] * m[7] + m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13]) * d;
    out
}

#[inline(always)]
pub fn transform_projection_no_position<'a, 'b, T: Num>(out: &'a mut [T; 2], a: &'b [T; 2], m: &'b [T; 16]) -> &'a mut [T; 2] {
    let mut d = a[0] * m[3] + a[1] * m[7] + m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9]) * d;
    out
}

#[inline(always)]
pub fn position_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 6]) -> &'a mut [T; 2] {
    out[0] = m[4];
    out[1] = m[5];
    out
}

#[inline(always)]
pub fn position_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 16]) -> &'a mut [T; 2] {
    out[0] = m[12];
    out[1] = m[13];
    out
}

#[inline(always)]
pub fn scale_mat2<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 4]) -> &'a mut [T; 2] {
    out[0] = length_values(m[0], m[2]);
    out[1] = length_values(m[1], m[3]);
    out
}

#[inline(always)]
pub fn scale_mat32<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 6]) -> &'a mut [T; 2] {
    out[0] = length_values(m[0], m[2]);
    out[1] = length_values(m[1], m[3]);
    out
}

#[inline(always)]
pub fn scale_mat3<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 9]) -> &'a mut [T; 2] {
    out[0] = vec3::length_values(m[0], m[3], m[6]);
    out[1] = vec3::length_values(m[1], m[4], m[7]);
    out
}

#[inline(always)]
pub fn scale_mat4<'a, 'b, T: Num>(out: &'a mut [T; 2], m: &'b [T; 16]) -> &'a mut [T; 2] {
    out[0] = vec3::length_values(m[0], m[4], m[8]);
    out[1] = vec3::length_values(m[1], m[5], m[9]);
    out
}
<|endoftext|>


<commit_before>use error::{RuntimeError, VoidResult};
use frame::GPUFrame;

use sys::dl;
use sys::x11;
use sys::xcb;
use sys::glx;
use sys::gl;

use sys::utils::fn_ptr::FnPtrLibrary;

use super::Context;

pub struct GlxContext {
   pub library: Box<FnPtrLibrary>,
   pub display: glx::Display,
   pub version: glx::Version,
   pub config: glx::Config,
   pub context: glx::Context,
   pub rendering_area: glx::GLXWindow,
}

impl Context for GlxContext {
   fn new(x11_display: &x11::Display, screen_id: &x11::ScreenID, window: &xcb::Window) -> Result<Self, RuntimeError> {
      let library_name = if gl::GLES2 {
         "libGLESv2.so"
      } else {
         "libGL.so"
      };

      let library = Box::new(
         try!(dl::Library::open(library_name))
      );

      try!(glx::load_functions(&library));

      let display = glx::Display{
         ptr: x11_display.ptr,
      };

      let version = try!(glx::initialize(&display));

      let config = try!(glx::choose_config(&display, screen_id));

      let context = try!(glx::create_new_context(&display, &config));

      let rendering_area = try!(Self::init_rendering_area(&display, &config, &context, window));

      try!(Self::init_gl());

      Ok(GlxContext {
         library: library,
         display: display,
         version: version,
         config: config,
         context: context,
         rendering_area: rendering_area,
      })
   }

   #[inline]
   fn create_gpu_frame(
      &self, width: u32, height: u32
   ) -> Result<Box<GPUFrame>, RuntimeError> {
      gl::frame::create_gpu_frame(width, height)
   }

   #[inline]
   fn swap_buffers(&self) -> VoidResult {
      glx::swap_buffers(&self.display, self.rendering_area)
   }
}

impl GlxContext {
   #[inline]
   pub fn init_rendering_area(
      display: &glx::Display,
      config: &glx::Config,
      context: &glx::Context,
      window: &xcb::Window
   ) -> Result<glx::GLXWindow, RuntimeError> {
      let rendering_area = try!(glx::create_rendering_area(&display, &config, window.window_id.id));

      try!(glx::make_current(&display, rendering_area, &context));

      // TODO
      // try!(glx::swap_interval(display, 0));

      Ok(rendering_area)
   }

   #[inline]
   pub fn init_gl() -> VoidResult {
      gl::initialize(&glx::Loader::new())
   }
}
<commit_msg>Trying different names for libGL.so and libGLESv2.so<commit_after>use error::{RuntimeError, VoidResult};
use frame::GPUFrame;

use sys::dl;
use sys::x11;
use sys::xcb;
use sys::glx;
use sys::gl;

use sys::utils::fn_ptr::FnPtrLibrary;

use super::Context;

pub struct GlxContext {
   pub library: Box<FnPtrLibrary>,
   pub display: glx::Display,
   pub version: glx::Version,
   pub config: glx::Config,
   pub context: glx::Context,
   pub rendering_area: glx::GLXWindow,
}

impl Context for GlxContext {
   fn new(x11_display: &x11::Display, screen_id: &x11::ScreenID, window: &xcb::Window) -> Result<Self, RuntimeError> {
      let library_names = if gl::GLES2 {
         vec!["libGLESv2.so", "libGLESv2.so.2", "libGLESv2.so.3"]
      } else {
         vec!["libGL.so", "libGL.so.1"]
      };

      let library = Box::new(
         try!(dl::Library::open_any(&library_names))
      );

      try!(glx::load_functions(&library));

      let display = glx::Display{
         ptr: x11_display.ptr,
      };

      let version = try!(glx::initialize(&display));

      let config = try!(glx::choose_config(&display, screen_id));

      let context = try!(glx::create_new_context(&display, &config));

      let rendering_area = try!(Self::init_rendering_area(&display, &config, &context, window));

      try!(Self::init_gl());

      Ok(GlxContext {
         library: library,
         display: display,
         version: version,
         config: config,
         context: context,
         rendering_area: rendering_area,
      })
   }

   #[inline]
   fn create_gpu_frame(
      &self, width: u32, height: u32
   ) -> Result<Box<GPUFrame>, RuntimeError> {
      gl::frame::create_gpu_frame(width, height)
   }

   #[inline]
   fn swap_buffers(&self) -> VoidResult {
      glx::swap_buffers(&self.display, self.rendering_area)
   }
}

impl GlxContext {
   #[inline]
   pub fn init_rendering_area(
      display: &glx::Display,
      config: &glx::Config,
      context: &glx::Context,
      window: &xcb::Window
   ) -> Result<glx::GLXWindow, RuntimeError> {
      let rendering_area = try!(glx::create_rendering_area(&display, &config, window.window_id.id));

      try!(glx::make_current(&display, rendering_area, &context));

      // TODO
      // try!(glx::swap_interval(display, 0));

      Ok(rendering_area)
   }

   #[inline]
   pub fn init_gl() -> VoidResult {
      gl::initialize(&glx::Loader::new())
   }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::symlink_metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if !parts.is_empty() {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<commit_msg>uucore::fs: add `fn resolve_relative_path`<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Joseph Crail <jbcrail@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind};
use std::io::Result as IOResult;
use std::path::{Component, Path, PathBuf};
use std::borrow::Cow;

#[cfg(unix)]
pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> {
    if path.is_absolute() {
        return path.into();
    }
    let mut result = env::current_dir().unwrap_or(PathBuf::from("/"));
    for comp in path.components() {
        match comp {
            Component::ParentDir => {
                result.pop();
            }
            Component::CurDir => (),
            Component::Normal(s) => result.push(s),
            _ => unreachable!(),
        }
    }
    result.into()
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> IOResult<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::symlink_metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    }
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> IOResult<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec![];

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) |
            Component::RootDir => {
                result.push(part.as_os_str());
            }
            Component::CurDir => (),
            Component::ParentDir => {
                parts.pop();
            }
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if !parts.is_empty() {
        for part in parts[..parts.len() - 1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => {
                    match can_mode {
                        CanonicalizeMode::Missing => continue,
                        _ => return Err(e),
                    }
                }
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => {
                if can_mode == CanonicalizeMode::Existing {
                    return Err(e);
                }
            }
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<|endoftext|>


<commit_before>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

use std::fmt::Debug;

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Scaling
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// # Optimizations
///
/// Every element of the vector to sort are compared to the first and last element of the sorted
/// vector. This prevents the worst case scenario to happen. The implementation still keeps an
/// O(N^2) scaling though.
///
/// # Notes
///
/// The implementation is 'stable' as it does preserve the relative order of items with
/// equal values.
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: Debug + PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    // Declare the vector of indices to return. Reserve memory for "n" element so it
    // is the same size as the vector to sort.
    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    if !input.is_empty() {

        // Place the first element's index (0) as the first element of the output_index vector.
        output_index.push(0);

        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            // enumerate() returns the current index of iteration, not the index of the
            // vector iterated upon. This means it will start at 0, even though we wanted to skip
            // the first element using skip(1). Let's get the value we wanted: 'i', the loop index
            // of the input array.
            let i = i_start_at_0 + 1;

            // Compare the element of the loop 'elem' with the last element stored in the index
            // vector 'output_index'.
            if *elem >= input[*output_index.last().unwrap()] {
                // If the element of the loop is larger or equal to the last sorted element, simply
                // append its index to the sorted index list.
                output_index.push(i);
            } else if *elem < input[*output_index.first().unwrap()] {
                // If the element of the loop is smaller than the first sorted element, simply put
                // it at the beginning of the sorted index list.
                output_index.insert(0, i);
            } else {
                // If the element of the loop is smaller than the last sorted element, we loop
                // over (backward) all sorted indices and compare the values to identify where
                // to place the loop element.
                // NOTE: We must use a loop on indices as to prevent problems with the
                //       rust borrow-checker.

                // Naively start at the second element of the output_index.
                for j in (1..i) {
                    if *elem < input[output_index[j]] {
                        output_index.insert(j, i);
                        break;
                    }
                }
            }
        }
    }

    assert_eq!(output_index.len(), n);

    return output_index;
}
<commit_msg>Get ride of Debug for type T.<commit_after>//! Insertion sort algorithm.
//!
//! The `insertion_sort` module contains the simple sorting algorithm "Insertion Sort".
//!
//! Source: https://en.wikipedia.org/wiki/Insertion_sort

/// Simple sort: insertion sort.
///
/// # Details
///
/// Insertion sort is one of the simplest sorting algorithm. Every elements of the list to sort
/// are picked one at a time and inserted into a the sorted list at the right location.
///
/// This function takes an immutable reference vector of any type and returns a vector of `usize`
/// of the same length containing the indices of the initial vector sorted.
///
/// # Scaling
///
/// In the best case scenario, the list is already sorted and the work is simply to append the
/// element at the end of the list, hence a O(N) scaling.
///
/// In the worst case scenario, the list is in reverse order. Hence, every element is compared to
/// all previous elements already sorted until this new one gets inserted at the beginning of the
/// sorted list, thus making this case O(N^2).
///
/// Insertion sort is still useful as its simplicity (and thus small overhead) makes it ideal for
/// small vectors.
///
/// # Optimizations
///
/// Every element of the vector to sort are compared to the first and last element of the sorted
/// vector. This prevents the worst case scenario to happen. The implementation still keeps an
/// O(N^2) scaling though.
///
/// # Notes
///
/// The implementation is 'stable' as it does preserve the relative order of items with
/// equal values.
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// assert_eq!(vec![3, 1, 2, 0], sorting::simplesorts::insertion::sort(&data));
/// ```
///
pub fn sort<T: PartialOrd>(input: &Vec<T>) -> Vec<usize> {
    let n = input.len();

    // Declare the vector of indices to return. Reserve memory for "n" element so it
    // is the same size as the vector to sort.
    let mut output_index: Vec<usize> = Vec::with_capacity(n);

    if !input.is_empty() {

        // Place the first element's index (0) as the first element of the output_index vector.
        output_index.push(0);

        // Loop over input vector, skipping the first element as it's already inserted as the first
        // element of output_index.
        for (i_start_at_0,elem) in input.iter().skip(1).enumerate() {
            // enumerate() returns the current index of iteration, not the index of the
            // vector iterated upon. This means it will start at 0, even though we wanted to skip
            // the first element using skip(1). Let's get the value we wanted: 'i', the loop index
            // of the input array.
            let i = i_start_at_0 + 1;

            // Compare the element of the loop 'elem' with the last element stored in the index
            // vector 'output_index'.
            if *elem >= input[*output_index.last().unwrap()] {
                // If the element of the loop is larger or equal to the last sorted element, simply
                // append its index to the sorted index list.
                output_index.push(i);
            } else if *elem < input[*output_index.first().unwrap()] {
                // If the element of the loop is smaller than the first sorted element, simply put
                // it at the beginning of the sorted index list.
                output_index.insert(0, i);
            } else {
                // If the element of the loop is smaller than the last sorted element, we loop
                // over (backward) all sorted indices and compare the values to identify where
                // to place the loop element.
                // NOTE: We must use a loop on indices as to prevent problems with the
                //       rust borrow-checker.

                // Naively start at the second element of the output_index.
                for j in (1..i) {
                    if *elem < input[output_index[j]] {
                        output_index.insert(j, i);
                        break;
                    }
                }
            }
        }
    }

    assert_eq!(output_index.len(), n);

    return output_index;
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]

use ::errors::*;
use ::Ignore;

use ::coremidi::*;

pub struct MidiInput {
    ignore_flags: Ignore
}

impl MidiInput {
    pub fn new(client_name: &str) -> Result<Self, InitError> {
        unimplemented!()
    }

    pub fn ignore(&mut self, flags: Ignore) {
        unimplemented!()
    }

    pub fn port_count(&self) -> usize {
        Sources::count()
    }

    pub fn port_name(&self, port_number: usize) -> Result<String, PortInfoError> {
        match Source::from_index(port_number).display_name() {
            Some(name) => Ok(name),
            None => Err(PortInfoError::CannotRetrievePortName)
        }
    }

    pub fn connect<F, T: Send>(
        self, port_number: usize, port_name: &str, callback: F, data: T
    ) -> Result<MidiInputConnection<T>, ConnectError<MidiInput>>
        where F: FnMut(f64, &[u8], &mut T) + Send + 'static {
        unimplemented!()
    }

    pub fn create_virtual<F, T: Send>(
        self, port_name: &str, callback: F, data: T
    ) -> Result<MidiInputConnection<T>, ConnectError<Self>>
    where F: FnMut(f64, &[u8], &mut T) + Send + 'static {
        unimplemented!()
    }
}

pub struct MidiInputConnection<T> {
    handler_data: Box<HandlerData<T>>,
}

/// This is all the data that is stored on the heap as long as a connection
/// is opened and passed to the callback handler.
///
/// It is important that `user_data` is the last field to not influence
/// offsets after monomorphization.
struct HandlerData<T> {
    last_time: Option<u64>,
    ignore_flags: Ignore,
    //callback: Box<FnMut(f64, &[u8], &mut T)+Send>,
    user_data: Option<T>
}

impl<T> MidiInputConnection<T> {
    pub fn close(self) -> (MidiInput, T) {
        unimplemented!()
    }
}

pub struct MidiOutput {
    client: Client
}

impl MidiOutput {
    pub fn new(client_name: &str) -> Result<Self, InitError> {
        match Client::new(client_name) {
            Ok(cl) => Ok(MidiOutput { client: cl }),
            Err(_) => Err(InitError)
        }

    }

    pub fn port_count(&self) -> usize {
        Destinations::count()
    }

    pub fn port_name(&self, port_number: usize) -> Result<String, PortInfoError> {
        match Destination::from_index(port_number).display_name() {
            Some(name) => Ok(name),
            None => Err(PortInfoError::CannotRetrievePortName)
        }
    }

    pub fn connect(self, port_number: usize, port_name: &str) -> Result<MidiOutputConnection, ConnectError<MidiOutput>> {
        let port = match self.client.output_port(port_name) {
            Ok(p) => p,
            Err(_) => return Err(ConnectError::other("failed to create output port", self))
        };
        // TODO: handle failure of from_index for invalid index
        let dest = Destination::from_index(port_number);
        Ok(MidiOutputConnection {
            client: self.client,
            details: OutputConnectionDetails::Explicit(port, dest)
        })
    }

    pub fn create_virtual(self, port_name: &str) -> Result<MidiOutputConnection, ConnectError<MidiOutput>> {
        let vrt = match self.client.virtual_source(port_name) {
            Ok(p) => p,
            Err(_) => return Err(ConnectError::other("failed to create virtual MIDI source", self))
        };
        Ok(MidiOutputConnection {
            client: self.client,
            details: OutputConnectionDetails::Virtual(vrt)
        })
    }
}

enum OutputConnectionDetails {
    Explicit(OutputPort, Destination),
    Virtual(VirtualSource)
}

pub struct MidiOutputConnection {
    client: Client,
    details: OutputConnectionDetails
}

impl MidiOutputConnection {
    pub fn close(self) -> MidiOutput {
        MidiOutput { client: self.client }
    }

    pub fn send(&mut self, message: &[u8]) -> Result<(), SendError> {
        // TODO: get rid of to_vec(), there should be no need to allocate here
        let packets = PacketBuffer::from_data(0, message.to_vec());
        match self.details {
            OutputConnectionDetails::Explicit(ref port, ref dest) => {
                port.send(&dest, &packets).map_err(|_| SendError::Other("error sending MIDI message to port"))
            },
            OutputConnectionDetails::Virtual(ref vrt) => {
                vrt.received(&packets).map_err(|_| SendError::Other("error sending MIDI to virtual destinations"))
            }
        }

    }
}<commit_msg>Implement more of CoreMIDI backend (currently does not compile)<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]

use ::errors::*;
use ::Ignore;

use ::coremidi::*;

pub struct MidiInput {
    client: Client,
    ignore_flags: Ignore
}

impl MidiInput {
    pub fn new(client_name: &str) -> Result<Self, InitError> {
        match Client::new(client_name) {
            Ok(cl) => Ok(MidiInput { client: cl, ignore_flags: Ignore::None }),
            Err(_) => Err(InitError)
        }
    }

    pub fn ignore(&mut self, flags: Ignore) {
        self.ignore_flags = flags;
    }

    pub fn port_count(&self) -> usize {
        Sources::count()
    }

    pub fn port_name(&self, port_number: usize) -> Result<String, PortInfoError> {
        match Source::from_index(port_number).display_name() {
            Some(name) => Ok(name),
            None => Err(PortInfoError::CannotRetrievePortName)
        }
    }

    pub fn connect<F, T: Send + 'static>(
        self, port_number: usize, port_name: &str, callback: F, data: T
    ) -> Result<MidiInputConnection<T>, ConnectError<MidiInput>>
        where F: FnMut(f64, &[u8], &mut T) + Send + 'static {
        // TODO: handle failure of from_index for invalid index
        let src = Source::from_index(port_number);
        let data_ref = &mut data;
        let port = match self.client.input_port(port_name, move |packets| {
            // TODO: filtering; maybe merge SysEx (if they can be split)
            for p in packets.iter() {
                callback(0.0, p.data(), data_ref)
            }
        }) {
            Ok(p) => p,
            Err(_) => return Err(ConnectError::other("error creating MIDI input port", self))
        };
        if let Err(_) = port.connect_source(&src) {
            return Err(ConnectError::other("error connecting MIDI input port", self));
        }
        Ok(MidiInputConnection {
            client: self.client,
            details: InputConnectionDetails::Explicit(port),
            handler_data: HandlerData {
                ignore_flags: self.ignore_flags,
                user_data: data
            }
        })
    }

    pub fn create_virtual<F, T: Send>(
        self, port_name: &str, callback: F, data: T
    ) -> Result<MidiInputConnection<T>, ConnectError<MidiInput>>
    where F: FnMut(f64, &[u8], &mut T) + Send + 'static {
        unimplemented!()
    }
}

enum InputConnectionDetails {
    Explicit(InputPort),
    Virtual(VirtualDestination)
}

pub struct MidiInputConnection<T> {
    client: Client,
    details: InputConnectionDetails,
    handler_data: HandlerData<T>
}

/// This is all the data that is stored on the heap as long as a connection
/// is opened and passed to the callback handler.
///
/// It is important that `user_data` is the last field to not influence
/// offsets after monomorphization.
struct HandlerData<T> {
    //last_time: Option<u64>,
    ignore_flags: Ignore,
    //callback: Box<FnMut(f64, &[u8], &mut T)+Send>,
    user_data: T //Option<T>
}

impl<T> MidiInputConnection<T> {
    pub fn close(self) -> (MidiInput, T) {
        (MidiInput { client: self.client, ignore_flags: self.handler_data.ignore_flags }, self.handler_data.user_data)
    }
}

pub struct MidiOutput {
    client: Client
}

impl MidiOutput {
    pub fn new(client_name: &str) -> Result<Self, InitError> {
        match Client::new(client_name) {
            Ok(cl) => Ok(MidiOutput { client: cl }),
            Err(_) => Err(InitError)
        }
    }

    pub fn port_count(&self) -> usize {
        Destinations::count()
    }

    pub fn port_name(&self, port_number: usize) -> Result<String, PortInfoError> {
        match Destination::from_index(port_number).display_name() {
            Some(name) => Ok(name),
            None => Err(PortInfoError::CannotRetrievePortName)
        }
    }

    pub fn connect(self, port_number: usize, port_name: &str) -> Result<MidiOutputConnection, ConnectError<MidiOutput>> {
        // TODO: handle failure of from_index for invalid index
        let dest = Destination::from_index(port_number as usize);
        let port = match self.client.output_port(port_name) {
            Ok(p) => p,
            Err(_) => return Err(ConnectError::other("error creating MIDI output port", self))
        };
        // TODO: handle failure of from_index for invalid index
        let dest = Destination::from_index(port_number);
        Ok(MidiOutputConnection {
            client: self.client,
            details: OutputConnectionDetails::Explicit(port, dest)
        })
    }

    pub fn create_virtual(self, port_name: &str) -> Result<MidiOutputConnection, ConnectError<MidiOutput>> {
        let vrt = match self.client.virtual_source(port_name) {
            Ok(p) => p,
            Err(_) => return Err(ConnectError::other("error creating virtual MIDI source", self))
        };
        Ok(MidiOutputConnection {
            client: self.client,
            details: OutputConnectionDetails::Virtual(vrt)
        })
    }
}

enum OutputConnectionDetails {
    Explicit(OutputPort, Destination),
    Virtual(VirtualSource)
}

pub struct MidiOutputConnection {
    client: Client,
    details: OutputConnectionDetails
}

impl MidiOutputConnection {
    pub fn close(self) -> MidiOutput {
        MidiOutput { client: self.client }
    }

    pub fn send(&mut self, message: &[u8]) -> Result<(), SendError> {
        // TODO: get rid of to_vec(), there should be no need to allocate here
        let packets = PacketBuffer::from_data(0, message.to_vec());
        match self.details {
            OutputConnectionDetails::Explicit(ref port, ref dest) => {
                port.send(&dest, &packets).map_err(|_| SendError::Other("error sending MIDI message to port"))
            },
            OutputConnectionDetails::Virtual(ref vrt) => {
                vrt.received(&packets).map_err(|_| SendError::Other("error sending MIDI to virtual destinations"))
            }
        }

    }
}<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate cargo_registry;
extern crate openssl;
extern crate postgres;
extern crate semver;
extern crate time;

use std::collections::HashMap;
use std::env;
use std::time::Duration;

use cargo_registry::{VersionDownload, Version, Model};

static LIMIT: i64 = 1000;

#[allow(dead_code)] // dead in tests
fn main() {
    let daemon = env::args().nth(1).as_ref().map(|s| &s[..])
                    == Some("daemon");
    let sleep = env::args().nth(2).map(|s| s.parse().unwrap());
    loop {
        let conn = cargo_registry::db::connect_now();
        update(&conn).unwrap();
        drop(conn);
        if daemon {
            std::thread::sleep(Duration::new(sleep.unwrap(), 0));
        } else {
            break
        }
    }
}

fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> {
    let mut max = 0;
    loop {
        // FIXME(rust-lang/rust#27401): weird declaration to make sure this
        // variable gets dropped.
        let tx; tx = conn.transaction()?;
        {
            let stmt = tx.prepare("SELECT * FROM version_downloads \
                                        WHERE processed = FALSE AND id > $1
                                        ORDER BY id ASC
                                        LIMIT $2")?;
            let mut rows = stmt.query(&[&max, &LIMIT])?;
            match collect(&tx, &mut rows)? {
                None => break,
                Some(m) => max = m,
            }
        }
        tx.set_commit();
        tx.finish()?;
    }
    Ok(())
}

fn collect(tx: &postgres::transaction::Transaction,
           rows: &mut postgres::rows::Rows) -> postgres::Result<Option<i32>> {
    use time::Duration;

    // Anything older than 24 hours ago will be frozen and will not be queried
    // against again.
    let cutoff = time::now_utc().to_timespec();
    let cutoff = cutoff - Duration::days(1);

    let mut map = HashMap::new();
    for row in rows.iter() {
        let download: VersionDownload = Model::from_row(&row);
        assert!(map.insert(download.id, download).is_none());
    }
    println!("updating {} versions (cutoff {})", map.len(),
             time::at(cutoff).rfc822());
    if map.len() == 0 {
        return Ok(None)
    }

    let mut max = 0;
    let mut total = 0;
    for (id, download) in map.iter() {
        if *id > max {
            max = *id;
        }
        if download.date > cutoff && download.counted == download.downloads {
            continue
        }
        let amt = download.downloads - download.counted;

        // Flag this row as having been processed if we're passed the cutoff,
        // and unconditionally increment the number of counted downloads.
        tx.execute("UPDATE version_downloads
                         SET processed = $2, counted = counted + $3
                         WHERE id = $1",
                   &[id, &(download.date < cutoff), &amt])?;
        println!("{}\n{}", time::at(download.date).rfc822(),
                 time::at(cutoff).rfc822());
        total += amt as i64;

        if amt == 0 {
            continue
        }

        let crate_id = Version::find(tx, download.version_id).unwrap().crate_id;

        // Update the total number of version downloads
        tx.execute("UPDATE versions
                         SET downloads = downloads + $1
                         WHERE id = $2",
                   &[&amt, &download.version_id])?;
        // Update the total number of crate downloads
        tx.execute("UPDATE crates SET downloads = downloads + $1
                         WHERE id = $2", &[&amt, &crate_id])?;

        // Update the total number of crate downloads for today
        let cnt = tx.execute("UPDATE crate_downloads
                                   SET downloads = downloads + $2
                                   WHERE crate_id = $1 AND date = date($3)",
                             &[&crate_id, &amt, &download.date])?;
        if cnt == 0 {
            tx.execute("INSERT INTO crate_downloads
                             (crate_id, downloads, date)
                             VALUES ($1, $2, $3)",
                       &[&crate_id, &amt, &download.date])?;
        }
    }

    // After everything else is done, update the global counter of total
    // downloads.
    tx.execute("UPDATE metadata SET total_downloads = total_downloads + $1",
               &[&total])?;

    Ok(Some(max))
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use time;
    use time::Duration;

    use postgres;
    use semver;

    use cargo_registry::{Version, Crate, User, Model, env};

    fn conn() -> postgres::Connection {
        postgres::Connection::connect(&env("TEST_DATABASE_URL")[..],
                                      postgres::TlsMode::None).unwrap()
    }

    fn user(conn: &postgres::transaction::Transaction) -> User{
        User::find_or_insert(conn, 2, "login", None, None, None,
                             "access_token", "api_token").unwrap()
    }

    fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) {
        let stmt = tx.prepare("SELECT * FROM crate_downloads
                               WHERE crate_id = $1").unwrap();
        let dl: i32 = stmt.query(&[&id]).unwrap().iter()
                          .next().unwrap().get("downloads");
        assert_eq!(dl, expected as i32);
    }

    #[test]
    fn increment() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, &None,
                                          &None, &None, &None, &None,
                                          &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id)
                    VALUES ($1)",
                   &[&version.id]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, processed)
                    VALUES ($1, true)",
                   &[&version.id]).unwrap();
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1);
        assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1);
        crate_downloads(&tx, krate.id, 1);
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1);
    }

    #[test]
    fn set_processed_true() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, current_date - interval '2 days', false)",
                   &[&version.id]).unwrap();
        ::update(&tx).unwrap();
        let stmt = tx.prepare("SELECT processed FROM version_downloads
                               WHERE version_id = $1").unwrap();
        let processed: bool = stmt.query(&[&version.id]).unwrap().iter()
                                  .next().unwrap().get("processed");
        assert!(processed);
    }

    #[test]
    fn dont_process_recent_row() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        let time = time::now_utc().to_timespec() - Duration::hours(2);
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, $2, false)",
                   &[&version.id, &time]).unwrap();
        ::update(&tx).unwrap();
        let stmt = tx.prepare("SELECT processed FROM version_downloads
                               WHERE version_id = $1").unwrap();
        let processed: bool = stmt.query(&[&version.id]).unwrap().iter()
                                  .next().unwrap().get("processed");
        assert!(!processed);
    }

    #[test]
    fn increment_a_little() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("UPDATE versions
                       SET updated_at = current_date - interval '2 hours'",
                   &[]).unwrap();
        tx.execute("UPDATE crates
                       SET updated_at = current_date - interval '2 hours'",
                   &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 1, current_date, false)",
                   &[&version.id]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id)
                    VALUES ($1)",
                   &[&version.id]).unwrap();

        let version_before = Version::find(&tx, version.id).unwrap();
        let krate_before = Crate::find(&tx, krate.id).unwrap();
        ::update(&tx).unwrap();
        let version2 = Version::find(&tx, version.id).unwrap();
        assert_eq!(version2.downloads, 2);
        assert_eq!(version2.updated_at, version_before.updated_at);
        let krate2 = Crate::find(&tx, krate.id).unwrap();
        assert_eq!(krate2.downloads, 2);
        assert_eq!(krate2.updated_at, krate_before.updated_at);
        crate_downloads(&tx, krate.id, 2);
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 2);
    }

    #[test]
    fn set_processed_no_set_updated_at() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("UPDATE versions
                       SET updated_at = current_date - interval '2 days'",
                   &[]).unwrap();
        tx.execute("UPDATE crates
                       SET updated_at = current_date - interval '2 days'",
                   &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, current_date - interval '2 days', false)",
                   &[&version.id]).unwrap();

        let version_before = Version::find(&tx, version.id).unwrap();
        let krate_before = Crate::find(&tx, krate.id).unwrap();
        ::update(&tx).unwrap();
        let version2 = Version::find(&tx, version.id).unwrap();
        assert_eq!(version2.updated_at, version_before.updated_at);
        let krate2 = Crate::find(&tx, krate.id).unwrap();
        assert_eq!(krate2.updated_at, krate_before.updated_at);
    }
}
<commit_msg>Remove logging of dates from update-downloads<commit_after>#![deny(warnings)]

extern crate cargo_registry;
extern crate openssl;
extern crate postgres;
extern crate semver;
extern crate time;

use std::collections::HashMap;
use std::env;
use std::time::Duration;

use cargo_registry::{VersionDownload, Version, Model};

static LIMIT: i64 = 1000;

#[allow(dead_code)] // dead in tests
fn main() {
    let daemon = env::args().nth(1).as_ref().map(|s| &s[..])
                    == Some("daemon");
    let sleep = env::args().nth(2).map(|s| s.parse().unwrap());
    loop {
        let conn = cargo_registry::db::connect_now();
        update(&conn).unwrap();
        drop(conn);
        if daemon {
            std::thread::sleep(Duration::new(sleep.unwrap(), 0));
        } else {
            break
        }
    }
}

fn update(conn: &postgres::GenericConnection) -> postgres::Result<()> {
    let mut max = 0;
    loop {
        // FIXME(rust-lang/rust#27401): weird declaration to make sure this
        // variable gets dropped.
        let tx; tx = conn.transaction()?;
        {
            let stmt = tx.prepare("SELECT * FROM version_downloads \
                                        WHERE processed = FALSE AND id > $1
                                        ORDER BY id ASC
                                        LIMIT $2")?;
            let mut rows = stmt.query(&[&max, &LIMIT])?;
            match collect(&tx, &mut rows)? {
                None => break,
                Some(m) => max = m,
            }
        }
        tx.set_commit();
        tx.finish()?;
    }
    Ok(())
}

fn collect(tx: &postgres::transaction::Transaction,
           rows: &mut postgres::rows::Rows) -> postgres::Result<Option<i32>> {
    use time::Duration;

    // Anything older than 24 hours ago will be frozen and will not be queried
    // against again.
    let cutoff = time::now_utc().to_timespec();
    let cutoff = cutoff - Duration::days(1);

    let mut map = HashMap::new();
    for row in rows.iter() {
        let download: VersionDownload = Model::from_row(&row);
        assert!(map.insert(download.id, download).is_none());
    }
    println!("updating {} versions (cutoff {})", map.len(),
             time::at(cutoff).rfc822());
    if map.len() == 0 {
        return Ok(None)
    }

    let mut max = 0;
    let mut total = 0;
    for (id, download) in map.iter() {
        if *id > max {
            max = *id;
        }
        if download.date > cutoff && download.counted == download.downloads {
            continue
        }
        let amt = download.downloads - download.counted;

        // Flag this row as having been processed if we're passed the cutoff,
        // and unconditionally increment the number of counted downloads.
        tx.execute("UPDATE version_downloads
                         SET processed = $2, counted = counted + $3
                         WHERE id = $1",
                   &[id, &(download.date < cutoff), &amt])?;
        total += amt as i64;

        if amt == 0 {
            continue
        }

        let crate_id = Version::find(tx, download.version_id).unwrap().crate_id;

        // Update the total number of version downloads
        tx.execute("UPDATE versions
                         SET downloads = downloads + $1
                         WHERE id = $2",
                   &[&amt, &download.version_id])?;
        // Update the total number of crate downloads
        tx.execute("UPDATE crates SET downloads = downloads + $1
                         WHERE id = $2", &[&amt, &crate_id])?;

        // Update the total number of crate downloads for today
        let cnt = tx.execute("UPDATE crate_downloads
                                   SET downloads = downloads + $2
                                   WHERE crate_id = $1 AND date = date($3)",
                             &[&crate_id, &amt, &download.date])?;
        if cnt == 0 {
            tx.execute("INSERT INTO crate_downloads
                             (crate_id, downloads, date)
                             VALUES ($1, $2, $3)",
                       &[&crate_id, &amt, &download.date])?;
        }
    }

    // After everything else is done, update the global counter of total
    // downloads.
    tx.execute("UPDATE metadata SET total_downloads = total_downloads + $1",
               &[&total])?;

    Ok(Some(max))
}

#[cfg(test)]
mod test {
    use std::collections::HashMap;

    use time;
    use time::Duration;

    use postgres;
    use semver;

    use cargo_registry::{Version, Crate, User, Model, env};

    fn conn() -> postgres::Connection {
        postgres::Connection::connect(&env("TEST_DATABASE_URL")[..],
                                      postgres::TlsMode::None).unwrap()
    }

    fn user(conn: &postgres::transaction::Transaction) -> User{
        User::find_or_insert(conn, 2, "login", None, None, None,
                             "access_token", "api_token").unwrap()
    }

    fn crate_downloads(tx: &postgres::transaction::Transaction, id: i32, expected: usize) {
        let stmt = tx.prepare("SELECT * FROM crate_downloads
                               WHERE crate_id = $1").unwrap();
        let dl: i32 = stmt.query(&[&id]).unwrap().iter()
                          .next().unwrap().get("downloads");
        assert_eq!(dl, expected as i32);
    }

    #[test]
    fn increment() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None, &None,
                                          &None, &None, &None, &None,
                                          &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id)
                    VALUES ($1)",
                   &[&version.id]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, processed)
                    VALUES ($1, true)",
                   &[&version.id]).unwrap();
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1);
        assert_eq!(Crate::find(&tx, krate.id).unwrap().downloads, 1);
        crate_downloads(&tx, krate.id, 1);
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 1);
    }

    #[test]
    fn set_processed_true() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, current_date - interval '2 days', false)",
                   &[&version.id]).unwrap();
        ::update(&tx).unwrap();
        let stmt = tx.prepare("SELECT processed FROM version_downloads
                               WHERE version_id = $1").unwrap();
        let processed: bool = stmt.query(&[&version.id]).unwrap().iter()
                                  .next().unwrap().get("processed");
        assert!(processed);
    }

    #[test]
    fn dont_process_recent_row() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        let time = time::now_utc().to_timespec() - Duration::hours(2);
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, $2, false)",
                   &[&version.id, &time]).unwrap();
        ::update(&tx).unwrap();
        let stmt = tx.prepare("SELECT processed FROM version_downloads
                               WHERE version_id = $1").unwrap();
        let processed: bool = stmt.query(&[&version.id]).unwrap().iter()
                                  .next().unwrap().get("processed");
        assert!(!processed);
    }

    #[test]
    fn increment_a_little() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("UPDATE versions
                       SET updated_at = current_date - interval '2 hours'",
                   &[]).unwrap();
        tx.execute("UPDATE crates
                       SET updated_at = current_date - interval '2 hours'",
                   &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 1, current_date, false)",
                   &[&version.id]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id)
                    VALUES ($1)",
                   &[&version.id]).unwrap();

        let version_before = Version::find(&tx, version.id).unwrap();
        let krate_before = Crate::find(&tx, krate.id).unwrap();
        ::update(&tx).unwrap();
        let version2 = Version::find(&tx, version.id).unwrap();
        assert_eq!(version2.downloads, 2);
        assert_eq!(version2.updated_at, version_before.updated_at);
        let krate2 = Crate::find(&tx, krate.id).unwrap();
        assert_eq!(krate2.downloads, 2);
        assert_eq!(krate2.updated_at, krate_before.updated_at);
        crate_downloads(&tx, krate.id, 2);
        ::update(&tx).unwrap();
        assert_eq!(Version::find(&tx, version.id).unwrap().downloads, 2);
    }

    #[test]
    fn set_processed_no_set_updated_at() {
        let conn = conn();
        let tx = conn.transaction().unwrap();
        let user = user(&tx);
        let krate = Crate::find_or_insert(&tx, "foo", user.id, &None,
                                          &None, &None, &None, &None,
                                          &None, &None, None).unwrap();
        let version = Version::insert(&tx, krate.id,
                                      &semver::Version::parse("1.0.0").unwrap(),
                                      &HashMap::new(), &[]).unwrap();
        tx.execute("UPDATE versions
                       SET updated_at = current_date - interval '2 days'",
                   &[]).unwrap();
        tx.execute("UPDATE crates
                       SET updated_at = current_date - interval '2 days'",
                   &[]).unwrap();
        tx.execute("INSERT INTO version_downloads \
                    (version_id, downloads, counted, date, processed)
                    VALUES ($1, 2, 2, current_date - interval '2 days', false)",
                   &[&version.id]).unwrap();

        let version_before = Version::find(&tx, version.id).unwrap();
        let krate_before = Crate::find(&tx, krate.id).unwrap();
        ::update(&tx).unwrap();
        let version2 = Version::find(&tx, version.id).unwrap();
        assert_eq!(version2.updated_at, version_before.updated_at);
        let krate2 = Crate::find(&tx, krate.id).unwrap();
        assert_eq!(krate2.updated_at, krate_before.updated_at);
    }
}
<|endoftext|>