<commit_before>#![allow(dead_code, unused_variables)]
use alloc::heap::{Heap, Alloc, Layout};
use bytes::BytesMut;

use std::rc::Rc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

pub mod error {
    error_chain! {
        errors {
            InvalidIndex
            InvalidConversion
        }
    }
}

use self::error::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Rc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Rc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use self::MediaKind::*;

pub trait FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [u8]>;
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]>;
    fn linesize(&self, idx: usize) -> Result<usize>;
    fn count(&self) -> usize;
}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: Option<TimeInfo>,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [u8]> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]> {
        match self.planes.get_mut(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
    fn linesize(&self, idx: usize) -> Result<usize> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }
}

impl DefaultFrameBuffer {
    pub fn new(kind: &MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub fn new_default_frame(kind: &MediaKind, t: Option<TimeInfo>) -> Frame {
    let buf = DefaultFrameBuffer::new(kind);

    Frame {
        kind: kind.clone(),
        buf: box buf,
        t: t,
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}
<commit_msg>frame: Simplify the arguments for the new_default_frame helper<commit_after>#![allow(dead_code, unused_variables)]
use alloc::heap::{Heap, Alloc, Layout};
use bytes::BytesMut;

use std::rc::Rc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

pub mod error {
    error_chain! {
        errors {
            InvalidIndex
            InvalidConversion
        }
    }
}

use self::error::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Rc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Rc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [u8]>;
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]>;
    fn linesize(&self, idx: usize) -> Result<usize>;
    fn count(&self) -> usize;
}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: Option<TimeInfo>,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [u8]> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8]> {
        match self.planes.get_mut(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
    fn linesize(&self, idx: usize) -> Result<usize> {
        match self.planes.get(idx) {
            None => Err(Error::from_kind(ErrorKind::InvalidIndex)),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Heap.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t,
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}
<|endoftext|>


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

// ignore-windows failing on win32 bot
// ignore-freebsd: output doesn't match
// ignore-tidy-linelength
// ignore-lldb
// ignore-android: FIXME(#10381)
// compile-flags:-g

// This test uses some GDB Python API features (e.g. accessing anonymous fields)
// which are only available in newer GDB version. The following directive will
// case the test runner to ignore this test if an older GDB version is used:
// min-gdb-version 7.7

// gdb-command: run

// gdb-command: print regular_struct
// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false, the_fourth_field = "I'm so pretty, oh so pretty..."}

// gdb-command: print tuple
// gdb-check:$2 = {true, 103, "blub"}

// gdb-command: print tuple_struct
// gdb-check:$3 = TupleStruct = {-104.5, 105}

// gdb-command: print empty_struct
// gdb-check:$4 = EmptyStruct

// gdb-command: print c_style_enum1
// gdb-check:$5 = CStyleEnumVar1

// gdb-command: print c_style_enum2
// gdb-check:$6 = CStyleEnumVar2

// gdb-command: print c_style_enum3
// gdb-check:$7 = CStyleEnumVar3

// gdb-command: print mixed_enum_c_style_var
// gdb-check:$8 = MixedEnumCStyleVar

// gdb-command: print mixed_enum_tuple_var
// gdb-check:$9 = MixedEnumTupleVar = {106, 107, false}

// gdb-command: print mixed_enum_struct_var
// gdb-check:$10 = MixedEnumStructVar = {field1 = 108.5, field2 = 109}

// gdb-command: print some
// gdb-check:$11 = Some = {110}

// gdb-command: print none
// gdb-check:$12 = None

// gdb-command: print some_fat
// gdb-check:$13 = Some = {"abc"}

// gdb-command: print none_fat
// gdb-check:$14 = None

// gdb-command: print nested_variant1
// gdb-check:$15 = NestedVariant1 = {NestedStruct = {regular_struct = RegularStruct = {the_first_field = 111, the_second_field = 112.5, the_third_field = true, the_fourth_field = "NestedStructString1"}, tuple_struct = TupleStruct = {113.5, 114}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar2, mixed_enum = MixedEnumTupleVar = {115, 116, false}}}

// gdb-command: print nested_variant2
// gdb-check:$16 = NestedVariant2 = {abc = NestedStruct = {regular_struct = RegularStruct = {the_first_field = 117, the_second_field = 118.5, the_third_field = false, the_fourth_field = "NestedStructString10"}, tuple_struct = TupleStruct = {119.5, 120}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar3, mixed_enum = MixedEnumStructVar = {field1 = 121.5, field2 = -122}}}

// gdb-command: print none_check1
// gdb-check:$17 = None

// gdb-command: print none_check2
// gdb-check:$18 = None

#![allow(dead_code, unused_variables)]

use self::CStyleEnum::{CStyleEnumVar1, CStyleEnumVar2, CStyleEnumVar3};
use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar};
use self::NestedEnum::{NestedVariant1, NestedVariant2};

struct RegularStruct {
    the_first_field: isize,
    the_second_field: f64,
    the_third_field: bool,
    the_fourth_field: &'static str,
}

struct TupleStruct(f64, i16);

struct EmptyStruct;

enum CStyleEnum {
    CStyleEnumVar1,
    CStyleEnumVar2,
    CStyleEnumVar3,
}

enum MixedEnum {
    MixedEnumCStyleVar,
    MixedEnumTupleVar(u32, u16, bool),
    MixedEnumStructVar { field1: f64, field2: i32 }
}

struct NestedStruct {
    regular_struct: RegularStruct,
    tuple_struct: TupleStruct,
    empty_struct: EmptyStruct,
    c_style_enum: CStyleEnum,
    mixed_enum: MixedEnum,
}

enum NestedEnum {
    NestedVariant1(NestedStruct),
    NestedVariant2 { abc: NestedStruct }
}

fn main() {

    let regular_struct = RegularStruct {
        the_first_field: 101,
        the_second_field: 102.5,
        the_third_field: false,
        the_fourth_field: "I'm so pretty, oh so pretty..."
    };

    let tuple = ( true, 103u32, "blub" );

    let tuple_struct = TupleStruct(-104.5, 105);

    let empty_struct = EmptyStruct;

    let c_style_enum1 = CStyleEnumVar1;
    let c_style_enum2 = CStyleEnumVar2;
    let c_style_enum3 = CStyleEnumVar3;

    let mixed_enum_c_style_var = MixedEnumCStyleVar;
    let mixed_enum_tuple_var = MixedEnumTupleVar(106, 107, false);
    let mixed_enum_struct_var = MixedEnumStructVar { field1: 108.5, field2: 109 };

    let some = Some(110_usize);
    let none: Option<isize> = None;
    let some_fat = Some("abc");
    let none_fat: Option<&'static str> = None;

    let nested_variant1 = NestedVariant1(
        NestedStruct {
            regular_struct: RegularStruct {
                the_first_field: 111,
                the_second_field: 112.5,
                the_third_field: true,
                the_fourth_field: "NestedStructString1",
            },
            tuple_struct: TupleStruct(113.5, 114),
            empty_struct: EmptyStruct,
            c_style_enum: CStyleEnumVar2,
            mixed_enum: MixedEnumTupleVar(115, 116, false)
        }
    );

    let nested_variant2 = NestedVariant2 {
        abc: NestedStruct {
            regular_struct: RegularStruct {
                the_first_field: 117,
                the_second_field: 118.5,
                the_third_field: false,
                the_fourth_field: "NestedStructString10",
            },
            tuple_struct: TupleStruct(119.5, 120),
            empty_struct: EmptyStruct,
            c_style_enum: CStyleEnumVar3,
            mixed_enum: MixedEnumStructVar {
                field1: 121.5,
                field2: -122
            }
        }
    };

    let none_check1: Option<(usize, Vec<usize>)> = None;
    let none_check2: Option<String> = None;

    zzz(); // #break
}

fn zzz() { () }
<commit_msg>Auto merge of #27534 - alexcrichton:revert-adding-gdb-pp-tests, r=michaelwoerister<commit_after><|endoftext|>


<commit_before>//! online reinforcement q learner (kind of double q and replay buffer learning)
#![allow(dead_code)]

extern crate rand;
extern crate nn;

use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::io::prelude::*;
use self::rand::Rng;
use self::nn::{NN, HaltCondition};
use super::Player;
use super::super::field::Field;

const GAMMA:f64 = 0.99; //q gamma (action-reward time difference high) //1.0?
const LR:f64 = 0.5; //neural net learning rate
const LR_DECAY:f64 = 25000f64; //NN learning rate decrease (half every DECAY games)
const LR_MIN:f64 = 0.1; //minimum NN LR
const MOM:f64 = 0.1; //neural net momentum
const EPOCHS_PER_STEP:u32 = 1; //epochs to learn from each turn
const RND_PICK_START:f64 = 0.5f64; //exploration factor start
const RND_PICK_DEC:f64 = 20000f64; //random exploration decrease (half every DEC games)
const RND_PICK_MIN:f64 = 0.05f64; //exploration rate minimum

pub struct PlayerAIQ
{
	initialized: bool,
	fixed: bool, //should the agent learn or not (fixed => dont learn)
	filename: String,
	pid: i32, //player ID
	nn: Option<NN>, //online network
	targetnn: Option<NN>, //target network (temporarely fixed value network)
	games_played: u32,
	lr: f64,
	exploration: f64,
	startp: f64, //for NN input (1 = self starting, -1 = enemy starting)
	memstate: Vec<f64>, //memorize state learning next turn
	memqval: Vec<f64>, //same
	memreward: f64, //same
	memplay: u32, //same
}

impl PlayerAIQ
{
	pub fn new(fix:bool) -> Box<PlayerAIQ>
	{
		Box::new(PlayerAIQ { initialized: false, fixed: fix, filename: String::new(), pid: 0,
				nn: None, targetnn: None, games_played: 0, lr: LR, exploration: RND_PICK_START,
				startp: 0.0, memstate: Vec::new(), memqval: Vec::new(), memreward: -1.0, memplay: 0 })
	}

	fn get_exploration(&self) -> f64
	{
		RND_PICK_MIN.max(RND_PICK_START * (2f64).powf(-(self.games_played as f64)/RND_PICK_DEC))
	}

	fn get_lr(&self) -> f64
	{
		LR_MIN.max(LR * (2f64).powf(-(self.games_played as f64)/LR_DECAY))
	}

	fn argmax(slice:&[f64]) -> u32
	{
		let mut x:u32 = 0;
		let mut max = slice[0];
		for i in 1..slice.len()
		{
			if max<slice[i]
			{
				x = i as u32;
				max = slice[i];
			}
		}
		x
	}

	fn field_to_input(field:&mut Field, p:i32, startp:f64) -> Vec<f64>
	{
		let op:i32 = if p == 1 { 2 } else { 1 }; //other player
		let mut input:Vec<f64> = Vec::with_capacity((2*field.get_size() + field.get_w() + 1) as usize);
		for (i, val) in field.get_field().iter().enumerate()
		{ //2 nodes for every square: -1 enemy, 0 free, 1 own; 0 square will not be reached with one move, 1 square can be directly filled
			if *val == p { input.push(1f64); input.push(0f64); }
			else if *val == op { input.push(-1f64); input.push(0f64); }
			else
			{ //empty square
				input.push(0f64);
				if (i as u32) < (field.get_size()-field.get_w()) { input.push(if field.get_field()[i+field.get_w() as usize] != 0 { 1f64 } else { 0f64 }); }
				else { input.push(1f64); }
			}
		}
		for x in 0..field.get_w()
		{ //1 node for every column: 1 own win, -1 enemy win, 0 none (which consistent order of the nodes does not matter, fully connected)
			if field.play(p, x)
			{ //valid play
				match field.get_state()
				{
					-1 | 0 => input.push(0f64),
					pid => input.push(if pid == p {1f64} else {-1f64}),
				}
				field.undo();
			}
			else { input.push(0f64); } //illegal move, nobody can win
		}
		//1 node for starting player (-1 enemy, 1 self)
		input.push(startp);
		//return
		input
	}
}

impl Player for PlayerAIQ
{
	fn init(&mut self, field:&Field, p:i32) -> bool
	{
		self.pid = p;

		self.filename = format!("AIQ-{}x{}.NN", field.get_w(), field.get_h());
		let file = File::open(&self.filename);
		if file.is_err()
		{
			//create new neural net, as it could not be loaded
			let n = field.get_size();
			let w = field.get_w();
			self.nn = Some(NN::new(&[2*n+w+1, 4*n, n, n/2, w])); //set size of NN layers here
			//games_played, exploration, lr already set
		}
		else
		{
			//load neural net from file (and games played)
			let mut reader = BufReader::new(file.unwrap());
			let mut datas = String::new();
			let mut nns = String::new();

			let res1 = reader.read_line(&mut datas);
			let res2 = reader.read_to_string(&mut nns);
			if res1.is_err() || res2.is_err() { return false; }

			let res = datas.trim().parse::<u32>();
			if res.is_err() { return false; }
			self.games_played = res.unwrap();
			self.nn = Some(NN::from_json(&nns));

			self.lr = self.get_lr();
			self.exploration = self.get_exploration();
		}

		self.targetnn = self.nn.clone();
		self.initialized = true;
		true
	}

	fn startp(&mut self, p:i32)
	{
		if p == self.pid
		{
			self.startp = 1.0;
		}
		else
		{
			self.startp = -1.0;
		}
	}

	fn play(&mut self, field:&mut Field) -> bool
	{
		if !self.initialized { return false; }
		//variables
		let mut rng = rand::thread_rng();
		let nn = self.nn.as_mut().unwrap();
		let targetnn = self.targetnn.as_mut().unwrap();

		//get current state formatted for the neural net
		let state = PlayerAIQ::field_to_input(field, self.pid, self.startp);

		//learn if not first move (reward is already set, won/loose would be outcome) and NN not fixed
		if !self.fixed && self.memreward != -1.0
		{
			//get Q values for next state
			let qval2 = targetnn.run(&state); //use double q learning target nn, to decouple action and value a bit
			let max = qval2[PlayerAIQ::argmax(&qval2) as usize];
			//calculate q update
			self.memqval[self.memplay as usize] = (self.memreward + GAMMA * max) / (1.0 + GAMMA); //Q learning (divide to stay in [0,1] for sigmoid)
			//train on the latest experience (q update)
			nn.train(&[(self.memstate.clone(), self.memqval.clone())])
				.halt_condition(HaltCondition::Epochs(EPOCHS_PER_STEP))
				.log_interval(None)
				//.log_interval(Some(2)) //debug
				.momentum(MOM)
				.rate(self.lr)
				.go();
		}

		//choose action by e-greedy
		self.memqval = nn.run(&state);
		self.memplay = PlayerAIQ::argmax(&self.memqval);
		if !self.fixed && rng.gen::<f64>() < self.exploration //random exploration if agent should learn.
		{
			self.memplay = rng.gen::<u32>() % field.get_w();
		}

		//perform action and set reward
		self.memreward = 0.5;
		let mut res = field.play(self.pid, self.memplay);
		if !res { self.memqval[self.memplay as usize] = 0.1; } //move did not meet the rules, but learn anyway, even if another random move is made

		//random play when it was not rule conform, also modify q-value for it?
		while !res //infinite if it is already draw!
		{
			self.memplay = rng.gen::<u32>() % field.get_w();
			res = field.play(self.pid, self.memplay);
		}

		//save state for next turn
		self.memstate = state;

		//return
		res
	}

	#[allow(unused_variables)]
	fn outcome(&mut self, field:&mut Field, state:i32)
	{
		//learn if not fixed
		if !self.fixed
		{
			let nn = self.nn.as_mut().unwrap();
			let op:i32 = if self.pid == 1 { 2 } else { 1 }; //other player
			//set reward (if draw, reward already set properly)
			if state == self.pid { self.memreward = 1.0; }
			else if state == op { self.memreward = 0.0; }
			//end-values of network should meet reward exactly
			self.memqval[self.memplay as usize] = self.memreward;
			//train NN
			nn.train(&[(self.memstate.clone(), self.memqval.clone())])
				.halt_condition(HaltCondition::Epochs(EPOCHS_PER_STEP))
				.log_interval(None)
				//.log_interval(Some(2)) //debug
				.momentum(MOM)
				.rate(self.lr)
				.go();
		}

		//parameters
		self.games_played += 1;
		self.lr = self.get_lr();
		self.exploration = self.get_exploration();
		self.targetnn = self.nn.clone();
		self.memreward = -1.0;
	}
}

impl Drop for PlayerAIQ
{
	fn drop(&mut self)
	{
		//write neural net to file, if it may has learned and was initialized
		if self.initialized && !self.fixed
		{
			let file = File::create(&self.filename);
			if file.is_err() { println!("Warning: Could not write AIQ NN file!"); return; }
			let mut writer = BufWriter::new(file.unwrap());

			let res1 = writeln!(&mut writer, "{}", self.games_played);
			let res2 = write!(&mut writer, "{}", self.nn.as_mut().unwrap().to_json());
			if res1.is_err() || res2.is_err() { println!("Warning: There was an error while writing AIQ NN file!"); return; }
		}
	}
}
<commit_msg>little improvement<commit_after>//! online reinforcement q learner (kind of double q and replay buffer learning)
#![allow(dead_code)]

extern crate rand;
extern crate nn;

use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::io::prelude::*;
use self::rand::Rng;
use self::nn::{NN, HaltCondition};
use super::Player;
use super::super::field::Field;

const GAMMA:f64 = 0.99; //q gamma (action-reward time difference high) //1.0?
const LR:f64 = 0.5; //neural net learning rate
const LR_DECAY:f64 = 250000f64; //NN learning rate decrease (half every DECAY games)
const LR_MIN:f64 = 0.1; //minimum NN LR
const MOM:f64 = 0.1; //neural net momentum
const EPOCHS_PER_STEP:u32 = 1; //epochs to learn from each turn
const RND_PICK_START:f64 = 0.5f64; //exploration factor start
const RND_PICK_DEC:f64 = 250000f64; //random exploration decrease (half every DEC games)
const RND_PICK_MIN:f64 = 0.05f64; //exploration rate minimum

pub struct PlayerAIQ
{
	initialized: bool,
	fixed: bool, //should the agent learn or not (fixed => dont learn)
	filename: String,
	pid: i32, //player ID
	nn: Option<NN>, //online network
	targetnn: Option<NN>, //target network (temporarely fixed value network)
	games_played: u32,
	lr: f64,
	exploration: f64,
	startp: f64, //for NN input (1 = self starting, -1 = enemy starting)
	memstate: Vec<f64>, //memorize state learning next turn
	memqval: Vec<f64>, //same
	memreward: f64, //same
	memplay: u32, //same
}

impl PlayerAIQ
{
	pub fn new(fix:bool) -> Box<PlayerAIQ>
	{
		Box::new(PlayerAIQ { initialized: false, fixed: fix, filename: String::new(), pid: 0,
				nn: None, targetnn: None, games_played: 0, lr: LR, exploration: RND_PICK_START,
				startp: 0.0, memstate: Vec::new(), memqval: Vec::new(), memreward: -1.0, memplay: 0 })
	}

	fn get_exploration(&self) -> f64
	{
		RND_PICK_MIN.max(RND_PICK_START * (2f64).powf(-(self.games_played as f64)/RND_PICK_DEC))
	}

	fn get_lr(&self) -> f64
	{
		LR_MIN.max(LR * (2f64).powf(-(self.games_played as f64)/LR_DECAY))
	}

	fn argmax(slice:&[f64]) -> u32
	{
		let mut x:u32 = 0;
		let mut max = slice[0];
		for i in 1..slice.len()
		{
			if max<slice[i]
			{
				x = i as u32;
				max = slice[i];
			}
		}
		x
	}

	fn field_to_input(field:&mut Field, p:i32, startp:f64) -> Vec<f64>
	{
		let op:i32 = if p == 1 { 2 } else { 1 }; //other player
		let mut input:Vec<f64> = Vec::with_capacity((2*field.get_size() + field.get_w() + 1) as usize);
		for (i, val) in field.get_field().iter().enumerate()
		{ //2 nodes for every square: -1 enemy, 0 free, 1 own; 0 square will not be reached with one move, 1 square can be directly filled
			if *val == p { input.push(1f64); input.push(0f64); }
			else if *val == op { input.push(-1f64); input.push(0f64); }
			else
			{ //empty square
				input.push(0f64);
				if (i as u32) < (field.get_size()-field.get_w()) { input.push(if field.get_field()[i+field.get_w() as usize] != 0 { 1f64 } else { 0f64 }); }
				else { input.push(1f64); }
			}
		}
		for x in 0..field.get_w()
		{ //1 node for every column: 1 own win, -1 enemy win, 0 none (which consistent order of the nodes does not matter, fully connected)
			if field.play(p, x)
			{ //valid play
				match field.get_state()
				{
					-1 | 0 => input.push(0f64),
					pid => input.push(if pid == p {1f64} else {-1f64}),
				}
				field.undo();
			}
			else { input.push(0f64); } //illegal move, nobody can win
		}
		//1 node for starting player (-1 enemy, 1 self)
		input.push(startp);
		//return
		input
	}
}

impl Player for PlayerAIQ
{
	fn init(&mut self, field:&Field, p:i32) -> bool
	{
		self.pid = p;

		self.filename = format!("AIQ-{}x{}.NN", field.get_w(), field.get_h());
		let file = File::open(&self.filename);
		if file.is_err()
		{
			//create new neural net, as it could not be loaded
			let n = field.get_size();
			let w = field.get_w();
			self.nn = Some(NN::new(&[2*n+w+1, 4*n, n, n/2, w])); //set size of NN layers here
			//games_played, exploration, lr already set
		}
		else
		{
			//load neural net from file (and games played)
			let mut reader = BufReader::new(file.unwrap());
			let mut datas = String::new();
			let mut nns = String::new();

			let res1 = reader.read_line(&mut datas);
			let res2 = reader.read_to_string(&mut nns);
			if res1.is_err() || res2.is_err() { return false; }

			let res = datas.trim().parse::<u32>();
			if res.is_err() { return false; }
			self.games_played = res.unwrap();
			self.nn = Some(NN::from_json(&nns));

			self.lr = self.get_lr();
			self.exploration = self.get_exploration();
		}

		self.targetnn = self.nn.clone();
		self.initialized = true;
		true
	}

	fn startp(&mut self, p:i32)
	{
		if p == self.pid
		{
			self.startp = 1.0;
		}
		else
		{
			self.startp = -1.0;
		}
	}

	fn play(&mut self, field:&mut Field) -> bool
	{
		if !self.initialized { return false; }
		//variables
		let mut rng = rand::thread_rng();
		let nn = self.nn.as_mut().unwrap();
		let targetnn = self.targetnn.as_mut().unwrap();

		//get current state formatted for the neural net
		let state = PlayerAIQ::field_to_input(field, self.pid, self.startp);

		//learn if not first move (reward is already set, won/loose would be outcome) and NN not fixed
		if !self.fixed && self.memreward != -1.0
		{
			//get Q values for next state
			let qval2 = targetnn.run(&state); //use double q learning target nn, to decouple action and value a bit
			let max = qval2[PlayerAIQ::argmax(&qval2) as usize];
			//calculate q update
			self.memqval[self.memplay as usize] = (self.memreward + GAMMA * max) / (1.0 + GAMMA); //Q learning (divide to stay in [0,1] for sigmoid)
			//train on the latest experience (q update)
			nn.train(&[(self.memstate.clone(), self.memqval.clone())])
				.halt_condition(HaltCondition::Epochs(EPOCHS_PER_STEP))
				.log_interval(None)
				//.log_interval(Some(2)) //debug
				.momentum(MOM)
				.rate(self.lr)
				.go();
		}

		//choose action by e-greedy
		self.memqval = nn.run(&state);
		self.memplay = PlayerAIQ::argmax(&self.memqval);
		if !self.fixed && rng.gen::<f64>() < self.exploration //random exploration if agent should learn.
		{
			self.memplay = rng.gen::<u32>() % field.get_w();
		}

		//perform action and set reward
		self.memreward = 0.5;
		let mut res = field.play(self.pid, self.memplay);
		if !res { self.memqval[self.memplay as usize] = 0.1; } //move did not meet the rules, but learn anyway, even if another random move is made

		//random play when it was not rule conform, also modify q-value for it?
		while !res //infinite if it is already draw!
		{
			self.memplay = rng.gen::<u32>() % field.get_w();
			res = field.play(self.pid, self.memplay);
		}

		//save state for next turn
		self.memstate = state;

		//return
		res
	}

	#[allow(unused_variables)]
	fn outcome(&mut self, field:&mut Field, state:i32)
	{
		//learn if not fixed
		if !self.fixed
		{
			let nn = self.nn.as_mut().unwrap();
			let op:i32 = if self.pid == 1 { 2 } else { 1 }; //other player
			//set reward (if draw, reward already set properly)
			if state == self.pid { self.memreward = 1.0; }
			else if state == op { self.memreward = 0.0; }
			//end-values of network should meet reward exactly
			self.memqval[self.memplay as usize] = self.memreward;
			//train NN
			nn.train(&[(self.memstate.clone(), self.memqval.clone())])
				.halt_condition(HaltCondition::Epochs(EPOCHS_PER_STEP))
				.log_interval(None)
				//.log_interval(Some(2)) //debug
				.momentum(MOM)
				.rate(self.lr)
				.go();
		}

		//parameters
		self.games_played += 1;
		self.lr = self.get_lr();
		self.exploration = self.get_exploration();
		self.targetnn = self.nn.clone();
		self.memreward = -1.0;
	}
}

impl Drop for PlayerAIQ
{
	fn drop(&mut self)
	{
		//write neural net to file, if it may has learned and was initialized
		if self.initialized && !self.fixed
		{
			let file = File::create(&self.filename);
			if file.is_err() { println!("Warning: Could not write AIQ NN file!"); return; }
			let mut writer = BufWriter::new(file.unwrap());

			let res1 = writeln!(&mut writer, "{}", self.games_played);
			let res2 = write!(&mut writer, "{}", self.nn.as_mut().unwrap().to_json());
			if res1.is_err() || res2.is_err() { println!("Warning: There was an error while writing AIQ NN file!"); return; }
		}
	}
}
<|endoftext|>


<commit_before>#![crate_name = "uptime"]
#![feature(collections, core, old_io, old_path, rustc_private, std_misc, str_words)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#![allow(non_camel_case_types)]

extern crate getopts;
extern crate libc;
extern crate time as rtime;

use std::ffi::CString;
use std::mem::transmute;
use std::old_io::{print, File};
use std::ptr::null;
use libc::{time_t, c_double, c_int, c_char};
use utmpx::*;

#[path = "../common/util.rs"] #[macro_use] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

#[cfg(unix)]
extern {
    fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *const c_utmp;
    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const c_char) -> c_int;
}

#[cfg(windows)]
extern {
    fn GetTickCount() -> libc::uint32_t;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const c_char) -> c_int {
    0
}

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", &opts).as_slice());
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let mut avg: [c_double; 3] = [0.0; 3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ");
        for n in range(0, loads) {
            print!("{:.2}{}", avg[n as usize], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, usize) {
    unsafe {
        utmpxname(CString::new(DEFAULT_FILE).unwrap().as_ptr());
    }

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, usize) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: usize) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = rtime::now();

    print!(" {:02}:{:02}:{:02} ", local_time.tm_hour,
           local_time.tm_min, local_time.tm_sec);
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_string();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return match boot_time {
                Some(t) => {
                    let now = rtime::get_time().sec;
                    let time = t as i64;
                    ((now - time) * 100) as i64 // Return in ms
                },
                _ => -1
             }
    };

    match uptime_text.as_slice().words().next() {
        Some(s) => match s.replace(".", "").as_slice().parse() {
                    Ok(n) => n,
                    Err(_) => -1
                   },
        None => -1
    }
}

