<commit_before>extern crate nalgebra as na;

use na::{Vector3, Rotation3};

use ai;
use gameutil;
use bf_info;
use terrain;

const SUPPLY_TIME: i32         = bf_info::TIME_MULTIPLIER * 1; // how often are supplies picked up
const SUPPLY_DISTANCE: f64     = 5.0; // distance where supply can be picked up

const SOLDIER_MAX_FOOD: i32 = 8;
const SOLDIER_MAX_AMMO: i32 = 40;

const MAX_TRUCK_SPEED_GRASS:  f64 = 18.0;
const MAX_TRUCK_SPEED_FOREST: f64 = 2.0;

pub fn execute_action(action: &ai::Action, bf: &mut bf_info::Battlefield, prev_curr_time: f64) -> () {
    match action {
        &ai::Action::NoAction(s)            => idle_soldier(bf, s, prev_curr_time),
        &ai::Action::MoveAction(s, diff)    => move_soldier(bf, s, diff),
        &ai::Action::ShootAction(from, to)  => shoot_soldier(from, to, bf),
        &ai::Action::BoardAction(s, tr)     => board_truck(bf, s, tr),
        &ai::Action::DriveAction(s, st, ga) => drive_truck(bf, s, st, ga),
        &ai::Action::DisembarkAction(s)     => disembark_truck(&mut bf.movers.boarded_map, s),
    }
}

// true every <tick> seconds
pub fn has_tick(bf: &bf_info::Battlefield, prev_curr_time: f64, tick: i32) -> bool {
    let pt = prev_curr_time as u64 / tick as u64;
    let ct = bf.curr_time   as u64 / tick as u64;
    pt != ct
}

fn move_soldier(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, diff: Vector3<f64>) -> () {
    if bf_info::soldier_boarded(&bf.movers.boarded_map, sid) != None {
        return;
    }
    let ref mut s = bf.movers.soldiers[sid.id];
    s.position += gameutil::truncate(diff, bf_info::SOLDIER_SPEED * bf.frame_time as f64);
}

fn idle_soldier(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, prev_curr_time: f64) -> () {
    let check_supply = has_tick(bf, prev_curr_time, SUPPLY_TIME);
    let ref mut soldier = bf.movers.soldiers[sid.id];
    if soldier.shot_timer > 0.0 {
        soldier.shot_timer -= bf.frame_time as f64;
    }

    if check_supply {
        for ref mut supply in &mut bf.supply_points {
            let dist = gameutil::dist(soldier, &supply.position);
            if dist < SUPPLY_DISTANCE {
                if soldier.food <= SOLDIER_MAX_FOOD - 1  && supply.amount_food >= 1 {
                    soldier.food += 1;
                    supply.amount_food -= 1;
                }
                if soldier.ammo <= SOLDIER_MAX_AMMO - 10 && supply.amount_ammo >= 10 {
                    soldier.ammo += 10;
                    supply.amount_ammo -= 10;
                }
            }
        }
    }
}

fn disembark_all_from_truck(boarded_map: &mut bf_info::BoardedMap, tid: bf_info::TruckID) -> () {
    if let Some(bds) = boarded_map.map.get_mut(&tid) {
        bds.clear();
    }
}

pub fn destroy_truck(boarded_map: &mut bf_info::BoardedMap, truck: &mut bf_info::Truck) -> () {
    truck.alive = false;
    disembark_all_from_truck(boarded_map, truck.id);
}

pub fn kill_soldier(boarded_map: &mut bf_info::BoardedMap, soldier: &mut bf_info::Soldier) -> () {
    soldier.alive = false;
    disembark_truck(boarded_map, soldier.id);
}

fn shoot_soldier(from: bf_info::SoldierID, to: bf_info::SoldierID, mut bf: &mut bf_info::Battlefield) {
    if bf_info::soldier_boarded(&bf.movers.boarded_map, from) != None {
        return;
    }

    if bf.movers.soldiers[from.id].ammo <= 0 {
        return;
    }

    if bf.movers.soldiers[from.id].shot_timer <= 0.0 {
        bf.movers.soldiers[from.id].shot_timer = 1.0;
        bf.movers.soldiers[from.id].ammo -= 1;
        let dist = gameutil::dist(&bf.movers.soldiers[from.id], &bf.movers.soldiers[to.id].position);
        let threshold = if dist > 100.0 { 0.0 } else { -dist * 0.005 + 1.0 };
        let hit_num = bf.rand();
        if hit_num < threshold {
            kill_soldier(&mut bf.movers.boarded_map, &mut bf.movers.soldiers[to.id]);
        }
        println!("{} shoots at {}! {} ({} - threshold was {})",
        from.id, to.id, hit_num, !bf.movers.soldiers[to.id].alive, threshold);
    }
}

fn board_truck(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, tid: bf_info::TruckID) -> () {
    if bf_info::truck_free_by_id(bf, tid) &&
        gameutil::dist(&bf.movers.soldiers[sid.id], &bf.movers.trucks[tid.id].position) < 3.0 {
        set_boarded(&mut bf.movers, sid, tid);
    }
}

fn drive_truck(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, steering: f64, gas: f64) -> () {
    let mtid = bf_info::soldier_boarded(&bf.movers.boarded_map, sid);
    if mtid == None {
        return;
    }

    let ref mut truck = bf.movers.trucks[mtid.unwrap().0.id];

    if !truck.alive {
        return;
    }

    truck.direction = na::rotate(
        &Rotation3::new(Vector3::new(0.0, 0.2 * gameutil::clamp(-1.0, 1.0, steering) * bf.frame_time, 0.0)),
        &truck.direction);
    truck.speed += gameutil::clamp(0.0,  1.0, gas) * 2.0  * bf.frame_time;
    truck.speed += gameutil::clamp(-1.0, 0.0, gas) * 10.0 * bf.frame_time;
    let forest = terrain::get_forest_at(&bf.ground, truck.position.x, truck.position.z);
    let max_speed = gameutil::mix(MAX_TRUCK_SPEED_GRASS, MAX_TRUCK_SPEED_FOREST, forest);
    truck.speed = gameutil::clamp(0.0, max_speed, truck.speed);
    truck.position += truck.direction * truck.speed * bf.frame_time;
}

fn disembark_truck(boarded_map: &mut bf_info::BoardedMap, sid: bf_info::SoldierID) -> () {
    let mid = bf_info::soldier_boarded(boarded_map, sid);
    println!("Soldier {} disembarked", sid.id);
    match mid {
        None => (),
        Some((tid, role)) => {
            unset_boarded(boarded_map, sid);
            if role == bf_info::BoardRole::Driver {
                let boarded = boarded_map.map.get_mut(&tid).unwrap();
                if boarded.len() > 0 {
                    boarded[0].role = bf_info::BoardRole::Driver;
                }
            }
        },
    }
}

fn set_boarded(mut mov: &mut bf_info::Movers, sid: bf_info::SoldierID, tid: bf_info::TruckID) -> () {
    if bf_info::soldier_boarded(&mov.boarded_map, sid) != None {
        println!("{} tried to board but is already boarded", sid.id);
        return;
    }

    match mov.boarded_map.map.get_mut(&tid) {
        Some(bds) => {
            let ln = bds.len();
            let role = if ln == 0 {
                bf_info::BoardRole::Driver
            } else {
                bf_info::BoardRole::Passenger
            };
            if ln < bf_info::TRUCK_NUM_PASSENGERS as usize + 1 {
                bds.push(bf_info::Boarded{sid: sid, role: role });
                println!("{} embarked truck {}!", sid.id, tid.id);
            } else {
                println!("{} tried to board but failed", sid.id);
            }
            return;
        },
        None => (),
    }
    mov.boarded_map.map.insert(tid, vec![bf_info::Boarded{sid: sid, role: bf_info::BoardRole::Driver}]);
    println!("{} embarked truck {}!", sid.id, tid.id);
}

fn unset_boarded(mut boarded_map: &mut bf_info::BoardedMap, sid: bf_info::SoldierID) -> () {
    for (_, ref mut bds) in &mut boarded_map.map {
        bds.retain(|ref mut bd| bd.sid != sid);
    }
}

<commit_msg>remove duplicate log messages<commit_after>extern crate nalgebra as na;

use na::{Vector3, Rotation3};

use ai;
use gameutil;
use bf_info;
use terrain;

