<commit_before>use byteorder::{WriteBytesExt, BigEndian};
use std::io::{Result, Read};

use std::fs::{File};

struct Header {
    magic: [u8; 4],
    orig_length: u32, // for some reasons the decrucnher asm checks if the first byte is a 0
                      // maybe it is a real u24?
    unknown: u32, // probably a checksum... again...checking explicitly for 0 in the asm :S
}

enum Chunk {
    Unique {
        data: Vec<u8>,
    },
    Repeated {
        byte: u8,
        num: u8,
    },
}

fn write_chunk<T: WriteBytesExt>(chunk: Chunk, mut target: T) -> Result<()> {
    match chunk {
        Chunk::Unique { data } => {
            // argh...negating without the compiler being a dingens
            try!(target.write_i8((data.len() as i32 * -1) as i8));
            for c in data.iter() {
                try!(target.write_u8(*c));
            }
        },
        Chunk::Repeated { byte, num } => {
            try!(target.write_u8(num - 1));
            try!(target.write_u8(byte));
        }
    }
    Ok(())
}

fn write_header<T: WriteBytesExt>(length: u64, mut target: T) -> Result<usize> {
    let header = Header { magic: *b"RPck", orig_length: length as u32, unknown: 0};
    for c in header.magic.iter() {
        try!(target.write_u8(*c));
    }

    try!(target.write_u32::<BigEndian>(header.orig_length));
    try!(target.write_u32::<BigEndian>(header.unknown));
    Ok(1)
}

pub fn archive<T: Read>(rfile: T, size: u64, wfile: File) -> Result<usize> {
    try!(write_header(size, &wfile));

    let mut current: Option<Chunk> = None;

    for byte in rfile.bytes() {
        // this is all looking super fuzzy :S n00bish code is n00bish :D
        let b = byte.unwrap();
        current = match current {
            None => Some(Chunk::Unique { data: [b].to_vec()}),
            Some(current) => {
                match current {
                    // pyramid, pyramid!
                    Chunk::Unique { mut data } => {
                        if b == *data.last().unwrap() {
                            // if it is unique (data[0] != data[1]) it must be at least 2 bytes long :S
                            // (that's what I found out from example files)
                            match data.len() {
                                1 => {
                                    Some(Chunk::Repeated {
                                        byte: b,
                                        num: 2,
                                    })
                                },
                                2 => {
                                    data.push(b);
                                    Some(Chunk::Unique {
                                        data: data,
                                    })
                                },
                                127 => {
                                    try!(write_chunk(Chunk::Unique {
                                        data: data,
                                    }, &wfile));
                                    Some(Chunk::Unique { data: [b].to_vec()})
                                },
                                _ => {
                                    let mut num = 1;
                                    while data.len() != 2 && *data.last().unwrap() == b {
                                        num += 1;
                                        data.pop();
                                    }
                                    if data.len() > 0 {
                                        try!(write_chunk(Chunk::Unique {
                                            data: data,
                                        }, &wfile));
                                    }
                                    Some(Chunk::Repeated {
                                        byte: b,
                                        num: num,
                                    })
                                }
                            }
                        } else {
                            data.push(b);
                            Some(Chunk::Unique {
                                data: data,
                            })
                        }
                    },
                    Chunk::Repeated { byte, mut num } => {
                        if b == byte {
                            num += 1;
                            let result = Chunk::Repeated {
                                byte: b,
                                num: num,
                            };
                            if num < 127 {
                                Some(result)
                            } else {
                                try!(write_chunk(result, &wfile));
                                None
                            }
                        } else {
                            try!(write_chunk(current, &wfile));
                            Some(Chunk::Unique { data: [b].to_vec()})
                        }
                    }
                }
            }
        }
    }
    if current.is_some() {
        try!(write_chunk(current.unwrap(), wfile));
    }
    Ok(1)
}<commit_msg>it compiles :O<commit_after>use byteorder::{WriteBytesExt, BigEndian};
use std::io::{Result, Read, Write};
use std::fs::{File};

struct Header {
    magic: [u8; 4],
    orig_length: u32, // for some reasons the decrucnher asm checks if the first byte is a 0
                      // maybe it is a real u24?
    unknown: u32, // probably a checksum... again...checking explicitly for 0 in the asm :S
}

enum Chunk {
    Unique {
        data: Vec<u8>,
    },
    Repeated {
        byte: u8,
        num: u8,
    },
}

fn write_chunk<T: WriteBytesExt>(chunk: Chunk, mut target: T) -> Result<()> {
    match chunk {
        Chunk::Unique { data } => {
            // argh...negating without the compiler being a dingens
            try!(target.write_i8((data.len() as i32 * -1) as i8));
            for c in data.iter() {
                try!(target.write_u8(*c));
            }
        },
        Chunk::Repeated { byte, num } => {
            try!(target.write_u8(num - 1));
            try!(target.write_u8(byte));
        }
    }
    Ok(())
}

fn write_header<T: WriteBytesExt>(length: u64, mut target: T) -> Result<usize> {
    let header = Header { magic: *b"RPck", orig_length: length as u32, unknown: 0};
    for c in header.magic.iter() {
        try!(target.write_u8(*c));
    }

    try!(target.write_u32::<BigEndian>(header.orig_length));
    try!(target.write_u32::<BigEndian>(header.unknown));
    Ok(1)
}

pub fn archive<T: Read>(rfile: T, size: u64, wfile: File) -> Result<()> {
    try!(write_header(size, &wfile));
    write_data(rfile, &wfile)
}