#[cfg(windows)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1} day, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1} days, {:2}:{:02},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2}:{:02},  ", uphours, upmins);
    }
}
<commit_msg>fix `uptime`<commit_after>#![crate_name = "uptime"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

extern crate getopts;
extern crate libc;
extern crate time as rtime;

use std::ffi::CString;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::transmute;
use std::ptr::null;
use libc::{time_t, c_double, c_int, c_char};
use utmpx::*;

#[path = "../common/util.rs"] #[macro_use] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

#[cfg(unix)]
extern {
    fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *const c_utmp;
    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const c_char) -> c_int;
}

#[cfg(windows)]
extern {
    fn GetTickCount() -> libc::uint32_t;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const c_char) -> c_int {
    0
}

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0} [OPTION]", program);
        println!("");
        println!("{}", getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", &opts));
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let mut avg: [c_double; 3] = [0.0; 3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_mut_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ");
        for n in 0..loads {
            print!("{:.2}{}", avg[n as usize], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

#[cfg(unix)]
fn process_utmpx() -> (Option<time_t>, usize) {
    unsafe {
        utmpxname(CString::new(DEFAULT_FILE).unwrap().as_ptr());
    }

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

#[cfg(windows)]
fn process_utmpx() -> (Option<time_t>, usize) {
    (None, 0) // TODO: change 0 to number of users
}

fn print_nusers(nusers: usize) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = rtime::now();

    print!(" {:02}:{:02}:{:02} ", local_time.tm_hour,
           local_time.tm_min, local_time.tm_sec);
}

#[cfg(unix)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let mut proc_uptime = String::new();

    if let Some(n) =
        File::open("/proc/uptime").ok()
            .and_then(|mut f| f.read_to_string(&mut proc_uptime).ok())
            .and_then(|_| proc_uptime.split_whitespace().next())
            .and_then(|s| s.replace(".", "").parse().ok()) {
        n
    } else {
        match boot_time {
            Some(t) => {
                let now = rtime::get_time().sec;
                let time = t as i64;
                ((now - time) * 100)
            },
            _ => -1,
        }
    }
}

#[cfg(windows)]
fn get_uptime(boot_time: Option<time_t>) -> i64 {
    unsafe { GetTickCount() as i64 }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1} day, {:2}:{:02}, ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1} days, {:2}:{:02}, ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2}:{:02}, ", uphours, upmins);
    }
}
<|endoftext|>