const SUPPLY_TIME: i32         = bf_info::TIME_MULTIPLIER * 1; // how often are supplies picked up
const SUPPLY_DISTANCE: f64     = 5.0; // distance where supply can be picked up

const SOLDIER_MAX_FOOD: i32 = 8;
const SOLDIER_MAX_AMMO: i32 = 40;

const MAX_TRUCK_SPEED_GRASS:  f64 = 18.0;
const MAX_TRUCK_SPEED_FOREST: f64 = 2.0;

pub fn execute_action(action: &ai::Action, bf: &mut bf_info::Battlefield, prev_curr_time: f64) -> () {
    match action {
        &ai::Action::NoAction(s)            => idle_soldier(bf, s, prev_curr_time),
        &ai::Action::MoveAction(s, diff)    => move_soldier(bf, s, diff),
        &ai::Action::ShootAction(from, to)  => shoot_soldier(from, to, bf),
        &ai::Action::BoardAction(s, tr)     => board_truck(bf, s, tr),
        &ai::Action::DriveAction(s, st, ga) => drive_truck(bf, s, st, ga),
        &ai::Action::DisembarkAction(s)     => disembark_truck(&mut bf.movers.boarded_map, s),
    }
}

// true every <tick> seconds
pub fn has_tick(bf: &bf_info::Battlefield, prev_curr_time: f64, tick: i32) -> bool {
    let pt = prev_curr_time as u64 / tick as u64;
    let ct = bf.curr_time   as u64 / tick as u64;
    pt != ct
}

fn move_soldier(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, diff: Vector3<f64>) -> () {
    if bf_info::soldier_boarded(&bf.movers.boarded_map, sid) != None {
        return;
    }
    let ref mut s = bf.movers.soldiers[sid.id];
    s.position += gameutil::truncate(diff, bf_info::SOLDIER_SPEED * bf.frame_time as f64);
}

fn idle_soldier(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, prev_curr_time: f64) -> () {
    let check_supply = has_tick(bf, prev_curr_time, SUPPLY_TIME);
    let ref mut soldier = bf.movers.soldiers[sid.id];
    if soldier.shot_timer > 0.0 {
        soldier.shot_timer -= bf.frame_time as f64;
    }

    if check_supply {
        for ref mut supply in &mut bf.supply_points {
            let dist = gameutil::dist(soldier, &supply.position);
            if dist < SUPPLY_DISTANCE {
                if soldier.food <= SOLDIER_MAX_FOOD - 1  && supply.amount_food >= 1 {
                    soldier.food += 1;
                    supply.amount_food -= 1;
                }
                if soldier.ammo <= SOLDIER_MAX_AMMO - 10 && supply.amount_ammo >= 10 {
                    soldier.ammo += 10;
                    supply.amount_ammo -= 10;
                }
            }
        }
    }
}

fn disembark_all_from_truck(boarded_map: &mut bf_info::BoardedMap, tid: bf_info::TruckID) -> () {
    if let Some(bds) = boarded_map.map.get_mut(&tid) {
        bds.clear();
    }
}

pub fn destroy_truck(boarded_map: &mut bf_info::BoardedMap, truck: &mut bf_info::Truck) -> () {
    truck.alive = false;
    disembark_all_from_truck(boarded_map, truck.id);
}

pub fn kill_soldier(boarded_map: &mut bf_info::BoardedMap, soldier: &mut bf_info::Soldier) -> () {
    soldier.alive = false;
    disembark_truck(boarded_map, soldier.id);
}

fn shoot_soldier(from: bf_info::SoldierID, to: bf_info::SoldierID, mut bf: &mut bf_info::Battlefield) {
    if bf_info::soldier_boarded(&bf.movers.boarded_map, from) != None {
        return;
    }

    if bf.movers.soldiers[from.id].ammo <= 0 {
        return;
    }

    if bf.movers.soldiers[from.id].shot_timer <= 0.0 {
        bf.movers.soldiers[from.id].shot_timer = 1.0;
        bf.movers.soldiers[from.id].ammo -= 1;
        let dist = gameutil::dist(&bf.movers.soldiers[from.id], &bf.movers.soldiers[to.id].position);
        let threshold = if dist > 100.0 { 0.0 } else { -dist * 0.005 + 1.0 };
        let hit_num = bf.rand();
        if hit_num < threshold {
            kill_soldier(&mut bf.movers.boarded_map, &mut bf.movers.soldiers[to.id]);
        }
        println!("{} shoots at {}! {} ({} - threshold was {})",
        from.id, to.id, hit_num, !bf.movers.soldiers[to.id].alive, threshold);
    }
}

fn board_truck(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, tid: bf_info::TruckID) -> () {
    if bf_info::truck_free_by_id(bf, tid) &&
        gameutil::dist(&bf.movers.soldiers[sid.id], &bf.movers.trucks[tid.id].position) < 3.0 {
        set_boarded(&mut bf.movers, sid, tid);
    }
}

fn drive_truck(bf: &mut bf_info::Battlefield, sid: bf_info::SoldierID, steering: f64, gas: f64) -> () {
    let mtid = bf_info::soldier_boarded(&bf.movers.boarded_map, sid);
    if mtid == None {
        return;
    }

    let ref mut truck = bf.movers.trucks[mtid.unwrap().0.id];

    if !truck.alive {
        return;
    }

    truck.direction = na::rotate(
        &Rotation3::new(Vector3::new(0.0, 0.2 * gameutil::clamp(-1.0, 1.0, steering) * bf.frame_time, 0.0)),
        &truck.direction);
    truck.speed += gameutil::clamp(0.0,  1.0, gas) * 2.0  * bf.frame_time;
    truck.speed += gameutil::clamp(-1.0, 0.0, gas) * 10.0 * bf.frame_time;
    let forest = terrain::get_forest_at(&bf.ground, truck.position.x, truck.position.z);
    let max_speed = gameutil::mix(MAX_TRUCK_SPEED_GRASS, MAX_TRUCK_SPEED_FOREST, forest);
    truck.speed = gameutil::clamp(0.0, max_speed, truck.speed);
    truck.position += truck.direction * truck.speed * bf.frame_time;
}

fn disembark_truck(boarded_map: &mut bf_info::BoardedMap, sid: bf_info::SoldierID) -> () {
    let mid = bf_info::soldier_boarded(boarded_map, sid);
    match mid {
        None => (),
        Some((tid, role)) => {
            unset_boarded(boarded_map, sid);
            println!("Soldier {} disembarked", sid.id);
            if role == bf_info::BoardRole::Driver {
                let boarded = boarded_map.map.get_mut(&tid).unwrap();
                if boarded.len() > 0 {
                    boarded[0].role = bf_info::BoardRole::Driver;
                }
            }
        },
    }
}

fn set_boarded(mut mov: &mut bf_info::Movers, sid: bf_info::SoldierID, tid: bf_info::TruckID) -> () {
    if bf_info::soldier_boarded(&mov.boarded_map, sid) != None {
        println!("{} tried to board but is already boarded", sid.id);
        return;
    }

    match mov.boarded_map.map.get_mut(&tid) {
        Some(bds) => {
            let ln = bds.len();
            let role = if ln == 0 {
                bf_info::BoardRole::Driver
            } else {
                bf_info::BoardRole::Passenger
            };
            if ln < bf_info::TRUCK_NUM_PASSENGERS as usize + 1 {
                bds.push(bf_info::Boarded{sid: sid, role: role });
                println!("{} embarked truck {}!", sid.id, tid.id);
            } else {
                println!("{} tried to board but failed", sid.id);
            }
            return;
        },
        None => (),
    }
    mov.boarded_map.map.insert(tid, vec![bf_info::Boarded{sid: sid, role: bf_info::BoardRole::Driver}]);
    println!("{} embarked truck {}!", sid.id, tid.id);
}

fn unset_boarded(mut boarded_map: &mut bf_info::BoardedMap, sid: bf_info::SoldierID) -> () {
    for (_, ref mut bds) in &mut boarded_map.map {
        bds.retain(|ref mut bd| bd.sid != sid);
    }
}

<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::fmt;
use std::io;

use basic::LogicalType;
use schema::types::Type;
use file::metadata::{ParquetMetaData, FileMetaData, RowGroupMetaData, ColumnChunkMetaData};