fn write_data<'a, TR: Read, TW: 'a>(readable: TR, writeable: &'a TW) -> Result<()> where &'a TW: Write {
    let mut current: Option<Chunk> = None;
    for byte in readable.bytes() {
        // this is all looking super fuzzy :S n00bish code is n00bish :D
        let b = byte.unwrap();
        current = match current {
            None => Some(Chunk::Unique { data: [b].to_vec()}),
            Some(current) => {
                match current {
                    // pyramid, pyramid!
                    Chunk::Unique { mut data } => {
                        if b == *data.last().unwrap() {
                            // if it is unique (data[0] != data[1]) it must be at least 2 bytes long :S
                            // (that's what I found out from example files)
                            match data.len() {
                                1 => {
                                    Some(Chunk::Repeated {
                                        byte: b,
                                        num: 2,
                                    })
                                },
                                2 => {
                                    data.push(b);
                                    Some(Chunk::Unique {
                                        data: data,
                                    })
                                },
                                127 => {
                                    try!(write_chunk(Chunk::Unique {
                                        data: data,
                                    }, writeable));
                                    Some(Chunk::Unique { data: [b].to_vec()})
                                },
                                _ => {
                                    let mut num = 1;
                                    while data.len() != 2 && *data.last().unwrap() == b {
                                        num += 1;
                                        data.pop();
                                    }
                                    if data.len() > 0 {
                                        try!(write_chunk(Chunk::Unique {
                                            data: data,
                                        }, writeable));
                                    }
                                    Some(Chunk::Repeated {
                                        byte: b,
                                        num: num,
                                    })
                                }
                            }
                        } else {
                            data.push(b);
                            Some(Chunk::Unique {
                                data: data,
                            })
                        }
                    },
                    Chunk::Repeated { byte, mut num } => {
                        if b == byte {
                            num += 1;
                            let result = Chunk::Repeated {
                                byte: b,
                                num: num,
                            };
                            if num < 127 {
                                Some(result)
                            } else {
                                try!(write_chunk(result, writeable));
                                None
                            }
                        } else {
                            try!(write_chunk(current, writeable));
                            Some(Chunk::Unique { data: [b].to_vec()})
                        }
                    }
                }
            }
        }
    }
    if current.is_some() {
        try!(write_chunk(current.unwrap(), writeable));
    }
    Ok(())
}<|endoftext|>


<commit_before>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::mem;
use std::ffi::{CStr, OsStr};
use std::path::Path;
use std::os::unix::ffi::OsStrExt;
use libc::c_char;

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
    data: &'a [u8],
    pos: usize,
}

impl<'a> ArgumentIterator<'a> {
    /// Create a new argument iterator for the given byte slice
    pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
        ArgumentIterator { data: data, pos: 0 }
    }

    /// Fetch a typed argument
    pub fn fetch<T> (&mut self) -> &'a T {
        let ptr = unsafe { self.data.as_ptr().offset(self.pos as isize) };
        let value = unsafe { mem::transmute(ptr) };
        self.pos += mem::size_of::<T>();
        assert!(self.pos <= self.data.len(), "trying to fetch argument behind data");
        value
    }

    /// Fetch a (zero-terminated) string (can be non-utf8)
    pub fn fetch_str (&mut self) -> &'a OsStr {
        let ptr = unsafe { self.data.as_ptr().offset(self.pos as isize) };
        let s = unsafe { CStr::from_ptr(ptr as *const c_char) };
        self.pos += s.to_bytes_with_nul().len();
        OsStr::from_bytes(s.to_bytes())
    }

    /// Fetch a (zero-terminated) path (can be non-utf8)
    pub fn fetch_path (&mut self) -> &'a Path {
        Path::new(self.fetch_str())
    }

    /// Fetch a slice of the remaining data
    pub fn fetch_data (&mut self) -> &'a [u8] {
        let bytes = &self.data[self.pos..];
        self.pos = self.data.len();
        bytes
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::ArgumentIterator;

    static TEST_DATA: [u8; 12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
    struct TestArgument { p1: u8, p2: u8, p3: u16 }

    #[test]
    fn generic_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x62);
        assert_eq!(arg.p2, 0x61);
        assert_eq!(arg.p3, 0x0072);
    }

    #[test]
    fn string_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_str();
        assert_eq!(arg, "foo");
        let arg = it.fetch_str();
        assert_eq!(arg, "bar");
    }

    #[test]
    fn path_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_path();
        assert_eq!(arg, Path::new("foo"));
        let arg = it.fetch_path();
        assert_eq!(arg, Path::new("bar"));
    }

    #[test]
    fn remaining_data_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        it.fetch_str();
        it.fetch_str();
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00]);
    }

    #[test]
    fn mixed_arguments () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg = it.fetch_str();
        assert_eq!(arg, "bar");
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00]);
    }
}
<commit_msg>Improve argument iterator (less unsafe code, platform independent)<commit_after>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::mem;
use std::ffi::OsStr;
use std::path::Path;
use std::os::unix::ffi::OsStrExt;

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
    data: &'a [u8],
}

impl<'a> ArgumentIterator<'a> {
    /// Create a new argument iterator for the given byte slice
    pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
        ArgumentIterator { data: data }
    }

    /// Fetch a typed argument
    pub fn fetch<T> (&mut self) -> &'a T {
        let len = mem::size_of::<T>();
        assert!(len <= self.data.len(), "out of data while fetching typed argument");
        let bytes = &self.data[..len];
        self.data = &self.data[len..];
        unsafe { mem::transmute(bytes.as_ptr()) }
    }

    /// Fetch a (zero-terminated) string (can be non-utf8)
    pub fn fetch_str (&mut self) -> &'a OsStr {
        let len = self.data.iter().position(|&c| c == 0).expect("out of data while fetching string argument");
        let bytes = &self.data[..len];
        self.data = &self.data[len+1..];
        OsStr::from_bytes(&bytes)
    }

    /// Fetch a (zero-terminated) path (can be non-utf8)
    pub fn fetch_path (&mut self) -> &'a Path {
        Path::new(self.fetch_str())
    }

    /// Fetch a slice of all remaining data
    pub fn fetch_data (&mut self) -> &'a [u8] {
        let bytes = self.data;
        self.data = &[];
        bytes
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::ArgumentIterator;

    static TEST_DATA: [u8; 12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
    struct TestArgument { p1: u8, p2: u8, p3: u16 }

    #[test]
    fn generic_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x62);
        assert_eq!(arg.p2, 0x61);
        assert_eq!(arg.p3, 0x0072);
    }

    #[test]
    fn string_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_str();
        assert_eq!(arg, "foo");
        let arg = it.fetch_str();
        assert_eq!(arg, "bar");
    }

    #[test]
    fn path_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_path();
        assert_eq!(arg, Path::new("foo"));
        let arg = it.fetch_path();
        assert_eq!(arg, Path::new("bar"));
    }

    #[test]
    fn data_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        it.fetch_str();
        it.fetch_str();
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00]);
    }

    #[test]
    fn mixed_arguments () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg = it.fetch_str();
        assert_eq!(arg, "bar");
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00]);
    }
}
<|endoftext|>