<commit_before>//! [POST /_matrix/federation/v1/get_missing_events/{roomId}](https://matrix.org/docs/spec/server_server/r0.1.4#post-matrix-federation-v1-get-missing-events-roomid)

use js_int::{uint, UInt};
use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves previous events that the sender is missing.",
        method: POST,
        name: "get_missing_events",
        path: "/_matrix/federation/v1/get_missing_events/:room_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID to search in.
        #[ruma_api(path)]
        room_id: &'a RoomId,

        /// The maximum number of events to retrieve. Defaults to 10.
        #[serde(default = "default_limit", skip_serializing_if = "is_default_limit")]
        limit: UInt,

        /// The minimum depth of events to retrieve. Defaults to 0.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        min_depth: UInt,

        /// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of `latest_events`.
        earliest_events: &'a [EventId],

        /// The event IDs to retrieve the previous events for.
        latest_events: &'a [EventId],
    }

    #[derive(Default)]
    response: {
        /// The missing PDUs.
        events: Vec<Pdu>
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` for events in the given room with the given constraints.
    pub fn new(
        room_id: &'a RoomId,
        earliest_events: &'a [EventId],
        latest_events: &'a [EventId],
    ) -> Self {
        Self {
            room_id,
            limit: default_limit(),
            min_depth: UInt::default(),
            earliest_events,
            latest_events,
        }
    }
}

impl Response {
    /// Creates a new `Response` with the given events.
    pub fn new(events: Vec<Pdu>) -> Self {
        Self { events }
    }
}

fn default_limit() -> UInt {
    uint!(10)
}

fn is_default_limit(val: &UInt) -> bool {
    *val == default_limit()
}
<commit_msg>Make get_missing_events Request/Response fields pub<commit_after>//! [POST /_matrix/federation/v1/get_missing_events/{roomId}](https://matrix.org/docs/spec/server_server/r0.1.4#post-matrix-federation-v1-get-missing-events-roomid)

use js_int::{uint, UInt};
use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves previous events that the sender is missing.",
        method: POST,
        name: "get_missing_events",
        path: "/_matrix/federation/v1/get_missing_events/:room_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The room ID to search in.
        #[ruma_api(path)]
        pub room_id: &'a RoomId,

        /// The maximum number of events to retrieve. Defaults to 10.
        #[serde(default = "default_limit", skip_serializing_if = "is_default_limit")]
        pub limit: UInt,

        /// The minimum depth of events to retrieve. Defaults to 0.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        pub min_depth: UInt,

        /// The latest event IDs that the sender already has. These are skipped when retrieving the previous events of `latest_events`.
        pub earliest_events: &'a [EventId],

        /// The event IDs to retrieve the previous events for.
        pub latest_events: &'a [EventId],
    }

    #[derive(Default)]
    response: {
        /// The missing PDUs.
        pub events: Vec<Pdu>
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` for events in the given room with the given constraints.
    pub fn new(
        room_id: &'a RoomId,
        earliest_events: &'a [EventId],
        latest_events: &'a [EventId],
    ) -> Self {
        Self {
            room_id,
            limit: default_limit(),
            min_depth: UInt::default(),
            earliest_events,
            latest_events,
        }
    }
}