/// Print Parquet metadata
#[allow(unused_must_use)]
pub fn print_parquet_metadata(out: &mut io::Write, metadata: &ParquetMetaData) {
  print_file_metadata(out, metadata.file_metadata());
  writeln!(out, "");
  writeln!(out, "");
  writeln!(out, "num of row groups: {}", metadata.num_row_groups());
  writeln!(out, "row groups:");
  writeln!(out, "");
  for (i, rg) in metadata.row_groups().iter().enumerate() {
    writeln!(out, "row group {}:", i);
    print_dashes(out, 80);
    print_row_group_metadata(out, rg);
  }
}

/// Print metadata information from `file_metadata`.
#[allow(unused_must_use)]
pub fn print_file_metadata(out: &mut io::Write, file_metadata: &FileMetaData) {
  writeln!(out, "version: {}", file_metadata.version());
  writeln!(out, "num of rows: {}", file_metadata.num_rows());
  if let Some(created_by) = file_metadata.created_by().as_ref() {
    writeln!(out, "created by: {}", created_by);
  }
  let schema = file_metadata.schema();
  print_schema(out, schema);
}

#[allow(unused_must_use)]
pub fn print_schema(out: &mut io::Write, tp: &Type) {
  // TODO: better if we can pass fmt::Write to Printer.
  // But how can we make it to accept both io::Write & fmt::Write?
  let mut s = String::new();
  {
    let mut printer = Printer::new(&mut s);
    printer.print(tp);
  }
  write!(out, "{}", s);
}

#[allow(unused_must_use)]
fn print_row_group_metadata(out: &mut io::Write, rg_metadata: &RowGroupMetaData) {
  writeln!(out, "total byte size: {}", rg_metadata.total_byte_size());
  writeln!(out, "num of rows: {}", rg_metadata.num_rows());
  writeln!(out, "");
  writeln!(out, "num of columns: {}", rg_metadata.num_columns());
  writeln!(out, "columns: ");
  for (i, cc) in rg_metadata.columns().iter().enumerate() {
    writeln!(out, "");
    writeln!(out, "column {}:", i);
    print_dashes(out, 80);
    print_column_chunk_metadata(out, cc);
  }
}

#[allow(unused_must_use)]
fn print_column_chunk_metadata(out: &mut io::Write, cc_metadata: &ColumnChunkMetaData) {
  writeln!(out, "column type: {}", cc_metadata.column_type());
  writeln!(out, "column path: {}", cc_metadata.column_path());
  let encoding_strs: Vec<_> = cc_metadata.encodings().iter()
    .map(|e| format!("{}", e)).collect();
  writeln!(out, "encodings: {}", encoding_strs.join(" "));
  let file_path_str = match cc_metadata.file_path() {
    None => "N/A",
    Some(ref fp) => *fp
  };
  writeln!(out, "file path: {}", file_path_str);
  writeln!(out, "file offset: {}", cc_metadata.file_offset());
  writeln!(out, "num of values: {}", cc_metadata.num_values());
  writeln!(out, "total compressed size (in bytes): {}", cc_metadata.compressed_size());
  writeln!(out, "total uncompressed size (in bytes): {}", cc_metadata.uncompressed_size());
  writeln!(out, "data page offset: {}", cc_metadata.data_page_offset());
  let index_page_offset_str = match cc_metadata.index_page_offset() {
    None => "N/A".to_owned(),
    Some(ipo) => ipo.to_string()
  };
  writeln!(out, "index page offset: {}", index_page_offset_str);
  let dict_page_offset_str = match cc_metadata.dictionary_page_offset() {
    None => "N/A".to_owned(),
    Some(dpo) => dpo.to_string()
  };
  writeln!(out, "dictionary page offset: {}", dict_page_offset_str);
  writeln!(out, "");
}

#[allow(unused_must_use)]
fn print_dashes(out: &mut io::Write, num: i32) {
  for _ in 0..num {
    write!(out, "-");
  }
  writeln!(out, "");
}

const INDENT_WIDTH: i32 = 2;

pub struct Printer<'a> {
  output: &'a mut fmt::Write,
  indent: i32
}

#[allow(unused_must_use)]
impl <'a> Printer<'a> {
  fn new(output: &'a mut fmt::Write) -> Self {
    Printer { output: output, indent: 0 }
  }

  fn print_indent(&mut self) {
    for _ in 0..self.indent {
      write!(self.output, " ");
    }
  }
}

#[allow(unused_must_use)]
impl<'a> Printer<'a> {
  pub fn print(&mut self, tp: &Type) {
    self.print_indent();
    match tp {
      &Type::PrimitiveType{ ref basic_info, physical_type, .. } => {
        write!(self.output, "{} {} {};", basic_info.repetition(), physical_type, basic_info.name());
      },
      &Type::GroupType{ ref basic_info, ref fields } => {
        if basic_info.has_repetition() {
          let r = basic_info.repetition();
          write!(self.output, "{} group {} ", r, basic_info.name());
          if basic_info.logical_type() != LogicalType::NONE {
            write!(self.output, "({}) ", basic_info.logical_type());
          }
          writeln!(self.output, "{{");
        } else {
          writeln!(self.output, "message {} {{", basic_info.name());
        }

        self.indent += INDENT_WIDTH;
        for c in fields {
          self.print(&c);
          writeln!(self.output, "");
        }
        self.indent -= INDENT_WIDTH;
        self.print_indent();
        write!(self.output, "}}");
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::rc::Rc;
  use schema::types::Type;
  use basic::{Type as PhysicalType, Repetition};

  #[test]
  fn test_print_primitive_type() {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      let foo = Type::primitive_type_builder("foo", PhysicalType::INT32)
        .with_repetition(Repetition::REQUIRED)
        .with_logical_type(LogicalType::INT_32)
        .build().unwrap();
      p.print(&foo);
    }
    assert_eq!(&mut s, "REQUIRED INT32 foo;");
  }

  #[test]
  fn test_print_group_type() {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      let f1 = Type::primitive_type_builder("f1", PhysicalType::INT32)
        .with_repetition(Repetition::REQUIRED)
        .with_logical_type(LogicalType::INT_32)
        .with_id(0)
        .build();
      let f2 = Type::primitive_type_builder("f2", PhysicalType::BYTE_ARRAY)
        .with_logical_type(LogicalType::UTF8)
        .with_id(1)
        .build();
      let f3 = Type::primitive_type_builder("f3", PhysicalType::FIXED_LEN_BYTE_ARRAY)
        .with_repetition(Repetition::REPEATED)
        .with_logical_type(LogicalType::INTERVAL)
        .with_length(12)
        .with_id(2)
        .build();
      let mut struct_fields = Vec::new();
      struct_fields.push(Rc::new(f1.unwrap()));
      struct_fields.push(Rc::new(f2.unwrap()));
      let foo = Type::group_type_builder("foo")
        .with_repetition(Repetition::OPTIONAL)
        .with_fields(&mut struct_fields)
        .with_id(1)
        .build().unwrap();
      let mut fields = Vec::new();
      fields.push(Rc::new(foo));
      fields.push(Rc::new(f3.unwrap()));
      let message = Type::group_type_builder("schema")
        .with_fields(&mut fields)
        .with_id(2)
        .build().unwrap();
      p.print(&message);
    }
    let expected =
"message schema {
  OPTIONAL group foo {
    REQUIRED INT32 f1;
    OPTIONAL BYTE_ARRAY f2;
  }
  REPEATED FIXED_LEN_BYTE_ARRAY f3;
}";
    assert_eq!(&mut s, expected);
  }
}
<commit_msg>Fix printer/parser incompatibility (#18)<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::fmt;
use std::io;

use basic::{LogicalType, Type as PhysicalType};
use schema::types::Type;
use file::metadata::{ParquetMetaData, FileMetaData, RowGroupMetaData, ColumnChunkMetaData};

/// Print Parquet metadata
#[allow(unused_must_use)]
pub fn print_parquet_metadata(out: &mut io::Write, metadata: &ParquetMetaData) {
  print_file_metadata(out, metadata.file_metadata());
  writeln!(out, "");
  writeln!(out, "");
  writeln!(out, "num of row groups: {}", metadata.num_row_groups());
  writeln!(out, "row groups:");
  writeln!(out, "");
  for (i, rg) in metadata.row_groups().iter().enumerate() {
    writeln!(out, "row group {}:", i);
    print_dashes(out, 80);
    print_row_group_metadata(out, rg);
  }
}

/// Print metadata information from `file_metadata`.
#[allow(unused_must_use)]
pub fn print_file_metadata(out: &mut io::Write, file_metadata: &FileMetaData) {
  writeln!(out, "version: {}", file_metadata.version());
  writeln!(out, "num of rows: {}", file_metadata.num_rows());
  if let Some(created_by) = file_metadata.created_by().as_ref() {
    writeln!(out, "created by: {}", created_by);
  }
  let schema = file_metadata.schema();
  print_schema(out, schema);
}

#[allow(unused_must_use)]
pub fn print_schema(out: &mut io::Write, tp: &Type) {
  // TODO: better if we can pass fmt::Write to Printer.
  // But how can we make it to accept both io::Write & fmt::Write?
  let mut s = String::new();
  {
    let mut printer = Printer::new(&mut s);
    printer.print(tp);
  }
  write!(out, "{}", s);
}

#[allow(unused_must_use)]
fn print_row_group_metadata(out: &mut io::Write, rg_metadata: &RowGroupMetaData) {
  writeln!(out, "total byte size: {}", rg_metadata.total_byte_size());
  writeln!(out, "num of rows: {}", rg_metadata.num_rows());
  writeln!(out, "");
  writeln!(out, "num of columns: {}", rg_metadata.num_columns());
  writeln!(out, "columns: ");
  for (i, cc) in rg_metadata.columns().iter().enumerate() {
    writeln!(out, "");
    writeln!(out, "column {}:", i);
    print_dashes(out, 80);
    print_column_chunk_metadata(out, cc);
  }
}

#[allow(unused_must_use)]
fn print_column_chunk_metadata(out: &mut io::Write, cc_metadata: &ColumnChunkMetaData) {
  writeln!(out, "column type: {}", cc_metadata.column_type());
  writeln!(out, "column path: {}", cc_metadata.column_path());
  let encoding_strs: Vec<_> = cc_metadata.encodings().iter()
    .map(|e| format!("{}", e)).collect();
  writeln!(out, "encodings: {}", encoding_strs.join(" "));
  let file_path_str = match cc_metadata.file_path() {
    None => "N/A",
    Some(ref fp) => *fp
  };
  writeln!(out, "file path: {}", file_path_str);
  writeln!(out, "file offset: {}", cc_metadata.file_offset());
  writeln!(out, "num of values: {}", cc_metadata.num_values());
  writeln!(out, "total compressed size (in bytes): {}", cc_metadata.compressed_size());
  writeln!(out, "total uncompressed size (in bytes): {}", cc_metadata.uncompressed_size());
  writeln!(out, "data page offset: {}", cc_metadata.data_page_offset());
  let index_page_offset_str = match cc_metadata.index_page_offset() {
    None => "N/A".to_owned(),
    Some(ipo) => ipo.to_string()
  };
  writeln!(out, "index page offset: {}", index_page_offset_str);
  let dict_page_offset_str = match cc_metadata.dictionary_page_offset() {
    None => "N/A".to_owned(),
    Some(dpo) => dpo.to_string()
  };
  writeln!(out, "dictionary page offset: {}", dict_page_offset_str);
  writeln!(out, "");
}

#[allow(unused_must_use)]
fn print_dashes(out: &mut io::Write, num: i32) {
  for _ in 0..num {
    write!(out, "-");
  }
  writeln!(out, "");
}

const INDENT_WIDTH: i32 = 2;

pub struct Printer<'a> {
  output: &'a mut fmt::Write,
  indent: i32
}