<commit_before>use token::*;
use parse::*;

/// Token iterator instance
///
/// # Example
/// ```ignore
/// extern crate lazy_bencoding;
/// use lazy_bencoding::*;
///
/// let bencoded = BEncoded::new(&data[..]);
/// let name = bencoded.get(b"info").get(b"name").get_utf8_string();
/// ```
///
/// You may now:
///
/// * iterate over `bencoded` to process all [`Token`](enum.Token.html) in order, or
/// * traverse the structure using [`get()`](#method.get) and [`get_utf8_string()`](#method.get_utf8_string).
#[derive(Clone, Copy)]
pub struct BEncoded<'a> {
    /// Next data to parse, only a cheap reference and updated with
    /// each [`next()`](#method.next)
    pub data: &'a [u8],
    /// Keeping track of the depth, for:
    ///
    /// * traversing, and
    /// * stopping after one item, before trailing data.
    pub depth: i16,
}

impl<'a> BEncoded<'a> {
    /// Construct from a pointer to data
    pub fn new(data: &'a [u8]) -> Self {
        BEncoded {
            data: data,
            depth: 0,
        }
    }

    /// Construct with empty data,
    /// used for when traversing fails
    pub fn empty() -> BEncoded<'static> {
        BEncoded {
            data: b"",
            depth: 0
        }
    }
}

/// The [token](enum.Token.html) stream. Advances `self.data` and updates `self.depth`.
impl<'a> Iterator for BEncoded<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.depth < 0 {
            // Already done
            return None;
        }

        match parse_token(self.data) {
            None => None,
            Some((token, rest)) => {
                match token {
                    Token::ListStart | Token::DictStart =>
                        self.depth += 1,
                    Token::End =>
                        self.depth -= 1,
                    _ =>
                        ()
                }
                if self.depth == 0 {
                    // Emit only one item at level 0
                    self.depth -= 1;
                }

                self.data = rest;
                Some(token)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    fn expect<'a>(input: &'a [u8], expected: &[::Token<'a>]) {
        let bencoded = ::BEncoded::new(input);
        let result = bencoded.collect::<Vec<::Token<'a>>>();
        assert_eq!(result, expected);
    }

    #[test]
    fn test_strings() {
        expect(b"4:spam", &[::Token::ByteString(b"spam")]);
    }

    #[test]
    fn test_integers() {
        expect(b"i3e", &[::Token::Integer(b"3")]);
        expect(b"i-3e", &[::Token::Integer(b"-3")]);
        expect(b"i0e", &[::Token::Integer(b"0")]);
    }

    #[test]
    fn test_lists() {
        expect(b"l4:spam4:eggse",
               &[::Token::ListStart,
                 ::Token::ByteString(b"spam"),
                 ::Token::ByteString(b"eggs"),
                 ::Token::End]);
    }

    #[test]
    fn test_dict() {
        expect(b"d3:cow3:moo4:spam4:eggse",
               &[::Token::DictStart,
                 ::Token::ByteString(b"cow"),
                 ::Token::ByteString(b"moo"),
                 ::Token::ByteString(b"spam"),
                 ::Token::ByteString(b"eggs"),
                 ::Token::End]);
        expect(b"d4:spaml1:a1:bee",
               &[::Token::DictStart,
                 ::Token::ByteString(b"spam"),
                 ::Token::ListStart,
                 ::Token::ByteString(b"a"),
                 ::Token::ByteString(b"b"),
                 ::Token::End,
                 ::Token::End]);
    }

    #[test]
    fn test_only_one() {
        expect(b"4:spam4:eggs", &[::Token::ByteString(b"spam")]);
    }
}
<commit_msg>bencoded: no longer derive Copy<commit_after>use token::*;
use parse::*;

/// Token iterator instance
///
/// # Example
/// ```ignore
/// extern crate lazy_bencoding;
/// use lazy_bencoding::*;
///
/// let bencoded = BEncoded::new(&data[..]);
/// let name = bencoded.get(b"info").get(b"name").get_utf8_string();
/// ```
///
/// You may now:
///
/// * iterate over `bencoded` to process all [`Token`](enum.Token.html) in order, or
/// * traverse the structure using [`get()`](#method.get) and [`get_utf8_string()`](#method.get_utf8_string).
#[derive(Clone)]
pub struct BEncoded<'a> {
    /// Next data to parse, only a cheap reference and updated with
    /// each [`next()`](#method.next)
    pub data: &'a [u8],
    /// Keeping track of the depth, for:
    ///
    /// * traversing, and
    /// * stopping after one item, before trailing data.
    pub depth: i16,
}

impl<'a> BEncoded<'a> {
    /// Construct from a pointer to data
    pub fn new(data: &'a [u8]) -> Self {
        BEncoded {
            data: data,
            depth: 0,
        }
    }

    /// Construct with empty data,
    /// used for when traversing fails
    pub fn empty() -> BEncoded<'static> {
        BEncoded {
            data: b"",
            depth: 0
        }
    }
}

/// The [token](enum.Token.html) stream. Advances `self.data` and updates `self.depth`.
impl<'a> Iterator for BEncoded<'a> {
    type Item = Token<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.depth < 0 {
            // Already done
            return None;
        }

        match parse_token(self.data) {
            None => None,
            Some((token, rest)) => {
                match token {
                    Token::ListStart | Token::DictStart =>
                        self.depth += 1,
                    Token::End =>
                        self.depth -= 1,
                    _ =>
                        ()
                }
                if self.depth == 0 {
                    // Emit only one item at level 0
                    self.depth -= 1;
                }

                self.data = rest;
                Some(token)
            }
        }
    }
}