impl Response {
    /// Creates a new `Response` with the given events.
    pub fn new(events: Vec<Pdu>) -> Self {
        Self { events }
    }
}

fn default_limit() -> UInt {
    uint!(10)
}

fn is_default_limit(val: &UInt) -> bool {
    *val == default_limit()
}
<|endoftext|>


<commit_before>//! Tests for multiple `--target` flags to subcommands

use cargo_test_support::{basic_manifest, cross_compile, project, rustc_host};

#[cargo_test]
fn double_target_rejected() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --target a --target b")
        .with_stderr("[ERROR] specifying multiple `--target` flags requires `-Zmultitarget`")
        .with_status(101)
        .run();
}

#[cargo_test]
fn double_target_rejected_with_config() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            r#"
                [build]
                target = ["a", "b"]
            "#,
        )
        .build();

    p.cargo("build")
        .with_stderr("[ERROR] specifying multiple `--target` flags requires `-Zmultitarget`")
        .with_status(101)
        .run();
}

#[cargo_test]
fn simple_build() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.target_bin(t1, "foo").is_file());
    assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_build_with_config() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = ["{t1}", "{t2}"]
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t1, "foo").is_file());
    assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_test() {
    if !cross_compile::can_run_on_host() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/lib.rs", "fn main() {}")
        .build();

    p.cargo("test -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(&format!("[RUNNING] [..]{}[..]", t1))
        .with_stderr_contains(&format!("[RUNNING] [..]{}[..]", t2))
        .run();
}

#[cargo_test]
fn simple_run() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("run -Z multitarget --target a --target b")
        .with_stderr("[ERROR] only one `--target` argument is supported")
        .with_status(101)
        .masquerade_as_nightly_cargo()
        .run();
}