#[allow(unused_must_use)]
impl <'a> Printer<'a> {
  fn new(output: &'a mut fmt::Write) -> Self {
    Printer { output: output, indent: 0 }
  }

  fn print_indent(&mut self) {
    for _ in 0..self.indent {
      write!(self.output, " ");
    }
  }
}

#[allow(unused_must_use)]
impl<'a> Printer<'a> {
  pub fn print(&mut self, tp: &Type) {
    self.print_indent();
    match tp {
      &Type::PrimitiveType{ ref basic_info, physical_type, type_length, scale, precision } => {
        let phys_type_str = match physical_type {
          PhysicalType::FIXED_LEN_BYTE_ARRAY => {
            // we need to include length for fixed byte array
            format!("{} ({})", physical_type, type_length)
          },
          _ => format!("{}", physical_type),
        };
        // also print logical type if it is available
        let logical_type_str = match basic_info.logical_type() {
          LogicalType::NONE => format!(""),
          decimal @ LogicalType::DECIMAL => {
            // for decimal type we should print precision and scale if they are > 0, e.g.
            // DECIMAL(9, 2) - DECIMAL(9) - DECIMAL
            let precision_scale = match (precision, scale) {
              (p, s) if p > 0 && s > 0 => format!(" ({}, {})", p, s),
              (p, 0) if p > 0 => format!(" ({})", p),
              _ => format!("")
            };
            format!(" ({}{})", decimal, precision_scale)
          },
          other_logical_type => format!(" ({})", other_logical_type),
        };
        write!(self.output, "{} {} {}{};", basic_info.repetition(), phys_type_str, basic_info.name(),
          logical_type_str);
      },
      &Type::GroupType{ ref basic_info, ref fields } => {
        if basic_info.has_repetition() {
          let r = basic_info.repetition();
          write!(self.output, "{} group {} ", r, basic_info.name());
          if basic_info.logical_type() != LogicalType::NONE {
            write!(self.output, "({}) ", basic_info.logical_type());
          }
          writeln!(self.output, "{{");
        } else {
          writeln!(self.output, "message {} {{", basic_info.name());
        }

        self.indent += INDENT_WIDTH;
        for c in fields {
          self.print(&c);
          writeln!(self.output, "");
        }
        self.indent -= INDENT_WIDTH;
        self.print_indent();
        write!(self.output, "}}");
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use std::rc::Rc;
  use schema::types::Type;
  use schema::parser::parse_message_type;
  use basic::{Type as PhysicalType, Repetition};

  fn assert_print_parse_message(message: Type) {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      p.print(&message);
    }
    let parsed = parse_message_type(&s).unwrap();
    assert_eq!(message, parsed);
  }

  #[test]
  fn test_print_primitive_type() {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      let foo = Type::primitive_type_builder("foo", PhysicalType::INT32)
        .with_repetition(Repetition::REQUIRED)
        .with_logical_type(LogicalType::INT_32)
        .build().unwrap();
      p.print(&foo);
    }
    assert_eq!(&mut s, "REQUIRED INT32 foo (INT_32);");
  }

  #[test]
  fn test_print_primitive_type_without_logical() {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      let foo = Type::primitive_type_builder("foo", PhysicalType::DOUBLE)
        .with_repetition(Repetition::REQUIRED)
        .build().unwrap();
      p.print(&foo);
    }
    assert_eq!(&mut s, "REQUIRED DOUBLE foo;");
  }