#[cfg(test)]
mod tests {
    fn expect<'a>(input: &'a [u8], expected: &[::Token<'a>]) {
        let bencoded = ::BEncoded::new(input);
        let result = bencoded.collect::<Vec<::Token<'a>>>();
        assert_eq!(result, expected);
    }

    #[test]
    fn test_strings() {
        expect(b"4:spam", &[::Token::ByteString(b"spam")]);
    }

    #[test]
    fn test_integers() {
        expect(b"i3e", &[::Token::Integer(b"3")]);
        expect(b"i-3e", &[::Token::Integer(b"-3")]);
        expect(b"i0e", &[::Token::Integer(b"0")]);
    }

    #[test]
    fn test_lists() {
        expect(b"l4:spam4:eggse",
               &[::Token::ListStart,
                 ::Token::ByteString(b"spam"),
                 ::Token::ByteString(b"eggs"),
                 ::Token::End]);
    }

    #[test]
    fn test_dict() {
        expect(b"d3:cow3:moo4:spam4:eggse",
               &[::Token::DictStart,
                 ::Token::ByteString(b"cow"),
                 ::Token::ByteString(b"moo"),
                 ::Token::ByteString(b"spam"),
                 ::Token::ByteString(b"eggs"),
                 ::Token::End]);
        expect(b"d4:spaml1:a1:bee",
               &[::Token::DictStart,
                 ::Token::ByteString(b"spam"),
                 ::Token::ListStart,
                 ::Token::ByteString(b"a"),
                 ::Token::ByteString(b"b"),
                 ::Token::End,
                 ::Token::End]);
    }

    #[test]
    fn test_only_one() {
        expect(b"4:spam4:eggs", &[::Token::ByteString(b"spam")]);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[macro_use]
extern crate lazy_static;

extern crate mal;
extern crate regex;

mod input;
mod series;

use std::path::Path;
use failure::{Error, ResultExt};
use mal::MAL;
use series::Series;

fn run() -> Result<(), Error> {
    // Temporary
    let args = std::env::args().collect::<Vec<String>>();

    let series = match Series::from_path(Path::new(&args[1])) {
        Ok(s) => s,
        Err(err) => {
            eprintln!("{}", err);
            panic!("{:?}", err);
        }
    };

    let mal = MAL::new(args[2].clone(), args[3].clone());
    let selected = find_and_select_series(&mal, &series.name)?;

    let anime_list = mal.get_anime_list().context("anime list retrieval failed")?;

    if let Some(list_status) = anime_list.iter().find(|a| a.info.id == selected.id) {
        println!("found anime on anime list:\n{:?}", list_status);
    } else {
        println!("anime not found on anime list");
    }

    Ok(())
}

fn main() {
    match run() {
        Ok(_) => (),
        Err(e) => {
            let mut fail: &failure::Fail = e.cause();
            eprintln!("fatal error: {}", fail);

            while let Some(cause) = fail.cause() {
                eprintln!("cause: {}", cause);
                fail = cause;
            }

            eprintln!("{}", e.backtrace());
        }
    }
}

fn find_and_select_series(mal: &MAL, name: &str) -> Result<mal::SeriesInfo, Error> {
    let mut series = mal.search(name).context("MAL search failed")?;

    if series.len() == 0 {
        return Err(format_err!("no anime named [{}] found", name));
    } else if series.len() > 1 {
        println!("found multiple anime named [{}] on MAL", name);
        println!("input the number corrosponding with the intended anime:\n");

        for (i, s) in series.iter().enumerate() {
            println!("{} [{}]", 1 + i, s.title);
        }

        let idx = input::read_usize_range(1, series.len())? - 1;
        Ok(series.swap_remove(idx))
    } else {
        Ok(series.swap_remove(0))
    }
}
<commit_msg>Remove redundant error checking<commit_after>#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;
#[macro_use]
extern crate lazy_static;

extern crate mal;
extern crate regex;

mod input;
mod series;

use std::path::Path;
use failure::{Error, ResultExt};
use mal::MAL;
use series::Series;

fn run() -> Result<(), Error> {
    // Temporary
    let args = std::env::args().collect::<Vec<String>>();

    let series = Series::from_path(Path::new(&args[1]))?;

    let mal = MAL::new(args[2].clone(), args[3].clone());
    let selected = find_and_select_series(&mal, &series.name)?;

    let anime_list = mal.get_anime_list().context("anime list retrieval failed")?;

    if let Some(list_status) = anime_list.iter().find(|a| a.info.id == selected.id) {
        println!("found anime on anime list:\n{:?}", list_status);
    } else {
        println!("anime not found on anime list");
    }

    Ok(())
}

fn main() {
    match run() {
        Ok(_) => (),
        Err(e) => {
            let mut fail: &failure::Fail = e.cause();
            eprintln!("fatal error: {}", fail);

            while let Some(cause) = fail.cause() {
                eprintln!("cause: {}", cause);
                fail = cause;
            }

            eprintln!("{}", e.backtrace());
        }
    }
}

fn find_and_select_series(mal: &MAL, name: &str) -> Result<mal::SeriesInfo, Error> {
    let mut series = mal.search(name).context("MAL search failed")?;

    if series.len() == 0 {
        return Err(format_err!("no anime named [{}] found", name));
    } else if series.len() > 1 {
        println!("found multiple anime named [{}] on MAL", name);
        println!("input the number corrosponding with the intended anime:\n");

        for (i, s) in series.iter().enumerate() {
            println!("{} [{}]", 1 + i, s.title);
        }

        let idx = input::read_usize_range(1, series.len())? - 1;
        Ok(series.swap_remove(idx))
    } else {
        Ok(series.swap_remove(0))
    }
}
<|endoftext|>


<commit_before>extern crate document;

use std::cmp::min;
use std::io::File;
use std::io::BufferedWriter;
use std::io::stdio::stdout_raw;

use document::parser::Parser;

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

#[allow(dead_code)]
fn main() {
    let mut args = std::os::args();

    let filename = args.remove(1);
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    };

    let mut out = BufferedWriter::new(stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}
<commit_msg>Allow processing input from stdin<commit_after>extern crate document;

use std::cmp::min;
use std::io::File;
use std::io::BufferedWriter;
use std::io::stdio;

use document::parser::Parser;

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn process_input<R>(input: R)
    where R: Reader
{
    let mut input = input;
    let data = match input.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    };

    let mut out = BufferedWriter::new(stdio::stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}

#[allow(dead_code)]
fn main() {
    let mut args = std::os::args();

    let filename = args.remove(1);

    if filename == "-" {
        process_input(stdio::stdin_raw());
    } else {
        process_input(File::open(&Path::new(filename)))
    }
}
<|endoftext|>


<commit_before>//Implements http://rosettacode.org/wiki/9_billion_names_of_God_the_integer

extern crate num;

use num::bigint::BigUint;
use std::from_str::FromStr;
use std::string::String;
use std::cmp::min;

 fn cumu<'a>(num: uint, cache: &'a mut Vec<Vec<BigUint>>) -> &'a Vec<BigUint> {