#[cargo_test]
fn simple_doc() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/lib.rs", "//! empty lib")
        .build();

    p.cargo("doc -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.build_dir().join(&t1).join("doc/foo/index.html").is_file());
    assert!(p.build_dir().join(&t2).join("doc/foo/index.html").is_file());
}

#[cargo_test]
fn simple_check() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("check -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();
}

#[cargo_test]
fn same_value_twice() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -Z multitarget")
        .arg("--target")
        .arg(&t)
        .arg("--target")
        .arg(&t)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn same_value_twice_with_config() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = ["{t}", "{t}"]
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_config_in_both_string_or_list() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = "{t}"
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());

    p.cargo("clean").run();

    p.change_file(
        ".cargo/config.toml",
        &format!(
            r#"
                [unstable]
                multitarget = true
                [build]
                target = ["{t}"]
            "#
        ),
    );

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_env() {
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build").env("CARGO_BUILD_TARGET", t).run();

    assert!(p.target_bin(t, "foo").is_file());
}
<commit_msg>test: fix to error message for multitarget<commit_after>//! Tests for multiple `--target` flags to subcommands

use cargo_test_support::{basic_manifest, cross_compile, project, rustc_host};

#[cargo_test]
fn double_target_rejected() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --target a --target b")
        .with_stderr("[ERROR] specifying multiple `--target` flags requires `-Zmultitarget`")
        .with_status(101)
        .run();
}

#[cargo_test]
fn double_target_rejected_with_config() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            r#"
                [build]
                target = ["a", "b"]
            "#,
        )
        .build();

    p.cargo("build")
        .with_stderr("[ERROR] specifying multiple `target` in `build.target` config value requires `-Zmultitarget`")
        .with_status(101)
        .run();
}

#[cargo_test]
fn simple_build() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.target_bin(t1, "foo").is_file());
    assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_build_with_config() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = ["{t1}", "{t2}"]
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t1, "foo").is_file());
    assert!(p.target_bin(t2, "foo").is_file());
}