  #[test]
  fn test_print_group_type() {
    let mut s = String::new();
    {
      let mut p = Printer::new(&mut s);
      let f1 = Type::primitive_type_builder("f1", PhysicalType::INT32)
        .with_repetition(Repetition::REQUIRED)
        .with_logical_type(LogicalType::INT_32)
        .with_id(0)
        .build();
      let f2 = Type::primitive_type_builder("f2", PhysicalType::BYTE_ARRAY)
        .with_logical_type(LogicalType::UTF8)
        .with_id(1)
        .build();
      let f3 = Type::primitive_type_builder("f3", PhysicalType::FIXED_LEN_BYTE_ARRAY)
        .with_repetition(Repetition::REPEATED)
        .with_logical_type(LogicalType::INTERVAL)
        .with_length(12)
        .with_id(2)
        .build();
      let mut struct_fields = Vec::new();
      struct_fields.push(Rc::new(f1.unwrap()));
      struct_fields.push(Rc::new(f2.unwrap()));
      let foo = Type::group_type_builder("foo")
        .with_repetition(Repetition::OPTIONAL)
        .with_fields(&mut struct_fields)
        .with_id(1)
        .build().unwrap();
      let mut fields = Vec::new();
      fields.push(Rc::new(foo));
      fields.push(Rc::new(f3.unwrap()));
      let message = Type::group_type_builder("schema")
        .with_fields(&mut fields)
        .with_id(2)
        .build().unwrap();
      p.print(&message);
    }
    let expected =
"message schema {
  OPTIONAL group foo {
    REQUIRED INT32 f1 (INT_32);
    OPTIONAL BYTE_ARRAY f2 (UTF8);
  }
  REPEATED FIXED_LEN_BYTE_ARRAY (12) f3 (INTERVAL);
}";
    assert_eq!(&mut s, expected);
  }

  #[test]
  fn test_print_and_parse_primitive() {
    let a2 = Type::primitive_type_builder("a2", PhysicalType::BYTE_ARRAY)
      .with_repetition(Repetition::REPEATED)
      .with_logical_type(LogicalType::UTF8)
      .build().unwrap();

    let a1 = Type::group_type_builder("a1")
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::LIST)
      .with_fields(&mut vec![Rc::new(a2)])
      .build().unwrap();

    let b3 = Type::primitive_type_builder("b3", PhysicalType::INT32)
      .with_repetition(Repetition::OPTIONAL)
      .build().unwrap();

    let b4 = Type::primitive_type_builder("b4", PhysicalType::DOUBLE)
      .with_repetition(Repetition::OPTIONAL)
      .build().unwrap();

    let b2 = Type::group_type_builder("b2")
      .with_repetition(Repetition::REPEATED)
      .with_logical_type(LogicalType::NONE)
      .with_fields(&mut vec![Rc::new(b3), Rc::new(b4)])
      .build().unwrap();

    let b1 = Type::group_type_builder("b1")
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::LIST)
      .with_fields(&mut vec![Rc::new(b2)])
      .build().unwrap();

    let a0 = Type::group_type_builder("a0")
      .with_repetition(Repetition::REQUIRED)
      .with_fields(&mut vec![Rc::new(a1), Rc::new(b1)])
      .build().unwrap();

    let message = Type::group_type_builder("root")
      .with_fields(&mut vec![Rc::new(a0)])
      .build().unwrap();

    assert_print_parse_message(message);
  }

  #[test]
  fn test_print_and_parse_nested() {
    let f1 = Type::primitive_type_builder("f1", PhysicalType::INT32)
      .with_repetition(Repetition::REQUIRED)
      .with_logical_type(LogicalType::INT_32)
      .build().unwrap();

    let f2 = Type::primitive_type_builder("f2", PhysicalType::BYTE_ARRAY)
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::UTF8)
      .build().unwrap();

    let foo = Type::group_type_builder("foo")
      .with_repetition(Repetition::OPTIONAL)
      .with_fields(&mut vec![Rc::new(f1), Rc::new(f2)])
      .build().unwrap();

    let f3 = Type::primitive_type_builder("f3", PhysicalType::FIXED_LEN_BYTE_ARRAY)
      .with_repetition(Repetition::REPEATED)
      .with_logical_type(LogicalType::INTERVAL)
      .with_length(12)
      .build().unwrap();

    let message = Type::group_type_builder("schema")
      .with_fields(&mut vec![Rc::new(foo), Rc::new(f3)])
      .build().unwrap();

    assert_print_parse_message(message);
  }

  #[test]
  fn test_print_and_parse_decimal() {
    let f1 = Type::primitive_type_builder("f1", PhysicalType::INT32)
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::DECIMAL)
      .with_precision(9)
      .with_scale(2)
      .build().unwrap();

    let f2 = Type::primitive_type_builder("f2", PhysicalType::INT32)
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::DECIMAL)
      .with_precision(9)
      .build().unwrap();

    let f3 = Type::primitive_type_builder("f3", PhysicalType::INT32)
      .with_repetition(Repetition::OPTIONAL)
      .with_logical_type(LogicalType::DECIMAL)
      .build().unwrap();

    let message = Type::group_type_builder("schema")
      .with_fields(&mut vec![Rc::new(f1), Rc::new(f2), Rc::new(f3)])
      .build().unwrap();

    assert_print_parse_message(message);
  }
}
<|endoftext|>


<commit_before>#![feature(libc)]

#![crate_name="sdl2_image"]
#![crate_type = "lib"]

extern crate sdl2;
extern crate libc;
extern crate sdl2_sys as sys;

#[macro_use]
extern crate bitflags;

use libc::{c_int, c_char};
use std::ptr;
use std::ffi::CString;
use std::path::Path;
use sdl2::surface::Surface;
use sdl2::render::Texture;
use sdl2::render::Renderer;
use sdl2::rwops::RWops;
use sdl2::version::Version;
use sdl2::get_error;
use sdl2::SdlResult;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_image")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_image")]
    extern {}
}

#[cfg(any(target_os="windows", target_os="linux", target_os="freebsd"))]
mod others {
    #[link(name="SDL2_image")]
    extern {}
}

#[allow(non_camel_case_types, dead_code)]
mod ffi;

/// InitFlags are passed to init() to control which subsystem
/// functionality to load.
bitflags! {
    flags InitFlag : u32 {
        const INIT_JPG  = ffi::IMG_INIT_JPG as u32,
        const INIT_PNG  = ffi::IMG_INIT_PNG as u32,
        const INIT_TIF  = ffi::IMG_INIT_TIF as u32,
        const INIT_WEBP = ffi::IMG_INIT_WEBP as u32
    }
}

/// Static method extensions for creating Surfaces
pub trait LoadSurface {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is SdlResult<~Surface>.
    fn from_file(filename: &Path) -> SdlResult<Self>;
    fn from_xpm_array(xpm: *const *const i8) -> SdlResult<Self>;
}

/// Method extensions to Surface for saving to disk
pub trait SaveSurface {
    fn save(&self, filename: &Path) -> SdlResult<()>;
    fn save_rw(&self, dst: &mut RWops) -> SdlResult<()>;
}

impl<'a> LoadSurface for Surface<'a> {
    fn from_file(filename: &Path) -> SdlResult<Surface<'a>> {
        //! Loads an SDL Surface from a file
        unsafe {
            let raw = ffi::IMG_Load(CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw, true))
            }
        }
    }

    fn from_xpm_array(xpm: *const *const i8) -> SdlResult<Surface<'a>> {
        //! Loads an SDL Surface from XPM data
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as *const *const c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw, true))
            }
        }
    }
}

impl<'a> SaveSurface for Surface<'a> {
    fn save(&self, filename: &Path) -> SdlResult<()> {
        //! Saves an SDL Surface to a file
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw(), CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }

    fn save_rw(&self, dst: &mut RWops) -> SdlResult<()> {
        //! Saves an SDL Surface to an RWops
        unsafe {
            let status = ffi::IMG_SavePNG_RW(self.raw(), dst.raw(), 0);

            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

/// Method extensions for creating Textures from a Renderer
pub trait LoadTexture {
    fn load_texture(&self, filename: &Path) -> SdlResult<Texture>;
}

impl<'a> LoadTexture for Renderer<'a> {
    fn load_texture(&self, filename: &Path) -> SdlResult<Texture> {
        //! Loads an SDL Texture from a file
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw(), CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Texture::from_ll(raw))
            }
        }
    }
}

pub fn init(flags: InitFlag) -> InitFlag {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    unsafe {
        let used = ffi::IMG_Init(flags.bits() as c_int);
        InitFlag::from_bits_truncate(used as u32)
    }
}

pub fn quit() {
    //! Teardown the SDL2_Image subsystem
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> Version {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        Version::from_ll(ffi::IMG_Linked_Version())
    }
}

#[inline]
fn to_surface_result<'a>(raw: *const sys::surface::SDL_Surface) -> SdlResult<Surface<'a>> {
    if raw == ptr::null() {
        Err(get_error())
    } else {
        unsafe { Ok(Surface::from_ll(raw, true)) }
    }
}

pub trait ImageRWops {
    /// load as a surface. except TGA
    fn load(&self) -> SdlResult<Surface>;
    /// load as a surface. This can load all supported image formats.
    fn load_typed(&self, _type: &str) -> SdlResult<Surface>;

    fn load_cur(&self) -> SdlResult<Surface>;
    fn load_ico(&self) -> SdlResult<Surface>;
    fn load_bmp(&self) -> SdlResult<Surface>;
    fn load_pnm(&self) -> SdlResult<Surface>;
    fn load_xpm(&self) -> SdlResult<Surface>;
    fn load_xcf(&self) -> SdlResult<Surface>;
    fn load_pcx(&self) -> SdlResult<Surface>;
    fn load_gif(&self) -> SdlResult<Surface>;
    fn load_jpg(&self) -> SdlResult<Surface>;
    fn load_tif(&self) -> SdlResult<Surface>;
    fn load_png(&self) -> SdlResult<Surface>;
    fn load_tga(&self) -> SdlResult<Surface>;
    fn load_lbm(&self) -> SdlResult<Surface>;
    fn load_xv(&self)  -> SdlResult<Surface>;
    fn load_webp(&self) -> SdlResult<Surface>;