    let len = cache.len();

    for l in range(len, num+1)
    {
	    let initial_value:BigUint = FromStr::from_str("0").unwrap();
	    let mut r: Vec<BigUint> = vec!(initial_value);

	    for x in range(1, l+1)
	    {
		 let y = r.get(x -1).clone();
		 let z = cache.get(l-x).get(min(x, l-x)).clone();
		 let w = y+z;

		 r.push(w)

	    }

	    cache.push(r);

    }

    cache.get(num)
}

// Returns a line

fn row(num: uint,  cache: &mut Vec<Vec<BigUint>>) -> String {

	let r = cumu(num,cache);
	let mut returned_string = String::new();
	for i in range(0,num)
	{
		let i = *r.get(i+1) - *r.get (i);
		let z = i.to_str();
		let y = z.as_slice();
		returned_string.push_str(y);
		returned_string.push_str(", ");
	}
	returned_string

}

#[cfg(not(test))]
fn main()
{

	    let mut cache: Vec<Vec<BigUint>> = Vec::new();

	    let initial_value:BigUint = FromStr::from_str("1").unwrap();

	    let initial_vector : Vec<BigUint> = vec!(initial_value);
	    cache.push(initial_vector);

	    println!("rows");
	    for n in range(1, 11)
	    {
			let x = n as uint;
			println!("{}: {}", n, row(x,&mut cache));
	    }

	    println!("sums");

	    let x: Vec<uint> = vec!(23, 123, 1234, 12345);
	    for y in x.iter()
	    {
			let z = cumu(*y,&mut cache);
			let w = z.last();
			println!("{}: {}", y, w.unwrap());

	   }

}

#[test]
fn test_cumu()
{

	    let mut cache: Vec<Vec<BigUint>> = Vec::new();

	    let initial_value:BigUint = FromStr::from_str("1").unwrap();

	    let initial_vector : Vec<BigUint> = vec!(initial_value);
	    cache.push(initial_vector);

	    let a: Vec<uint> = vec!(23, 123, 1234);
	    let b: Vec<BigUint> = vec!(FromStr::from_str("1255").unwrap(), FromStr::from_str("2552338241").unwrap(), FromStr::from_str("156978797223733228787865722354959930").unwrap());
	    let mut n=0;
	    for y in a.iter()
	    {
			let z = cumu(*y,&mut cache);
			let w = z.last().unwrap();
			assert!(w == b.get(n));
			n= n+1;

	   }
}

#[test]
fn test_row()
{

	    let mut cache: Vec<Vec<BigUint>> = Vec::new();

	    let initial_value:BigUint = FromStr::from_str("1").unwrap();

	    let initial_vector : Vec<BigUint> = vec!(initial_value);
	    cache.push(initial_vector);

	    let a: String = FromStr::from_str("1, 2, 1, 1, ").unwrap();

		let x = 4;
			assert!(a == row(x,&mut cache));

}

<commit_msg>fix formatting and spacing<commit_after>//Implements http://rosettacode.org/wiki/9_billion_names_of_God_the_integer

extern crate num;

use num::bigint::BigUint;
use std::from_str::FromStr;
use std::string::String;
use std::cmp::min;

fn cumu<'a>(num: uint, cache: &'a mut Vec<Vec<BigUint>>) -> &'a Vec<BigUint> {
    let len = cache.len();
    for l in range(len, num+1) {
	let initial_value:BigUint = FromStr::from_str("0").unwrap();
	let mut r: Vec<BigUint> = vec!(initial_value);

	for x in range(1, l+1) {
	    let y = r.get(x -1).clone();
	    let z = cache.get(l-x).get(min(x, l-x)).clone();
	    let w = y+z;

	    r.push(w)
	}
	cache.push(r);
    }
    cache.get(num)
}

// Returns a line
fn row(num: uint,  cache: &mut Vec<Vec<BigUint>>) -> String {
    let r = cumu(num,cache);
    let mut returned_string = String::new();
    for i in range(0,num) {
	let i = *r.get(i+1) - *r.get (i);
	let z = i.to_str();
	let y = z.as_slice();
	returned_string.push_str(y);
	returned_string.push_str(", ");
    }
    returned_string
}

#[cfg(not(test))]
fn main() {
    let mut cache: Vec<Vec<BigUint>> = Vec::new();
    let initial_value:BigUint = FromStr::from_str("1").unwrap();
    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    println!("rows");
    for n in range(1, 11) {
	let x = n as uint;
	println!("{}: {}", n, row(x,&mut cache));
    }

    println!("sums");

    let x: Vec<uint> = vec!(23, 123, 1234, 12345);
    for y in x.iter() {
	let z = cumu(*y,&mut cache);
	let w = z.last();
	println!("{}: {}", y, w.unwrap());
    }
}

#[test]
fn test_cumu() {
    let mut cache: Vec<Vec<BigUint>> = Vec::new();

    let initial_value:BigUint = FromStr::from_str("1").unwrap();

    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    let a: Vec<uint> = vec!(23, 123, 1234);
    let b: Vec<BigUint> = vec!(
        FromStr::from_str("1255").unwrap(),
        FromStr::from_str("2552338241").unwrap(),
        FromStr::from_str("156978797223733228787865722354959930").unwrap());

    let mut n=0;
    for y in a.iter() {
	let z = cumu(*y,&mut cache);
	let w = z.last().unwrap();
	assert!(w == b.get(n));
	n= n+1;
    }
}