#[cargo_test]
fn simple_test() {
    if !cross_compile::can_run_on_host() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/lib.rs", "fn main() {}")
        .build();

    p.cargo("test -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .with_stderr_contains(&format!("[RUNNING] [..]{}[..]", t1))
        .with_stderr_contains(&format!("[RUNNING] [..]{}[..]", t2))
        .run();
}

#[cargo_test]
fn simple_run() {
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("run -Z multitarget --target a --target b")
        .with_stderr("[ERROR] only one `--target` argument is supported")
        .with_status(101)
        .masquerade_as_nightly_cargo()
        .run();
}

#[cargo_test]
fn simple_doc() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/lib.rs", "//! empty lib")
        .build();

    p.cargo("doc -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.build_dir().join(&t1).join("doc/foo/index.html").is_file());
    assert!(p.build_dir().join(&t2).join("doc/foo/index.html").is_file());
}

#[cargo_test]
fn simple_check() {
    if cross_compile::disabled() {
        return;
    }
    let t1 = cross_compile::alternate();
    let t2 = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("check -Z multitarget")
        .arg("--target")
        .arg(&t1)
        .arg("--target")
        .arg(&t2)
        .masquerade_as_nightly_cargo()
        .run();
}

#[cargo_test]
fn same_value_twice() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build -Z multitarget")
        .arg("--target")
        .arg(&t)
        .arg("--target")
        .arg(&t)
        .masquerade_as_nightly_cargo()
        .run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn same_value_twice_with_config() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = ["{t}", "{t}"]
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_config_in_both_string_or_list() {
    if cross_compile::disabled() {
        return;
    }
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .file(
            ".cargo/config.toml",
            &format!(
                r#"
                    [unstable]
                    multitarget = true
                    [build]
                    target = "{t}"
                "#
            ),
        )
        .build();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());

    p.cargo("clean").run();

    p.change_file(
        ".cargo/config.toml",
        &format!(
            r#"
                [unstable]
                multitarget = true
                [build]
                target = ["{t}"]
            "#
        ),
    );

    p.cargo("build").masquerade_as_nightly_cargo().run();

    assert!(p.target_bin(t, "foo").is_file());
}

#[cargo_test]
fn works_with_env() {
    let t = rustc_host();
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build").env("CARGO_BUILD_TARGET", t).run();

    assert!(p.target_bin(t, "foo").is_file());
}
<|endoftext|>