    fn is_cur(&self) -> bool;
    fn is_ico(&self) -> bool;
    fn is_bmp(&self) -> bool;
    fn is_pnm(&self) -> bool;
    fn is_xpm(&self) -> bool;
    fn is_xcf(&self) -> bool;
    fn is_pcx(&self) -> bool;
    fn is_gif(&self) -> bool;
    fn is_jpg(&self) -> bool;
    fn is_tif(&self) -> bool;
    fn is_png(&self) -> bool;
    fn is_lbm(&self) -> bool;
    fn is_xv(&self)  -> bool;
    fn is_webp(&self) -> bool;
}

impl ImageRWops for RWops {
    fn load(&self) -> SdlResult<Surface> {
        let raw = unsafe {
            ffi::IMG_Load_RW(self.raw(), 0)
        };
        to_surface_result(raw)
    }
    fn load_typed(&self, _type: &str) -> SdlResult<Surface> {
        let raw = unsafe {
            ffi::IMG_LoadTyped_RW(self.raw(), 0, CString::new(_type.as_bytes()).unwrap().as_ptr())
        };
        to_surface_result(raw)
    }

    fn load_cur(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadCUR_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_ico(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadICO_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_bmp(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadBMP_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pnm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPNM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xpm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXPM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xcf(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXCF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pcx(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPCX_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_gif(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadGIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_jpg(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadJPG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tif(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadTIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_png(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPNG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tga(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadTGA_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_lbm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadLBM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xv(&self)  -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXV_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_webp(&self)  -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadWEBP_RW(self.raw()) };
        to_surface_result(raw)
    }

    fn is_cur(&self) -> bool {
        unsafe { ffi::IMG_isCUR(self.raw()) == 1 }
    }
    fn is_ico(&self) -> bool {
        unsafe { ffi::IMG_isICO(self.raw()) == 1 }
    }
    fn is_bmp(&self) -> bool {
        unsafe { ffi::IMG_isBMP(self.raw()) == 1 }
    }
    fn is_pnm(&self) -> bool {
        unsafe { ffi::IMG_isPNM(self.raw()) == 1 }
    }
    fn is_xpm(&self) -> bool {
        unsafe { ffi::IMG_isXPM(self.raw()) == 1 }
    }
    fn is_xcf(&self) -> bool {
        unsafe { ffi::IMG_isXCF(self.raw()) == 1 }
    }
    fn is_pcx(&self) -> bool {
        unsafe { ffi::IMG_isPCX(self.raw()) == 1 }
    }
    fn is_gif(&self) -> bool {
        unsafe { ffi::IMG_isGIF(self.raw()) == 1 }
    }
    fn is_jpg(&self) -> bool {
        unsafe { ffi::IMG_isJPG(self.raw()) == 1 }
    }
    fn is_tif(&self) -> bool {
        unsafe { ffi::IMG_isTIF(self.raw()) == 1 }
    }
    fn is_png(&self) -> bool {
        unsafe { ffi::IMG_isPNG(self.raw()) == 1 }
    }
    fn is_lbm(&self) -> bool {
        unsafe { ffi::IMG_isLBM(self.raw()) == 1 }
    }
    fn is_xv(&self)  -> bool {
        unsafe { ffi::IMG_isXV(self.raw())  == 1 }
    }
    fn is_webp(&self) -> bool {
        unsafe { ffi::IMG_isWEBP(self.raw())  == 1 }
    }
}
<commit_msg>update usage of Texture::from_ll() to take self as a parameter<commit_after>#![feature(libc)]

#![crate_name="sdl2_image"]
#![crate_type = "lib"]

extern crate sdl2;
extern crate libc;
extern crate sdl2_sys as sys;

#[macro_use]
extern crate bitflags;

use libc::{c_int, c_char};
use std::ptr;
use std::ffi::CString;
use std::path::Path;
use sdl2::surface::Surface;
use sdl2::render::Texture;
use sdl2::render::Renderer;
use sdl2::rwops::RWops;
use sdl2::version::Version;
use sdl2::get_error;
use sdl2::SdlResult;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_image")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_image")]
    extern {}
}

#[cfg(any(target_os="windows", target_os="linux", target_os="freebsd"))]
mod others {
    #[link(name="SDL2_image")]
    extern {}
}

#[allow(non_camel_case_types, dead_code)]
mod ffi;

/// InitFlags are passed to init() to control which subsystem
/// functionality to load.
bitflags! {
    flags InitFlag : u32 {
        const INIT_JPG  = ffi::IMG_INIT_JPG as u32,
        const INIT_PNG  = ffi::IMG_INIT_PNG as u32,
        const INIT_TIF  = ffi::IMG_INIT_TIF as u32,
        const INIT_WEBP = ffi::IMG_INIT_WEBP as u32
    }
}

/// Static method extensions for creating Surfaces
pub trait LoadSurface {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is SdlResult<~Surface>.
    fn from_file(filename: &Path) -> SdlResult<Self>;
    fn from_xpm_array(xpm: *const *const i8) -> SdlResult<Self>;
}

/// Method extensions to Surface for saving to disk
pub trait SaveSurface {
    fn save(&self, filename: &Path) -> SdlResult<()>;
    fn save_rw(&self, dst: &mut RWops) -> SdlResult<()>;
}

impl<'a> LoadSurface for Surface<'a> {
    fn from_file(filename: &Path) -> SdlResult<Surface<'a>> {
        //! Loads an SDL Surface from a file
        unsafe {
            let raw = ffi::IMG_Load(CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw, true))
            }
        }
    }

    fn from_xpm_array(xpm: *const *const i8) -> SdlResult<Surface<'a>> {
        //! Loads an SDL Surface from XPM data
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as *const *const c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw, true))
            }
        }
    }
}

impl<'a> SaveSurface for Surface<'a> {
    fn save(&self, filename: &Path) -> SdlResult<()> {
        //! Saves an SDL Surface to a file
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw(), CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }

    fn save_rw(&self, dst: &mut RWops) -> SdlResult<()> {
        //! Saves an SDL Surface to an RWops
        unsafe {
            let status = ffi::IMG_SavePNG_RW(self.raw(), dst.raw(), 0);

            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

/// Method extensions for creating Textures from a Renderer
pub trait LoadTexture {
    fn load_texture(&self, filename: &Path) -> SdlResult<Texture>;
}

impl<'a> LoadTexture for Renderer<'a> {
    fn load_texture(&self, filename: &Path) -> SdlResult<Texture> {
        //! Loads an SDL Texture from a file
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw(), CString::new(filename.to_str().unwrap()).unwrap().as_ptr());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Texture::from_ll(self, raw))
            }
        }
    }
}

pub fn init(flags: InitFlag) -> InitFlag {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    unsafe {
        let used = ffi::IMG_Init(flags.bits() as c_int);
        InitFlag::from_bits_truncate(used as u32)
    }
}

pub fn quit() {
    //! Teardown the SDL2_Image subsystem
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> Version {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        Version::from_ll(ffi::IMG_Linked_Version())
    }
}

#[inline]
fn to_surface_result<'a>(raw: *const sys::surface::SDL_Surface) -> SdlResult<Surface<'a>> {
    if raw == ptr::null() {
        Err(get_error())
    } else {
        unsafe { Ok(Surface::from_ll(raw, true)) }
    }
}

pub trait ImageRWops {
    /// load as a surface. except TGA
    fn load(&self) -> SdlResult<Surface>;
    /// load as a surface. This can load all supported image formats.
    fn load_typed(&self, _type: &str) -> SdlResult<Surface>;

    fn load_cur(&self) -> SdlResult<Surface>;
    fn load_ico(&self) -> SdlResult<Surface>;
    fn load_bmp(&self) -> SdlResult<Surface>;
    fn load_pnm(&self) -> SdlResult<Surface>;
    fn load_xpm(&self) -> SdlResult<Surface>;
    fn load_xcf(&self) -> SdlResult<Surface>;
    fn load_pcx(&self) -> SdlResult<Surface>;
    fn load_gif(&self) -> SdlResult<Surface>;
    fn load_jpg(&self) -> SdlResult<Surface>;
    fn load_tif(&self) -> SdlResult<Surface>;
    fn load_png(&self) -> SdlResult<Surface>;
    fn load_tga(&self) -> SdlResult<Surface>;
    fn load_lbm(&self) -> SdlResult<Surface>;
    fn load_xv(&self)  -> SdlResult<Surface>;
    fn load_webp(&self) -> SdlResult<Surface>;