#[test]
fn test_row() {

    let mut cache: Vec<Vec<BigUint>> = Vec::new();

    let initial_value:BigUint = FromStr::from_str("1").unwrap();

    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    let a: String = FromStr::from_str("1, 2, 1, 1, ").unwrap();

    let x = 4;
    assert!(a == row(x,&mut cache));

}
<|endoftext|>


<commit_before>use na::RealField;

use crate::material::{LocalMaterialProperties, Material, MaterialCombineMode, MaterialContext};

use crate::math::Vector;

/// Description of the state of surface of a solid.
///
/// Strictly speaking, the coefficient provided here only exist
/// when considering a pair of touching surfaces. In practice, nphysics
/// will average the coefficient of the two surfaces in contact in order
/// to deduce the restitution/friction coefficient.
#[derive(Copy, Clone, Debug)]
pub struct BasicMaterial<N: RealField> {
    /// The ID of this material for automatic lookup.
    pub id: Option<u32>,
    /// Restitution coefficient of the surface.
    pub restitution: N,
    /// Friction coefficient of the surface.
    pub friction: N,
    /// The fictitious velocity at the surface of this material.
    pub surface_velocity: Option<Vector<N>>,
    /// The way restitution coefficients are combined if no match
    /// was found in the material lookup tables.
    pub restitution_combine_mode: MaterialCombineMode,
    /// The way friction coefficients are combined if no match
    /// was found in the material lookup tables.
    pub friction_combine_mode: MaterialCombineMode,
}

impl<N: RealField> BasicMaterial<N> {
    /// Initialize a material with the specified restitution and friction coefficients.
    pub fn new(restitution: N, friction: N) -> Self {
        BasicMaterial {
            id: None,
            restitution,
            friction,
            surface_velocity: None,
            restitution_combine_mode: MaterialCombineMode::Average,
            friction_combine_mode: MaterialCombineMode::Average,
        }
    }
}

impl<N: RealField> Material<N> for BasicMaterial<N> {
    fn local_properties(&self, context: MaterialContext<N>) -> LocalMaterialProperties<N> {
        LocalMaterialProperties {
            id: self.id,
            restitution: (self.restitution, self.restitution_combine_mode),
            friction: (self.friction, self.friction_combine_mode),
            surface_velocity: self
                .surface_velocity
                .map(|v| context.position * v)
                .unwrap_or(Vector::zeros()),
        }
    }
}

impl<N: RealField> Default for BasicMaterial<N> {
    fn default() -> Self {
        BasicMaterial::new(N::zero(), na::convert(0.5))
    }
}
<commit_msg>better unwrap<commit_after>use na::RealField;

use crate::material::{LocalMaterialProperties, Material, MaterialCombineMode, MaterialContext};

use crate::math::Vector;

/// Description of the state of surface of a solid.
///
/// Strictly speaking, the coefficient provided here only exist
/// when considering a pair of touching surfaces. In practice, nphysics
/// will average the coefficient of the two surfaces in contact in order
/// to deduce the restitution/friction coefficient.
#[derive(Copy, Clone, Debug)]
pub struct BasicMaterial<N: RealField> {
    /// The ID of this material for automatic lookup.
    pub id: Option<u32>,
    /// Restitution coefficient of the surface.
    pub restitution: N,
    /// Friction coefficient of the surface.
    pub friction: N,
    /// The fictitious velocity at the surface of this material.
    pub surface_velocity: Option<Vector<N>>,
    /// The way restitution coefficients are combined if no match
    /// was found in the material lookup tables.
    pub restitution_combine_mode: MaterialCombineMode,
    /// The way friction coefficients are combined if no match
    /// was found in the material lookup tables.
    pub friction_combine_mode: MaterialCombineMode,
}

impl<N: RealField> BasicMaterial<N> {
    /// Initialize a material with the specified restitution and friction coefficients.
    pub fn new(restitution: N, friction: N) -> Self {
        BasicMaterial {
            id: None,
            restitution,
            friction,
            surface_velocity: None,
            restitution_combine_mode: MaterialCombineMode::Average,
            friction_combine_mode: MaterialCombineMode::Average,
        }
    }
}

impl<N: RealField> Material<N> for BasicMaterial<N> {
    fn local_properties(&self, context: MaterialContext<N>) -> LocalMaterialProperties<N> {
        LocalMaterialProperties {
            id: self.id,
            restitution: (self.restitution, self.restitution_combine_mode),
            friction: (self.friction, self.friction_combine_mode),
            surface_velocity: self
                .surface_velocity
                .map(|v| context.position * v)
                .unwrap_or_else(Vector::zeros),
        }
    }
}