<commit_before>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use gui::chars;
use gui::Colored;
use util::units::{AsTuple, Direction, Offset, Point, Rectangle, Size};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_frame: Rectangle,
    map_view: Point,
    info_frame: Rectangle,
    message_frame: Rectangle,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_frame: Rectangle::new(Point::new(16, 1), Size::new(63, 38)),
                map_view: Point::new(0, 0),
                info_frame: Rectangle::new(Point::new(1, 1), Size::new(13, 48)),
                message_frame: Rectangle::new(Point::new(16, 41), Size::new(63, 8)),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        None
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.draw_borders(game, console);
        self.draw_map(game, console);
        self.draw_player(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        self.draw_box_with_title(console, "Map", self.map_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
        self.draw_box_with_title(console, "Info", self.info_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
        self.draw_box_with_title(console, "Messages", self.message_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
    }

    fn draw_box_with_title(&self, console: &mut Console, title: &str, rect: Rectangle) {
        console.put_plain(rect.location() + Point::new(0, 0), chars::NW);
        console.put_plain(rect.location() + Point::new(rect.width(), 0), chars::NE);
        console.put_plain(rect.location() + Point::new(0, rect.height()), chars::SW);
        console.put_plain(rect.location() + Point::new(rect.width(), rect.height()), chars::SE);

        for x in 1..rect.width() {
            console.put_plain(rect.location() + Point::new(x, 0), chars::HLINE);
            console.put_plain(rect.location() + Point::new(x, rect.height()), chars::HLINE);
        }

        for y in 1..rect.height() {
            console.put_plain(rect.location() + Point::new(0, y), chars::VLINE);
            console.put_plain(rect.location() + Point::new(rect.width(), y), chars::VLINE);
        }

        console.print_plain(rect.location() + Point::new(1, 0), title);
    }

    #[allow(unused)]
    fn draw_map(&self, game: &mut Game, console: &mut Console) {
        let map = &game.world.map;

        let (ux, uy): (usize, usize) = self.map_view.as_tuple();
        let (width, height) = self.map_frame.size().as_tuple();

        for (y, line) in map.tiles[uy .. uy + height].iter().enumerate() {
            for (x, cell) in line[ux .. ux + width].iter().enumerate() {
                console.put(self.map_frame.location() + Point::new(x as i32, y as i32), ' ', Colors::white, cell.bg_color());
            }
        }
    }

    #[allow(unused)]
    fn draw_player(&mut self, game: &mut Game, console: &mut Console) {
        let pos = game.world.player.pos;

        let adjusted_pos = pos + self.map_frame.location() - self.map_view;

        if adjusted_pos.x >= self.map_frame.location().x + self.map_frame.width() - 10 {
            if self.view_can_move_right(game) {
                self.map_view = self.map_view.right(1);
            }
        }

        if adjusted_pos.y >= self.map_frame.location().y + self.map_frame.height() - 5 {
            if self.view_can_move_down(game) {
                self.map_view = self.map_view.down(1);
            }
        }

        if adjusted_pos.y <= self.map_frame.location().y + 5 {
            if self.view_can_move_up(game) {
                self.map_view = self.map_view.up(1);
            }
        }

        if adjusted_pos.x <= self.map_frame.location().x + 10 {
            if self.view_can_move_left(game) {
                self.map_view = self.map_view.left(1);
            }
        }

        if adjusted_pos.x >= self.map_frame.location().x && adjusted_pos.y >= self.map_frame.location().y {
            console.put_plain(self.map_frame.location() - self.map_view + pos, '@');
        }
    }

    #[allow(unused)]
    fn view_can_move_up(&self, game: &Game) -> bool {
        self.map_view.y  > 0
    }

    #[allow(unused)]
    fn view_can_move_down(&self, game: &Game) -> bool {
        self.map_view.y + self.map_frame.height() < game.world.map.height()
    }

    #[allow(unused)]
    fn view_can_move_left(&self, game: &Game) -> bool {
        self.map_view.x > 0
    }

    #[allow(unused)]
    fn view_can_move_right(&self, game: &Game) -> bool {
        self.map_view.x + self.map_frame.width() < game.world.map.width()
    }

}
<commit_msg>Clean up draw_box code in game_screen<commit_after>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use gui::chars;
use gui::Colored;
use util::units::{AsTuple, Direction, Offset, Point, Rectangle, Size};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_frame: Rectangle,
    map_view: Point,
    info_frame: Rectangle,
    message_frame: Rectangle,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_frame: Rectangle::new(Point::new(16, 1), Size::new(63, 38)),
                map_view: Point::new(0, 0),
                info_frame: Rectangle::new(Point::new(1, 1), Size::new(13, 48)),
                message_frame: Rectangle::new(Point::new(16, 41), Size::new(63, 8)),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        None
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.draw_borders(game, console);
        self.draw_map(game, console);
        self.draw_player(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        self.draw_box_with_title(console, "Map", self.map_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
        self.draw_box_with_title(console, "Info", self.info_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
        self.draw_box_with_title(console, "Messages", self.message_frame.translate(Offset::new(-1, -1)).resize(Offset::new(1, 1)));
    }

    fn draw_box_with_title(&self, console: &mut Console, title: &str, rect: Rectangle) {

        let loc = rect.location();
        let width = rect.width();
        let height = rect.height();

        console.put_plain(loc + (0, 0),             chars::NW);
        console.put_plain(loc + (width, 0),         chars::NE);
        console.put_plain(loc + (0, height),        chars::SW);
        console.put_plain(loc + (width, height),    chars::SE);

        for x in 1..width {
            console.put_plain(loc + (x, 0),         chars::HLINE);
            console.put_plain(loc + (x, height),    chars::HLINE);
        }

        for y in 1..height {
            console.put_plain(loc + (0, y),         chars::VLINE);
            console.put_plain(loc + (width, y),     chars::VLINE);
        }

        console.print_plain(rect.location() + (1, 0), title);
    }

    #[allow(unused)]
    fn draw_map(&self, game: &mut Game, console: &mut Console) {
        let map = &game.world.map;

        let (ux, uy): (usize, usize) = self.map_view.as_tuple();
        let (width, height) = self.map_frame.size().as_tuple();

        for (y, line) in map.tiles[uy .. uy + height].iter().enumerate() {
            for (x, cell) in line[ux .. ux + width].iter().enumerate() {
                console.put(self.map_frame.location() + Point::new(x as i32, y as i32), ' ', Colors::white, cell.bg_color());
            }
        }
    }

    #[allow(unused)]
    fn draw_player(&mut self, game: &mut Game, console: &mut Console) {
        let pos = game.world.player.pos;

        let adjusted_pos = pos + self.map_frame.location() - self.map_view;

        if adjusted_pos.x >= self.map_frame.location().x + self.map_frame.width() - 10 {
            if self.view_can_move_right(game) {
                self.map_view = self.map_view.right(1);
            }
        }

        if adjusted_pos.y >= self.map_frame.location().y + self.map_frame.height() - 5 {
            if self.view_can_move_down(game) {
                self.map_view = self.map_view.down(1);
            }
        }

        if adjusted_pos.y <= self.map_frame.location().y + 5 {
            if self.view_can_move_up(game) {
                self.map_view = self.map_view.up(1);
            }
        }

        if adjusted_pos.x <= self.map_frame.location().x + 10 {
            if self.view_can_move_left(game) {
                self.map_view = self.map_view.left(1);
            }
        }

        if adjusted_pos.x >= self.map_frame.location().x && adjusted_pos.y >= self.map_frame.location().y {
            console.put_plain(self.map_frame.location() - self.map_view + pos, '@');
        }
    }

    #[allow(unused)]
    fn view_can_move_up(&self, game: &Game) -> bool {
        self.map_view.y  > 0
    }

    #[allow(unused)]
    fn view_can_move_down(&self, game: &Game) -> bool {
        self.map_view.y + self.map_frame.height() < game.world.map.height()
    }

    #[allow(unused)]
    fn view_can_move_left(&self, game: &Game) -> bool {
        self.map_view.x > 0
    }

    #[allow(unused)]
    fn view_can_move_right(&self, game: &Game) -> bool {
        self.map_view.x + self.map_frame.width() < game.world.map.width()
    }

}
<|endoftext|>


<commit_before>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use util::units::{Direction, Point};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_location: Point,
    info_location: Point,
    message_location: Point,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_location: Point::new(16, 1),
                info_location: Point::new(1, 1),
                message_location: Point::new(16, 41),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        return None;
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.render_map(game, console);

        let repr = game.world.player.repr;
        let pos = game.world.player.pos;

        console.put_plain(self.map_location + pos, repr);

        self.draw_borders(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        let CHAR_VLINE = 179 as char;
        let CHAR_HLINE = 196 as char;
        let CHAR_CORNER_NW = 218 as char;
        let CHAR_CORNER_NE = 191 as char;
        let CHAR_CORNER_SW = 192 as char;
        let CHAR_CORNER_SE = 217 as char;

        console.put_plain(self.map_location + Point::new(-1, -1), CHAR_CORNER_NW);
        console.put_plain(self.map_location + Point::new(63, -1), CHAR_CORNER_NE);
        console.put_plain(self.map_location + Point::new(-1, 38), CHAR_CORNER_SW);
        console.put_plain(self.map_location + Point::new(63, 38), CHAR_CORNER_SE);

        for x in 0..63 {
            console.put_plain(self.map_location + Point::new(x, -1), CHAR_HLINE);
            console.put_plain(self.map_location + Point::new(x, 38), CHAR_HLINE);
        }

        for y in 0..38 {
            console.put_plain(self.map_location + Point::new(-1, y), CHAR_VLINE);
            console.put_plain(self.map_location + Point::new(63, y), CHAR_VLINE);
        }

        console.put_plain(self.map_location + Point::new(0, -1), 'M');
        console.put_plain(self.map_location + Point::new(1, -1), 'a');
        console.put_plain(self.map_location + Point::new(2, -1), 'p');

        console.put_plain(self.info_location + Point::new(-1, -1), CHAR_CORNER_NW);
        console.put_plain(self.info_location + Point::new(13, -1), CHAR_CORNER_NE);
        console.put_plain(self.info_location + Point::new(-1, 48), CHAR_CORNER_SW);
        console.put_plain(self.info_location + Point::new(13, 48), CHAR_CORNER_SE);

        for x in 0..13 {
            console.put_plain(self.info_location + Point::new(x, -1), CHAR_HLINE);
            console.put_plain(self.info_location + Point::new(x, 48), CHAR_HLINE);
        }

        for y in 0..48 {
            console.put_plain(self.info_location + Point::new(-1, y), CHAR_VLINE);
            console.put_plain(self.info_location + Point::new(13, y), CHAR_VLINE);
        }

        console.put_plain(self.info_location + Point::new(0, -1), 'I');
        console.put_plain(self.info_location + Point::new(1, -1), 'n');
        console.put_plain(self.info_location + Point::new(2, -1), 'f');
        console.put_plain(self.info_location + Point::new(3, -1), 'o');

        console.put_plain(self.message_location + Point::new(-1, -1), CHAR_CORNER_NW);
        console.put_plain(self.message_location + Point::new(63, -1), CHAR_CORNER_NE);
        console.put_plain(self.message_location + Point::new(-1,  8), CHAR_CORNER_SW);
        console.put_plain(self.message_location + Point::new(63,  8), CHAR_CORNER_SE);

        for x in 0..63 {
            console.put_plain(self.message_location + Point::new(x, -1), CHAR_HLINE);
            console.put_plain(self.message_location + Point::new(x,  8), CHAR_HLINE);
        }

        for y in 0..8 {
            console.put_plain(self.message_location + Point::new(-1, y), CHAR_VLINE);
            console.put_plain(self.message_location + Point::new(63, y), CHAR_VLINE);
        }

        console.put_plain(self.message_location + Point::new(0, -1), 'M');
        console.put_plain(self.message_location + Point::new(1, -1), 'e');
        console.put_plain(self.message_location + Point::new(2, -1), 's');
        console.put_plain(self.message_location + Point::new(3, -1), 's');
        console.put_plain(self.message_location + Point::new(4, -1), 'a');
        console.put_plain(self.message_location + Point::new(5, -1), 'g');
        console.put_plain(self.message_location + Point::new(6, -1), 'e');
        console.put_plain(self.message_location + Point::new(7, -1), 's');

    }

    #[allow(unused)]
    fn render_map(&self, game: &mut Game, console: &mut Console) {
        let map = &(game.world.map);

        for (y, line) in map.tiles.iter().enumerate() {
            for (x, cell) in line.iter().enumerate() {
                console.put(self.map_location + Point::new(x as i32, y as i32), ' ', Colors::white, cell.b_color());
            }
        }
    }

}
<commit_msg>Transition to using chars::CHAR for special chars<commit_after>use engine::Game;
use gui::screens::{self, Screen, ScreenChange};
use gui::{Console, Colors, Key};
use gui::chars;
use util::units::{Direction, Point};

#[allow(missing_copy_implementations)]
pub struct GameScreen {
    map_location: Point,
    info_location: Point,
    message_location: Point,
}

impl GameScreen {
    pub fn new() -> Box<Screen> {
        Box::new(
            GameScreen {
                map_location: Point::new(16, 1),
                info_location: Point::new(1, 1),
                message_location: Point::new(16, 41),
            }
        )
    }
}

impl Screen for GameScreen {

    #[allow(unused)]
    fn input(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        if let Some(key) = console.check_for_keypress() {
            match key {
                Key::Up => {
                    game.world.walk(Direction::Up);
                },
                Key::Down => {
                    game.world.walk(Direction::Down);
                },
                Key::Left => {
                    game.world.walk(Direction::Left);
                },
                Key::Right => {
                    game.world.walk(Direction::Right);
                },
                Key::Escape => {
                    return Some(ScreenChange::AddScreen(screens::PauseScreen::new()));
                },
                _ => {}
            }
        }

        None
    }

    #[allow(unused)]
    fn update(&mut self, game: &mut Game, console: &mut Console) -> Option<ScreenChange> {
        return None;
    }

    #[allow(unused)]
    fn render(&mut self, game: &mut Game, console: &mut Console) {
        self.render_map(game, console);

        let repr = game.world.player.repr;
        let pos = game.world.player.pos;

        console.put_plain(self.map_location + pos, repr);

        self.draw_borders(game, console);
    }
}

impl GameScreen {

    #[allow(unused)]
    fn draw_borders(&self, game: &mut Game, console: &mut Console) {
        console.put_plain(self.map_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.map_location + Point::new(63, -1), chars::NE as char);
        console.put_plain(self.map_location + Point::new(-1, 38), chars::SW as char);
        console.put_plain(self.map_location + Point::new(63, 38), chars::SE as char);

        for x in 0..63 {
            console.put_plain(self.map_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.map_location + Point::new(x, 38), chars::HLINE as char);
        }

        for y in 0..38 {
            console.put_plain(self.map_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.map_location + Point::new(63, y), chars::VLINE as char);
        }

        console.put_plain(self.map_location + Point::new(0, -1), 'M');
        console.put_plain(self.map_location + Point::new(1, -1), 'a');
        console.put_plain(self.map_location + Point::new(2, -1), 'p');

        console.put_plain(self.info_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.info_location + Point::new(13, -1), chars::NE as char);
        console.put_plain(self.info_location + Point::new(-1, 48), chars::SW as char);
        console.put_plain(self.info_location + Point::new(13, 48), chars::SE as char);

        for x in 0..13 {
            console.put_plain(self.info_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.info_location + Point::new(x, 48), chars::HLINE as char);
        }

        for y in 0..48 {
            console.put_plain(self.info_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.info_location + Point::new(13, y), chars::VLINE as char);
        }

        console.put_plain(self.info_location + Point::new(0, -1), 'I');
        console.put_plain(self.info_location + Point::new(1, -1), 'n');
        console.put_plain(self.info_location + Point::new(2, -1), 'f');
        console.put_plain(self.info_location + Point::new(3, -1), 'o');

        console.put_plain(self.message_location + Point::new(-1, -1), chars::NW as char);
        console.put_plain(self.message_location + Point::new(63, -1), chars::NE as char);
        console.put_plain(self.message_location + Point::new(-1,  8), chars::SW as char);
        console.put_plain(self.message_location + Point::new(63,  8), chars::SE as char);

        for x in 0..63 {
            console.put_plain(self.message_location + Point::new(x, -1), chars::HLINE as char);
            console.put_plain(self.message_location + Point::new(x,  8), chars::HLINE as char);
        }

        for y in 0..8 {
            console.put_plain(self.message_location + Point::new(-1, y), chars::VLINE as char);
            console.put_plain(self.message_location + Point::new(63, y), chars::VLINE as char);
        }

        console.put_plain(self.message_location + Point::new(0, -1), 'M');
        console.put_plain(self.message_location + Point::new(1, -1), 'e');
        console.put_plain(self.message_location + Point::new(2, -1), 's');
        console.put_plain(self.message_location + Point::new(3, -1), 's');
        console.put_plain(self.message_location + Point::new(4, -1), 'a');
        console.put_plain(self.message_location + Point::new(5, -1), 'g');
        console.put_plain(self.message_location + Point::new(6, -1), 'e');
        console.put_plain(self.message_location + Point::new(7, -1), 's');

    }

    #[allow(unused)]
    fn render_map(&self, game: &mut Game, console: &mut Console) {
        let map = &(game.world.map);

        for (y, line) in map.tiles.iter().enumerate() {
            for (x, cell) in line.iter().enumerate() {
                console.put(self.map_location + Point::new(x as i32, y as i32), ' ', Colors::white, cell.b_color());
            }
        }
    }

}
<|endoftext|>


<commit_before>#![feature(core, os, io, path)]

extern crate zip;

use std::old_io::File;
use zip::ZipReader;
use zip::fileinfo::FileInfo;

fn main() {
    let args = std::os::args();
    match args.len()
    {
        2 => list(&mut zip_file(&args[1][])),
        3 => extract(&mut zip_file(&args[1][]), &args[2][]),
        _ => usage(&args[0][])
    }
}

macro_rules! do_or_die{
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {println!("{}",err); panic!()}
    })
}