    fn is_cur(&self) -> bool;
    fn is_ico(&self) -> bool;
    fn is_bmp(&self) -> bool;
    fn is_pnm(&self) -> bool;
    fn is_xpm(&self) -> bool;
    fn is_xcf(&self) -> bool;
    fn is_pcx(&self) -> bool;
    fn is_gif(&self) -> bool;
    fn is_jpg(&self) -> bool;
    fn is_tif(&self) -> bool;
    fn is_png(&self) -> bool;
    fn is_lbm(&self) -> bool;
    fn is_xv(&self)  -> bool;
    fn is_webp(&self) -> bool;
}

impl ImageRWops for RWops {
    fn load(&self) -> SdlResult<Surface> {
        let raw = unsafe {
            ffi::IMG_Load_RW(self.raw(), 0)
        };
        to_surface_result(raw)
    }
    fn load_typed(&self, _type: &str) -> SdlResult<Surface> {
        let raw = unsafe {
            ffi::IMG_LoadTyped_RW(self.raw(), 0, CString::new(_type.as_bytes()).unwrap().as_ptr())
        };
        to_surface_result(raw)
    }

    fn load_cur(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadCUR_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_ico(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadICO_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_bmp(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadBMP_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pnm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPNM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xpm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXPM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xcf(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXCF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pcx(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPCX_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_gif(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadGIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_jpg(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadJPG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tif(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadTIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_png(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadPNG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tga(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadTGA_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_lbm(&self) -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadLBM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xv(&self)  -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadXV_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_webp(&self)  -> SdlResult<Surface> {
        let raw = unsafe { ffi::IMG_LoadWEBP_RW(self.raw()) };
        to_surface_result(raw)
    }

    fn is_cur(&self) -> bool {
        unsafe { ffi::IMG_isCUR(self.raw()) == 1 }
    }
    fn is_ico(&self) -> bool {
        unsafe { ffi::IMG_isICO(self.raw()) == 1 }
    }
    fn is_bmp(&self) -> bool {
        unsafe { ffi::IMG_isBMP(self.raw()) == 1 }
    }
    fn is_pnm(&self) -> bool {
        unsafe { ffi::IMG_isPNM(self.raw()) == 1 }
    }
    fn is_xpm(&self) -> bool {
        unsafe { ffi::IMG_isXPM(self.raw()) == 1 }
    }
    fn is_xcf(&self) -> bool {
        unsafe { ffi::IMG_isXCF(self.raw()) == 1 }
    }
    fn is_pcx(&self) -> bool {
        unsafe { ffi::IMG_isPCX(self.raw()) == 1 }
    }
    fn is_gif(&self) -> bool {
        unsafe { ffi::IMG_isGIF(self.raw()) == 1 }
    }
    fn is_jpg(&self) -> bool {
        unsafe { ffi::IMG_isJPG(self.raw()) == 1 }
    }
    fn is_tif(&self) -> bool {
        unsafe { ffi::IMG_isTIF(self.raw()) == 1 }
    }
    fn is_png(&self) -> bool {
        unsafe { ffi::IMG_isPNG(self.raw()) == 1 }
    }
    fn is_lbm(&self) -> bool {
        unsafe { ffi::IMG_isLBM(self.raw()) == 1 }
    }
    fn is_xv(&self)  -> bool {
        unsafe { ffi::IMG_isXV(self.raw())  == 1 }
    }
    fn is_webp(&self) -> bool {
        unsafe { ffi::IMG_isWEBP(self.raw())  == 1 }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;

use std::env::args;
use std::io::{self, Write};
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use coreutils::extra::OptionalExt;

static HELP: &'static str = r#"
    NAME
        rem - set a count-down.
    SYNOPSIS
        rem [-h | --help] [-m N | --minutes N] [-H N | --hours N] [-s N | --seconds N] [-M N | --milliseconds N] [-n | --len] [-b | --blink]
    DESCRIPTION
        This utility lets you set a count-down with a progress bar. The options can be given in combination, adding together the durations given.
    OPTIONS
        -h
        --help
            Print this manual page.
        -m N
        --minutes N
            Wait N minutes.
        -H N
        --hours N
            Wait N hours.
        -s N
        --seconds N
            Wait N seconds.
        -M N
        --milliseconds N
            Wait N milliseconds.
        -n
        --len
            Length of the progress bar.
        -b
        --blink
            Blink with a red banner when done.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    let mut ms = 0u64;
    let mut len = 20;
    let mut blink = false;

    // Loop over the arguments.
    loop {
        let arg = if let Some(x) = args.next() {
            x
        } else {
            break;
        };

        match arg.as_str() {
            "-h" | "--help" => {
                // Print help.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
                return;
            },
            "-n" | "--len" => len = args.next().fail("no number after -n.", &mut stderr).parse().try(&mut stderr),
            "-b" | "--blink" => blink = true,
            t => {
                // Find number input.
                let num: u64 = args.next().unwrap_or_else(|| {
                    stderr.write(b"error: incorrectly formatted number.\
                                   Please input a positive integer.").try(&mut stderr);
                    stderr.flush().try(&mut stderr);
                    exit(1);
                }).parse().try(&mut stderr);
                ms += num * match t {
                    "-m" | "--minutes" => 1000 * 60,
                    "-H" | "--hours" => 1000 * 60 * 60,
                    "-s" | "--seconds" => 1000,
                    "-M" | "--milliseconds" => 1,
                    _ => {
                        // Unknown argument.
                        stderr.write(b"error: unknown argument, ").try(&mut stderr);
                        stderr.write(t.as_bytes()).try(&mut stderr);
                        stderr.write(b".\n").try(&mut stderr);
                        stderr.flush().try(&mut stderr);
                        exit(1);
                    },

                };
            },
        }
    }

    // Hide the cursor.
    stdout.write(b"\x1b[?25l").try(&mut stderr);
    // Draw the empty progress bar.
    for _ in 0..len + 1 {
        stdout.write(b" ").try(&mut stderr);
    }
    stdout.write(b"]").try(&mut stderr);

    stdout.write(b"\r[").try(&mut stderr);

    // As time goes, update the progress bar.
    for _ in 0..len {
        stdout.write(b"#").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        // Sleep.
        sleep(Duration::from_millis(ms / len));
    }

    if blink {
        for _ in 0..13 {
            stdout.write(b"\x1b[41m").try(&mut stderr);
            stdout.write(b"\x1b[2K").try(&mut stderr);
            stdout.flush().try(&mut stderr);
            sleep(Duration::from_millis(200));

            stdout.write(b"\x1b[0m").try(&mut stderr);
            stdout.write(b"\x1b[2K").try(&mut stderr);
            stdout.flush().try(&mut stderr);
            sleep(Duration::from_millis(200));
        }
    }

    // Show the cursor again.
    stdout.write(b"\x1b[?25h").try(&mut stderr);
    stdout.write(b"\n").try(&mut stderr);
}
<commit_msg>Short help<commit_after>#![deny(warnings)]

extern crate coreutils;

use std::env::args;
use std::io::{self, Write};
use std::process::exit;
use std::thread::sleep;
use std::time::Duration;

use coreutils::extra::OptionalExt;

static LONG_HELP: &'static str = r#"
    NAME
        rem - set a count-down.
    SYNOPSIS
        rem [-h | --help] [-m N | --minutes N] [-H N | --hours N] [-s N | --seconds N] [-M N | --milliseconds N] [-n | --len] [-b | --blink]
    DESCRIPTION
        This utility lets you set a count-down with a progress bar. The options can be given in combination, adding together the durations given.
    OPTIONS
        --help
            Print this manual page.
        -h
            Print short help page.
        -m N
        --minutes N
            Wait N minutes.
        -H N
        --hours N
            Wait N hours.
        -s N
        --seconds N
            Wait N seconds.
        -M N
        --milliseconds N
            Wait N milliseconds.
        -n N
        --len N
            Set the length of the progress bar to N.
        -b
        --blink
            Blink with a red banner when done.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

static SHORT_HELP: &'static str = r#"
    rem - set a count-down.

    Options (use --help for extended list):
    -m N          => Wait N minutes.
    -H N          => Wait N hours.
    -s N          => Wait N seconds.
    -M N          => Wait N milliseconds.
    -n N          => N character progress bar.
    -b            => Blink when done.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    let mut ms = 0u64;
    let mut len = 20;
    let mut blink = false;

    // Loop over the arguments.
    loop {
        let arg = if let Some(x) = args.next() {
            x
        } else {
            break;
        };

        match arg.as_str() {
            "--help" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            "-h" => {
                // Print help.
                stdout.write(SHORT_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            "-n" | "--len" => len = args.next().fail("no number after -n.", &mut stderr).parse().try(&mut stderr),
            "-b" | "--blink" => blink = true,
            t => {
                // Find number input.
                let num: u64 = args.next().unwrap_or_else(|| {
                    stderr.write(b"error: incorrectly formatted number.\
                                   Please input a positive integer.").try(&mut stderr);
                    stderr.flush().try(&mut stderr);
                    exit(1);
                }).parse().try(&mut stderr);
                ms += num * match t {
                    "-m" | "--minutes" => 1000 * 60,
                    "-H" | "--hours" => 1000 * 60 * 60,
                    "-s" | "--seconds" => 1000,
                    "-M" | "--milliseconds" => 1,
                    _ => {
                        // Unknown argument.
                        stderr.write(b"error: unknown argument, ").try(&mut stderr);
                        stderr.write(t.as_bytes()).try(&mut stderr);
                        stderr.write(b".\n").try(&mut stderr);
                        stderr.flush().try(&mut stderr);
                        exit(1);
                    },

                };
            },
        }
    }

    // Hide the cursor.
    stdout.write(b"\x1b[?25l").try(&mut stderr);
    // Draw the empty progress bar.
    for _ in 0..len + 1 {
        stdout.write(b" ").try(&mut stderr);
    }
    stdout.write(b"]").try(&mut stderr);

    stdout.write(b"\r[").try(&mut stderr);

    // As time goes, update the progress bar.
    for _ in 0..len {
        stdout.write(b"#").try(&mut stderr);
        stdout.flush().try(&mut stderr);
        // Sleep.
        sleep(Duration::from_millis(ms / len));
    }

    if blink {
        // This will print a blinking red banner.
        for _ in 0..13 {
            // Set drawing mode to red background.
            stdout.write(b"\x1b[41m").try(&mut stderr);
            // Clear the current line, rendering the background red.
            stdout.write(b"\x1b[2K").try(&mut stderr);
            // Flush.
            stdout.flush().try(&mut stderr);
            // Sleep.
            sleep(Duration::from_millis(200));

            // Clear the drawing mode.
            stdout.write(b"\x1b[0m").try(&mut stderr);
            // Clear the background.
            stdout.write(b"\x1b[2K").try(&mut stderr);
            // Flush.
            stdout.flush().try(&mut stderr);
            sleep(Duration::from_millis(200));

            // Repeat...
        }
    }

    // Show the cursor again.
    stdout.write(b"\x1b[?25h").try(&mut stderr);
    stdout.write(b"\n").try(&mut stderr);
}
<|endoftext|>


<commit_before>//! Functions for interacting with browser processes.

use std::process::{Command, Child, Stdio};
use std::io::Result;

use url::Url;

/// Opens a browser window at the specified URL in a new process.
///
/// Returns an `io::Result` containing the child process.
///
/// This function uses platform-specific utilities to determine the user's default browser. The
/// following platforms are supported:
///
/// | Platform | Program    |
/// | -------- | ---------- |
/// | Linux    | `xdg-open` |
/// | OS X     | `open`     |
/// | Windows  | `start`    |
///
/// # Panics
/// Panics if called on an unsupported operating system.
pub fn open(url: &str) -> Result<Child> {
    let (browser, args) = if cfg!(target_os = "linux") {
        ("xdg-open", None)
    } else if cfg!(target_os = "macos") {
        ("open", None)
    } else if cfg!(target_os = "windows") {
        // `start` requires an empty string as its first parameter.
        ("start", Some(vec![""]))
    } else {
        panic!("unsupported OS")
    };
    open_specific(url, &browser, args)
}

/// Opens a specified browser in a new process.
///
/// The browser will be called with any supplied arguments in addition to the URL as an additional
/// argument.
///
/// Returns an `io::Result` containing the child process.
pub fn open_specific(url: &str, browser: &str, browser_args: Option<Vec<&str>>) -> Result<Child> {
    let url = Url::parse(url).unwrap();
    debug!("starting process '{:?}' with url {:?}", browser, url);

    Command::new(browser)
            .arg(url.to_string())
            .args(&browser_args.unwrap_or(Vec::new()))
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
}
<commit_msg>add `-g` flag to `open` on OS X<commit_after>//! Functions for interacting with browser processes.

use std::process::{Command, Child, Stdio};
use std::io::Result;

use url::Url;

/// Opens a browser window at the specified URL in a new process.
///
/// Returns an `io::Result` containing the child process.
///
/// This function uses platform-specific utilities to determine the user's default browser. The
/// following platforms are supported:
///
/// | Platform | Program    |
/// | -------- | ---------- |
/// | Linux    | `xdg-open` |
/// | OS X     | `open`     |
/// | Windows  | `start`    |
///
/// # Panics
/// Panics if called on an unsupported operating system.
pub fn open(url: &str) -> Result<Child> {
    let (browser, args) = if cfg!(target_os = "linux") {
        ("xdg-open", None)
    } else if cfg!(target_os = "macos") {
        ("open", Some(vec!["-g"]))
    } else if cfg!(target_os = "windows") {
        // `start` requires an empty string as its first parameter.
        ("start", Some(vec![""]))
    } else {
        panic!("unsupported OS")
    };
    open_specific(url, &browser, args)
}

/// Opens a specified browser in a new process.
///
/// The browser will be called with any supplied arguments in addition to the URL as an additional
/// argument.
///
/// Returns an `io::Result` containing the child process.
pub fn open_specific(url: &str, browser: &str, browser_args: Option<Vec<&str>>) -> Result<Child> {
    let url = Url::parse(url).unwrap();
    debug!("starting process '{:?}' with url {:?}", browser, url);

    Command::new(browser)
            .arg(url.to_string())
            .args(&browser_args.unwrap_or(Vec::new()))
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
}
<|endoftext|>


<commit_before>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Returns `true` iff the span is over an empty range.
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty => true,
      _     => false,
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match self {
      &Empty => {},
      &One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      &Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<commit_msg>is_empty bugfix<commit_after>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Returns `true` iff the span is over an empty range.
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty       => true,
      One (ref b) => b.is_empty(),
      Many(ref v) => v.iter().all(|b| b.is_empty()),
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match self {
      &Empty => {},
      &One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      &Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<|endoftext|>


<commit_before>use hyper::status::StatusCode;
use rotor_stream::StreamSocket;
use time::Duration;

use super::Response;

pub trait Context {
    fn emit_error_page(&self,
        code: StatusCode, response: &mut Response)
    {
        unimplemented!();
    }
    fn byte_timeout(&self) -> Duration {
        Duration::seconds(10)
    }
}
<commit_msg>An implementation of default error page<commit_after>use hyper::status::StatusCode;
use hyper::header::{ContentLength, ContentType};
use rotor_stream::StreamSocket;
use time::Duration;
use hyper::mime::{Mime, TopLevel, SubLevel};

use super::Response;

pub trait Context {
    fn emit_error_page(&self,
        code: StatusCode, response: &mut Response)
    {
        if response.is_started() {
            // Too late, nothing to do
            return;
        }
        response.status(code);
        let data = format!("
{} {}
\n\

Served for you by rotor-http
\n",
            code, code.canonical_reason().unwrap_or("Unknown"));
        let bytes = data.as_bytes();
        response.add_header(ContentLength(bytes.len() as u64)).unwrap();
        response.add_header(ContentType(
            Mime(TopLevel::Text, SubLevel::Html, vec![]))).unwrap();
        response.done_headers().unwrap();
        response.write_body(bytes);
        response.done();
    }
    fn byte_timeout(&self) -> Duration {
        Duration::seconds(10)
    }
}
<|endoftext|>