impl<N: RealField> Default for BasicMaterial<N> {
    fn default() -> Self {
        BasicMaterial::new(N::zero(), na::convert(0.5))
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

use support::{database, project};

#[cfg(not(windows))]
const NEW_LINE: &'static str = "\n";

#[cfg(windows)]
const NEW_LINE: &'static str = "\r\n";

#[test]
fn run_infer_schema_without_docs() {
    test_print_schema("print_schema_simple_without_docs", vec![]);
}

#[test]
fn run_infer_schema() {
    test_print_schema("print_schema_simple", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_include() {
    test_print_schema(
        "print_schema_only_tables",
        vec!["--with-docs", "-w", "users1"],
    );
}

#[test]
fn run_infer_schema_exclude() {
    test_print_schema(
        "print_schema_except_tables",
        vec!["--with-docs", "-b", "users1"],
    );
}

#[test]
fn run_infer_schema_order() {
    test_print_schema("print_schema_order", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_compound_primary_key() {
    test_print_schema("print_schema_compound_primary_key", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name() {
    test_print_schema(
        "print_schema_specifying_schema_name",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name_with_foreign_keys() {
    test_print_schema(
        "print_schema_specifying_schema_name_with_foreign_keys",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_with_foreign_keys() {
    test_print_schema("print_schema_with_foreign_keys", vec!["--with-docs"]);
}

#[test]
fn print_schema_column_renaming() {
    test_print_schema("print_schema_column_renaming", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "mysql")]
fn print_schema_unsigned() {
    test_print_schema("print_schema_unsigned", vec!["--with-docs"]);
}

#[test]
fn print_schema_patch_file() {
    let path_to_patch_file = backend_file_path("print_schema_patch_file", "schema.patch");
    let path = path_to_patch_file.display().to_string();
    test_print_schema("print_schema_patch_file", vec!["--patch-file", &path]);
}

#[test]
fn print_schema_custom_types() {
    test_print_schema(
        "print_schema_custom_types",
        vec!["--import-types", "foo::*", "--import-types", "bar::*"],
    );
}

#[cfg(feature = "sqlite")]
const BACKEND: &str = "sqlite";
#[cfg(feature = "postgres")]
const BACKEND: &str = "postgres";
#[cfg(feature = "mysql")]
const BACKEND: &str = "mysql";

fn backend_file_path(test_name: &str, file: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name)
        .join(BACKEND)
        .join(file)
}

fn test_print_schema(test_name: &str, args: Vec<&str>) {
    let test_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name);
    let p = project(test_name).build();
    let db = database(&p.database_url());

    p.command("setup").run();

    let schema = read_file(&backend_file_path(test_name, "schema.sql"));
    db.execute(&schema);

    let result = p.command("print-schema").args(args).run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    let expected = read_file(&backend_file_path(test_name, "expected.rs"));

    assert_diff!(&expected, result.stdout(), NEW_LINE, 0);

    test_print_schema_config(test_name, &test_path, schema, expected);
}

fn test_print_schema_config(test_name: &str, test_path: &Path, schema: String, expected: String) {
    let config = read_file(&test_path.join("diesel.toml"));
    let mut p = project(&format!("{}_config", test_name)).file("diesel.toml", &config);

    let patch_file = backend_file_path(test_name, "schema.patch");
    if patch_file.exists() {
        let patch_contents = read_file(&patch_file);
        p = p.file("schema.patch", &patch_contents);
    }

    let p = p.build();

    p.command("setup").run();
    p.create_migration("12345_create_schema", &schema, "");

    let result = p.command("migration").arg("run").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    let schema = p.file_contents("src/schema.rs");
    assert_diff!(&expected, &schema, NEW_LINE, 0);

    let result = p.command("print-schema").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    assert_diff!(&expected, result.stdout(), NEW_LINE, 0);
}

fn read_file(path: &Path) -> String {
    let mut file = File::open(path).expect(&format!("Could not open {}", path.display()));
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();
    string
}
<commit_msg>Explicitly unify line endings in tests<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};

use support::{database, project};

#[test]
fn run_infer_schema_without_docs() {
    test_print_schema("print_schema_simple_without_docs", vec![]);
}

#[test]
fn run_infer_schema() {
    test_print_schema("print_schema_simple", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_include() {
    test_print_schema(
        "print_schema_only_tables",
        vec!["--with-docs", "-w", "users1"],
    );
}

#[test]
fn run_infer_schema_exclude() {
    test_print_schema(
        "print_schema_except_tables",
        vec!["--with-docs", "-b", "users1"],
    );
}

#[test]
fn run_infer_schema_order() {
    test_print_schema("print_schema_order", vec!["--with-docs"]);
}

#[test]
fn run_infer_schema_compound_primary_key() {
    test_print_schema("print_schema_compound_primary_key", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name() {
    test_print_schema(
        "print_schema_specifying_schema_name",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_specifying_schema_name_with_foreign_keys() {
    test_print_schema(
        "print_schema_specifying_schema_name_with_foreign_keys",
        vec!["--with-docs", "--schema", "custom_schema"],
    )
}

#[test]
#[cfg(feature = "postgres")]
fn print_schema_with_foreign_keys() {
    test_print_schema("print_schema_with_foreign_keys", vec!["--with-docs"]);
}

#[test]
fn print_schema_column_renaming() {
    test_print_schema("print_schema_column_renaming", vec!["--with-docs"]);
}

#[test]
#[cfg(feature = "mysql")]
fn print_schema_unsigned() {
    test_print_schema("print_schema_unsigned", vec!["--with-docs"]);
}

#[test]
fn print_schema_patch_file() {
    let path_to_patch_file = backend_file_path("print_schema_patch_file", "schema.patch");
    let path = path_to_patch_file.display().to_string();
    test_print_schema("print_schema_patch_file", vec!["--patch-file", &path]);
}

#[test]
fn print_schema_custom_types() {
    test_print_schema(
        "print_schema_custom_types",
        vec!["--import-types", "foo::*", "--import-types", "bar::*"],
    );
}

#[cfg(feature = "sqlite")]
const BACKEND: &str = "sqlite";
#[cfg(feature = "postgres")]
const BACKEND: &str = "postgres";
#[cfg(feature = "mysql")]
const BACKEND: &str = "mysql";

fn backend_file_path(test_name: &str, file: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name)
        .join(BACKEND)
        .join(file)
}

fn test_print_schema(test_name: &str, args: Vec<&str>) {
    let test_path = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests")
        .join("print_schema")
        .join(test_name);
    let p = project(test_name).build();
    let db = database(&p.database_url());

    p.command("setup").run();

    let schema = read_file(&backend_file_path(test_name, "schema.sql"));
    db.execute(&schema);

    let result = p.command("print-schema").args(args).run();

    assert!(result.is_success(), "Result was unsuccessful {:?}", result);
    let expected = read_file(&backend_file_path(test_name, "expected.rs")).replace("\r\n", "\n");

    let result = result.stdout().replace("\r\n", "\n");

    assert_diff!(&expected, &result, "\n", 0);

    test_print_schema_config(test_name, &test_path, schema, expected);
}

fn test_print_schema_config(test_name: &str, test_path: &Path, schema: String, expected: String) {
    let config = read_file(&test_path.join("diesel.toml"));
    let mut p = project(&format!("{}_config", test_name)).file("diesel.toml", &config);

    let patch_file = backend_file_path(test_name, "schema.patch");
    if patch_file.exists() {
        let patch_contents = read_file(&patch_file);
        p = p.file("schema.patch", &patch_contents);
    }

    let p = p.build();

    p.command("setup").run();
    p.create_migration("12345_create_schema", &schema, "");

    let result = p.command("migration").arg("run").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    let schema = p.file_contents("src/schema.rs").replace("\r\n", "\n");
    assert_diff!(&expected, &schema, "\n", 0);

    let result = p.command("print-schema").run();
    assert!(result.is_success(), "Result was unsuccessful {:?}", result);

    let result = result.stdout().replace("\r\n", "\n");
    assert_diff!(&expected, &result, "\n", 0);
}

fn read_file(path: &Path) -> String {
    let mut file = File::open(path).expect(&format!("Could not open {}", path.display()));
    let mut string = String::new();
    file.read_to_string(&mut string).unwrap();
    string
}
<|endoftext|>


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

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/// Coerce an immutable reference to be mutable.
#[inline]
#[deprecated="casting &T to &mut T is undefined behaviour: use Cell<T>, RefCell<T> or Unsafe<T>"]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::transmute;
    use raw;
    use realstd::str::StrAllocating;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(box [76u8], transmute("L".to_owned()));
        }
    }
}
<commit_msg>std: Change names of transmute's type parameters<commit_after>// Copyright 2012-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.

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<T, U>(thing: T) -> U {
    intrinsics::transmute(thing)
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/// Coerce an immutable reference to be mutable.
#[inline]
#[deprecated="casting &T to &mut T is undefined behaviour: use Cell<T>, RefCell<T> or Unsafe<T>"]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::transmute;
    use raw;
    use realstd::str::StrAllocating;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(box [76u8], transmute("L".to_owned()));
        }
    }
}
<|endoftext|>


<commit_before>//! Random number generation

export Rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    #[legacy_exports];
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        move s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        util::unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        move r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        move m
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {
    #[legacy_exports];

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libcore: De-export dvec, rand, run, and sys<commit_after>//! Random number generation

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    #[legacy_exports];
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
pub trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
pub type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        move s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:Copy>(values: &[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:Copy>(values: &[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: Copy>(v : &[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:Copy>(v: &[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        util::unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:Copy>(v: &[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        move r
    }

    /// Shuffle a vec
    fn shuffle<T:Copy>(values: &[T]) -> ~[T] {
        let mut m = vec::from_slice(values);
        self.shuffle_mut(m);
        move m
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(values: &[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    c: *rctx,
    drop { rustrt::rand_free(self.c); }
}

fn RandRes(c: *rctx) -> RandRes {
    RandRes {
        c: c
    }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
pub fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
pub fn Rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
pub fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

pub fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

pub fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
pub mod tests {
    #[test]
    pub fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    pub fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    pub fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    pub fn gen_int_range() {
        let r = rand::Rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    pub fn gen_int_from_fail() {
        rand::Rng().gen_int_range(5, -2);
    }

    #[test]
    pub fn gen_uint_range() {
        let r = rand::Rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    pub fn gen_uint_range_fail() {
        rand::Rng().gen_uint_range(5u, 2u);
    }

    #[test]
    pub fn gen_float() {
        let r = rand::Rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    pub fn gen_weighted_bool() {
        let r = rand::Rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    pub fn gen_str() {
        let r = rand::Rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    pub fn gen_bytes() {
        let r = rand::Rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    pub fn choose() {
        let r = rand::Rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    pub fn choose_option() {
        let r = rand::Rng();
        let x: Option<int> = r.choose_option([]);
        assert x.is_none();
        assert r.choose_option([1, 1, 1]) == Some(1);
    }

    #[test]
    pub fn choose_weighted() {
        let r = rand::Rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    pub fn choose_weighted_option() {
        let r = rand::Rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        let v: Option<int> = r.choose_weighted_option([]);
        assert v.is_none();
    }

    #[test]
    pub fn weighted_vec() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    pub fn shuffle() {
        let r = rand::Rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


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

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn(&[~str])),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static NUM_OF_COMMANDS: uint = 7;

// FIXME(#7617): should just be &'static [Command<'static>]
// but mac os doesn't seem to like that and tries to loop
// past the end of COMMANDS in usage thus passing garbage
// to str::repeat and eventually malloc and crashing.
static COMMANDS: [Command<'static>, .. NUM_OF_COMMANDS] = [
    Command{
        cmd: "build",
        action: CallMain("rustc", rustc::main_args),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command{
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command{
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~\"\n\nUsage:\trust test <filename>"
        )
    },
    Command{
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main_args),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command{
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main_args),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command{
        cmd: "sketch",
        action: CallMain("rusti", rusti::main_args),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command{
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find |command| {
        command.cmd == command_string
    }.map_move(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename] => {
            let p = Path(*filename);
            let test_exec = p.filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main_args);
            let exit_code = run::process_status(~"./" + test_exec, []);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let p = Path(*filename);
            let exec = p.filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main_args);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    f(osargs);
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for command in COMMANDS.iter() {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    #[fixed_stack_segment]; #[inline(never)];

    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for command in r.iter() {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<commit_msg>librust: Remove unnecessary workaround. Closes #7617<commit_after>// Copyright 2013 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.

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn(&[~str])),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static COMMANDS: &'static [Command<'static>] = &'static [
    Command {
        cmd: "build",
        action: CallMain("rustc", rustc::main_args),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command {
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command {
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~\"\n\nUsage:\trust test <filename>"
        )
    },
    Command {
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main_args),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command {
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main_args),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command {
        cmd: "sketch",
        action: CallMain("rusti", rusti::main_args),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command {
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find |command| {
        command.cmd == command_string
    }.map_move(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename] => {
            let p = Path(*filename);
            let test_exec = p.filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main_args);
            let exit_code = run::process_status(~"./" + test_exec, []);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let p = Path(*filename);
            let exec = p.filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main_args);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn(&[~str])) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    f(osargs);
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for command in COMMANDS.iter() {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    #[fixed_stack_segment]; #[inline(never)];

    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for command in r.iter() {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<|endoftext|>