fn zip_file(file: &str) -> ZipReader<File>{
    do_or_die!(zip::ZipReader::open(&Path::new(file)))
}

fn output_file(file: &str)->File{
    do_or_die!(File::create(&Path::new(file)))
}

fn zipped_file_info(zip: &mut ZipReader<File>, file: &str) -> FileInfo{
    do_or_die!(zip.info(file))
}

fn list(reader: &mut ZipReader<File>)->(){
    for file in reader.files(){
        let (year, month, day, hour, minute, second) = file.last_modified_datetime;
        let mod_time = format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", year, month, day, hour, minute, second);
        println!("{} ({}): bytes: {:10}, compressed: {:10}",
            file.name, mod_time, file.compressed_size, file.uncompressed_size);
    }
}

fn extract(zip: &mut ZipReader<File>, file: &str)->(){
    let mut out = output_file(file);
    let info = zipped_file_info(zip, file);
    do_or_die!(zip.extract(&info, &mut out));
}

fn usage(this: &str)->(){
    println!("Usage: {} [file.zip] [file_to_extract]", this);
}
<commit_msg>Make zip-demo code close to root<commit_after>#![feature(core, os, io, path)]

extern crate zip;
use std::os;
use std::old_io::File;
use zip::ZipReader;
use zip::fileinfo::FileInfo;

fn main() {
    let args = os::args();
    match args.len()
    {
        2 => list(&mut zip_file(&args[1][])),
        3 => extract(&mut zip_file(&args[1][]), &args[2][]),
        _ => usage(&args[0][])
    }
}

macro_rules! do_or_die{
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {println!("{}",err); panic!()}
    })
}

fn zip_file(file: &str) -> ZipReader<File>{
    do_or_die!(zip::ZipReader::open(&Path::new(file)))
}

fn output_file(file: &str)->File{
    do_or_die!(File::create(&Path::new(file)))
}

fn zipped_file_info(zip: &mut ZipReader<File>, file: &str) -> FileInfo{
    do_or_die!(zip.info(file))
}

fn list(reader: &mut ZipReader<File>)->(){
    for file in reader.files(){
        let (year, month, day, hour, minute, second) = file.last_modified_datetime;
        let mod_time = format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", year, month, day, hour, minute, second);
        println!("{} ({}): bytes: {:10}, compressed: {:10}",
            file.name, mod_time, file.compressed_size, file.uncompressed_size);
    }
}

fn extract(zip: &mut ZipReader<File>, file: &str)->(){
    let mut out = output_file(file);
    let info = zipped_file_info(zip, file);
    do_or_die!(zip.extract(&info, &mut out));
}

fn usage(this: &str)->(){
    println!("Usage: {} [file.zip] [file_to_extract]", this);
}
<|endoftext|>