<commit_before>use std::io::{Write, Result as IoResult};
use {Color, Style};

/// Controlling terminals.
pub trait TermControl {

    /// Print the CSI (control sequence introducer) followed by a byte string.
    fn csi(&mut self, b: &[u8]) -> IoResult<usize>;
    /// Print OSC (operating system command) followed by a byte string.
    fn osc(&mut self, b: &[u8]) -> IoResult<usize>;
    /// Print OSC (device control string) followed by a byte string.
    fn dsc(&mut self, b: &[u8]) -> IoResult<usize>;

    /// Clear the entire screen.
    fn clear(&mut self) -> IoResult<usize> {
        self.csi(b"2J")
    }
    /// Clear the current line.
    fn clear_line(&mut self) -> IoResult<usize> {
        self.csi(b"2K")
    }
    /// Show the cursor.
    fn show_cursor(&mut self) -> IoResult<usize> {
        self.csi(b"?25h")
    }
    /// Hide the cursor.
    fn hide_cursor(&mut self) -> IoResult<usize> {
        self.csi(b"?25l")
    }
    /// Reset the rendition mode.
    fn reset(&mut self) -> IoResult<usize> {
        self.csi(b"m")
    }
    /// Go to a given position.
    fn goto(&mut self, x: u16, y: u16) -> IoResult<usize> {
        self.csi(&[
            b'0' + (x / 10000) as u8,
            b'0' + (x / 1000) as u8 % 10,
            b'0' + (x / 100) as u8 % 10,
            b'0' + (x / 10) as u8 % 10,
            b'0' + x as u8 % 10,
            b';',
            b'0' + (y / 10000) as u8,
            b'0' + (y / 1000) as u8 % 10,
            b'0' + (y / 100) as u8 % 10,
            b'0' + (y / 10) as u8 % 10,
            b'0' + y as u8 % 10,
            b'H',
        ])
    }
    /// Set graphic rendition.
    fn rendition(&mut self, r: u8) -> IoResult<usize> {
        self.csi(&[
            b'0' + r / 100,
            b'0' + r / 10 % 10,
            b'0' + r % 10,
            b'm',
        ])
    }
    /// Set foreground color
    fn color(&mut self, color: Color) -> IoResult<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'3',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set background color
    fn bg_color(&mut self, color: Color) -> IoResult<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'4',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set rendition mode (SGR).
    fn style(&mut self, mode: Style) -> IoResult<usize> {
        self.rendition(mode as u8)
    }
}

impl<W: Write> TermControl for W {
    fn csi(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1B[").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
    fn osc(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1B]").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
    fn dsc(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1BP").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
}
<commit_msg>Make the position 0-based<commit_after>use std::io::{Write, Result as IoResult};
use {Color, Style};

/// Controlling terminals.
pub trait TermControl {

    /// Print the CSI (control sequence introducer) followed by a byte string.
    fn csi(&mut self, b: &[u8]) -> IoResult<usize>;
    /// Print OSC (operating system command) followed by a byte string.
    fn osc(&mut self, b: &[u8]) -> IoResult<usize>;
    /// Print OSC (device control string) followed by a byte string.
    fn dsc(&mut self, b: &[u8]) -> IoResult<usize>;

    /// Clear the entire screen.
    fn clear(&mut self) -> IoResult<usize> {
        self.csi(b"2J")
    }
    /// Clear the current line.
    fn clear_line(&mut self) -> IoResult<usize> {
        self.csi(b"2K")
    }
    /// Show the cursor.
    fn show_cursor(&mut self) -> IoResult<usize> {
        self.csi(b"?25h")
    }
    /// Hide the cursor.
    fn hide_cursor(&mut self) -> IoResult<usize> {
        self.csi(b"?25l")
    }
    /// Reset the rendition mode.
    fn reset(&mut self) -> IoResult<usize> {
        self.csi(b"m")
    }
    /// Go to a given position.
    ///
    /// The position is 0-based.
    fn goto(&mut self, mut x: u16, mut y: u16) -> IoResult<usize> {
        x += 1;
        y += 1;

        self.csi(&[
            b'0' + (y / 10000) as u8,
            b'0' + (y / 1000) as u8 % 10,
            b'0' + (y / 100) as u8 % 10,
            b'0' + (y / 10) as u8 % 10,
            b'0' + y as u8 % 10,
            b';',
            b'0' + (x / 10000) as u8,
            b'0' + (x / 1000) as u8 % 10,
            b'0' + (x / 100) as u8 % 10,
            b'0' + (x / 10) as u8 % 10,
            b'0' + x as u8 % 10,
            b'H',
        ])
    }
    /// Set graphic rendition.
    fn rendition(&mut self, r: u8) -> IoResult<usize> {
        self.csi(&[
            b'0' + r / 100,
            b'0' + r / 10 % 10,
            b'0' + r % 10,
            b'm',
        ])
    }
    /// Set foreground color
    fn color(&mut self, color: Color) -> IoResult<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'3',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set background color
    fn bg_color(&mut self, color: Color) -> IoResult<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'4',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set rendition mode (SGR).
    fn style(&mut self, mode: Style) -> IoResult<usize> {
        self.rendition(mode as u8)
    }
}

impl<W: Write> TermControl for W {
    fn csi(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1B[").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
    fn osc(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1B]").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
    fn dsc(&mut self, b: &[u8]) -> IoResult<usize> {
        self.write(b"\x1BP").and_then(|x| {
            self.write(b).map(|y| x + y)
        })
    }
}
<|endoftext|>


<commit_before>use std::env;

fn main () {
    if let Some(lib_dir) = env::var("SODIUM_LIB_DIR").ok() {
    	println!("cargo:rustc-flags=-L native={}", lib_dir);
    }

    let mode = if env::var_os("SODIUM_STATIC").is_some() {
    	"static"
    } else {
    	"dylib"
    };

    println!("cargo:rustc-flags=-l {0}=sodium", mode);
}
<commit_msg>Cleanup of patch from @markuskobler<commit_after>use std::env;

fn main () {
    if let Ok(lib_dir) = env::var("SODIUM_LIB_DIR") {
    	println!("cargo:rustc-flags=-L native={}", lib_dir);
    }

    let mode = match env::var_os("SODIUM_STATIC") {
        Some(_) => "static",
        None => "dylib"
    };

    println!("cargo:rustc-flags=-l {0}=sodium", mode);
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utils for forming gzchunked streams.

use std::vec::Vec;
use std::mem;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::default::Default;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use flate2::{write::GzEncoder, read::GzDecoder};

/// Size of a gzchunked block.
const BLOCK_SIZE: usize = 10 << 20;

/// A wrapper type for gzip compression level.
pub struct Compression(flate2::Compression);

/// A gzchunked streaming encoder.
pub struct Encoder {
    encoder: GzEncoder<Vec<u8>>,
    compression: Compression,
}

/// A gzchunked streaming decoder.
pub struct Decoder {
    queue: VecDeque<Vec<u8>>,
}

/// A type for defining gzip compression level for gzchunked.
impl Compression {
    pub fn new(level: u32) -> Compression {
        Compression(flate2::Compression::new(level))
    }
}

impl Default for Compression {
    fn default() -> Compression {
        Compression(flate2::Compression::new(5))
    }
}

impl Encoder {
    /// Creates a new encoder with specified gzip compression level.
    pub fn new(compression: Compression) -> Encoder {
        Encoder {
            encoder: GzEncoder::new(Vec::new(), compression.0),
            compression,
        }
    }

    /// Writes next data chunk into the stream.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        self.encoder.write_u64::<BigEndian>(buf.len() as u64)?;
        self.encoder.write_all(buf)?;
        Ok(())
    }

    /// Attempts to retrieve next gzipped block.
    /// Returns `Ok(None)` if there's not enough data for a whole block.
    pub fn try_next_chunk(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        self.encoder.flush()?;
        if self.encoder.get_ref().len() < BLOCK_SIZE {
            return Ok(None)
        }

        Ok(Some(self.next_chunk()?))
    }

    /// Retrieves next gzipped block without checking its size.
    pub fn next_chunk(&mut self) -> std::io::Result<Vec<u8>> {
        self.encoder.flush()?;
        let new_encoder = GzEncoder::new(Vec::new(), self.compression.0);
        let old_encoder = mem::replace(&mut self.encoder, new_encoder);
        let encoded_data = old_encoder.finish()?;

        Ok(encoded_data)
    }
}

impl Decoder {
    /// Creates a new decoder.
    pub fn new() -> Decoder {
        Decoder {
            queue: VecDeque::new()
        }
    }

    /// Decodes next gzchunked block and puts all results into the internal queue.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        let mut decoder = GzDecoder::new(buf);
        let mut chunked_data_vec: Vec<u8> = Vec::new();
        decoder.read_to_end(&mut chunked_data_vec)?;
        let mut chunked_data = chunked_data_vec.as_slice();
        while !chunked_data.is_empty() {
            let length = chunked_data.read_u64::<BigEndian>()?;
            let mut data = vec![0; length as usize];
            chunked_data.read_exact(data.as_mut_slice())?;
            self.queue.push_back(data);
        }
        Ok(())
    }

    /// Attempts to retrieve next data piece from queue.
    /// Returns `None` if the queue is empty.
    pub fn try_next_data(&mut self) -> Option<Vec<u8>> {
        self.queue.pop_front()
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use rand::{Rng, SeedableRng, rngs::StdRng};

    #[test]
    fn test_encode_and_decode_empty() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        let encoded_block = encoder.next_chunk().unwrap();
        // This is because the block should at least contain gzip header.
        assert!(!encoded_block.is_empty());
        decoder.write(encoded_block.as_slice()).unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_all_in_one_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        encoder.write(&[]).unwrap();
        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        encoder.write(&[1]).unwrap();

        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_one_per_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_random() {
        let mut rng = StdRng::seed_from_u64(20200509);
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();
        let mut expected_data: Vec<Vec<u8>> = Vec::new();
        let mut decoded_data: Vec<Vec<u8>> = Vec::new();
        for _ in 0..256 {
            let size = rng.gen_range(128, 256);
            let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
            encoder.write(data.as_slice()).unwrap();
            if let Some(block) = encoder.try_next_chunk().unwrap() {
                decoder.write(block.as_slice()).unwrap();
                while let Some(data) = decoder.try_next_data() {
                    decoded_data.push(data);
                }
            }
            expected_data.push(data);
        }
        let last_block = encoder.next_chunk().unwrap();
        decoder.write(last_block.as_slice()).unwrap();
        while let Some(data) = decoder.try_next_data() {
            decoded_data.push(data);
        }
        assert_eq!(decoded_data, expected_data);
    }

    #[test]
    fn test_encode_and_decode_max_compression() {
        let mut encoder = Encoder::new(Compression::new(9));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_min_compression() {
        let mut encoder = Encoder::new(Compression::new(0));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    // Should panic because the underlying gzip only supports levels from 0 to 9.
    #[test]
    #[should_panic]
    fn test_huge_compression() {
        Encoder::new(Compression::new(100500));
    }
}
<commit_msg>Simplify imports in the gzchunked module.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utils for forming gzchunked streams.

use std::collections::VecDeque;
use std::io::{Read as _, Write as _};

use byteorder::{BigEndian, ReadBytesExt as _, WriteBytesExt as _};

/// Size of a gzchunked block.
const BLOCK_SIZE: usize = 10 << 20;

/// A wrapper type for gzip compression level.
pub struct Compression(flate2::Compression);

/// A gzchunked streaming encoder.
pub struct Encoder {
    encoder: flate2::write::GzEncoder<Vec<u8>>,
    compression: Compression,
}

/// A gzchunked streaming decoder.
pub struct Decoder {
    queue: VecDeque<Vec<u8>>,
}

/// A type for defining gzip compression level for gzchunked.
impl Compression {
    pub fn new(level: u32) -> Compression {
        Compression(flate2::Compression::new(level))
    }
}

impl Default for Compression {
    fn default() -> Compression {
        Compression(flate2::Compression::new(5))
    }
}

impl Encoder {
    /// Creates a new encoder with specified gzip compression level.
    pub fn new(compression: Compression) -> Encoder {
        Encoder {
            encoder: flate2::write::GzEncoder::new(Vec::new(), compression.0),
            compression,
        }
    }

    /// Writes next data chunk into the stream.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        self.encoder.write_u64::<BigEndian>(buf.len() as u64)?;
        self.encoder.write_all(buf)?;
        Ok(())
    }

    /// Attempts to retrieve next gzipped block.
    /// Returns `Ok(None)` if there's not enough data for a whole block.
    pub fn try_next_chunk(&mut self) -> std::io::Result<Option<Vec<u8>>> {
        self.encoder.flush()?;
        if self.encoder.get_ref().len() < BLOCK_SIZE {
            return Ok(None)
        }

        Ok(Some(self.next_chunk()?))
    }

    /// Retrieves next gzipped block without checking its size.
    pub fn next_chunk(&mut self) -> std::io::Result<Vec<u8>> {
        self.encoder.flush()?;
        let new_encoder = flate2::write::GzEncoder::new(Vec::new(), self.compression.0);
        let old_encoder = std::mem::replace(&mut self.encoder, new_encoder);
        let encoded_data = old_encoder.finish()?;

        Ok(encoded_data)
    }
}

impl Decoder {
    /// Creates a new decoder.
    pub fn new() -> Decoder {
        Decoder {
            queue: VecDeque::new()
        }
    }

    /// Decodes next gzchunked block and puts all results into the internal queue.
    pub fn write(&mut self, buf: &[u8]) -> std::io::Result<()> {
        let mut decoder = flate2::read::GzDecoder::new(buf);
        let mut chunked_data_vec: Vec<u8> = Vec::new();
        decoder.read_to_end(&mut chunked_data_vec)?;
        let mut chunked_data = chunked_data_vec.as_slice();
        while !chunked_data.is_empty() {
            let length = chunked_data.read_u64::<BigEndian>()?;
            let mut data = vec![0; length as usize];
            chunked_data.read_exact(data.as_mut_slice())?;
            self.queue.push_back(data);
        }
        Ok(())
    }

    /// Attempts to retrieve next data piece from queue.
    /// Returns `None` if the queue is empty.
    pub fn try_next_data(&mut self) -> Option<Vec<u8>> {
        self.queue.pop_front()
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_encode_and_decode_empty() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        let encoded_block = encoder.next_chunk().unwrap();
        // This is because the block should at least contain gzip header.
        assert!(!encoded_block.is_empty());
        decoder.write(encoded_block.as_slice()).unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_all_in_one_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        encoder.write(&[]).unwrap();
        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        encoder.write(&[1]).unwrap();

        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_one_per_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_random() {
        use rand::{Rng as _, SeedableRng as _};
        let mut rng = rand::rngs::StdRng::seed_from_u64(20200509);

        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();
        let mut expected_data: Vec<Vec<u8>> = Vec::new();
        let mut decoded_data: Vec<Vec<u8>> = Vec::new();
        for _ in 0..256 {
            let size = rng.gen_range(128, 256);
            let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
            encoder.write(data.as_slice()).unwrap();
            if let Some(block) = encoder.try_next_chunk().unwrap() {
                decoder.write(block.as_slice()).unwrap();
                while let Some(data) = decoder.try_next_data() {
                    decoded_data.push(data);
                }
            }
            expected_data.push(data);
        }
        let last_block = encoder.next_chunk().unwrap();
        decoder.write(last_block.as_slice()).unwrap();
        while let Some(data) = decoder.try_next_data() {
            decoded_data.push(data);
        }
        assert_eq!(decoded_data, expected_data);
    }

    #[test]
    fn test_encode_and_decode_max_compression() {
        let mut encoder = Encoder::new(Compression::new(9));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_min_compression() {
        let mut encoder = Encoder::new(Compression::new(0));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    // Should panic because the underlying gzip only supports levels from 0 to 9.
    #[test]
    #[should_panic]
    fn test_huge_compression() {
        Encoder::new(Compression::new(100500));
    }
}
<|endoftext|>


<commit_before>use std::ascii::*;
use cases::lowercase::to_lower_case;

/// Converts a `String` to `snake_case` `String`
///
/// #Examples
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "foo_bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "HTTP Foo bar".to_string();
///     let expected_string: String = "http_foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "Foo bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "Foo Bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "FooBar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "FOO_BAR".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "fooBar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "fooBar3".to_string();
///     let expected_string: String = "foo_bar_3".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
pub fn to_snake_case(non_snake_case_string: String) -> String {
    if non_snake_case_string.contains(' ') || non_snake_case_string.contains('_') ||
       non_snake_case_string.contains('-') {
        to_snake_from_sentence_or_kebab(non_snake_case_string)
    } else {
        to_snake_from_camel_or_class(non_snake_case_string)
    }
}

fn to_snake_from_camel_or_class(non_snake_case_string: String) -> String {
    let mut result: String = "".to_string();
    let mut first_character: bool = true;
    for character in non_snake_case_string.chars() {
        if character == character.to_ascii_uppercase() && !first_character {
            result = format!("{}_{}", result, character.to_ascii_lowercase());
        } else {
            result = format!("{}{}", result, character.to_ascii_lowercase());
            first_character = false;
        }
    }
    result
}

fn to_snake_from_sentence_or_kebab(non_snake_case_string: String) -> String {
    to_lower_case(non_snake_case_string.replace(" ", "_").replace("-", "_"))
}

/// Determines of a `String` is `snake_case`
///
/// #Examples
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "Foo bar string that is really really long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo-bar-string-that-is-really-really-long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "FooBarIsAReallyReallyLongString".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "Foo Bar Is A Really Really Long String".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "FOO_BAR_IS_A_REALLY_REALLY_LONG_STRING".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "fooBarIsAReallyReallyLongString".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar1_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar_1_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
pub fn is_snake_case(test_string: String) -> bool {
    test_string == to_snake_case(test_string.clone())
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;

    #[bench]
    fn bench_snake(b: &mut Bencher) {
        b.iter(|| super::to_snake_case("Foo bar".to_string()));
    }

    #[bench]
    fn bench_is_snake(b: &mut Bencher) {
        b.iter(|| super::is_snake_case("Foo bar".to_string()));
    }

    #[bench]
    fn bench_snake_from_kebab(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_sentence_or_kebab("test-test-test".to_string()));
    }

    #[bench]
    fn bench_snake_from_upper_kebab(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_sentence_or_kebab("TEST-TEST-TEST".to_string()));
    }

    #[bench]
    fn bench_snake_from_snake(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_sentence_or_kebab("test_case".to_string()));
    }

    #[bench]
    fn bench_snake_from_sentence(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_sentence_or_kebab("The quick brown fox".to_string()));
    }

    #[bench]
    fn bench_snake_from_camel(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_camel_or_class("testCase".to_string()));
    }

    #[bench]
    fn bench_snake_from_class(b: &mut Bencher) {
        b.iter(|| super::to_snake_from_camel_or_class("TestCase".to_string()));
    }
}
<commit_msg>Reworked snake case.<commit_after>/// Converts a `String` to `snake_case` `String`
///
/// #Examples
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "foo_bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "HTTP Foo bar".to_string();
///     let expected_string: String = "http_foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "Foo bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "Foo Bar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "FooBar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "FOO_BAR".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "fooBar".to_string();
///     let expected_string: String = "foo_bar".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
/// ```
///     use inflector::cases::snakecase::to_snake_case;
///     let mock_string: String = "fooBar3".to_string();
///     let expected_string: String = "foo_bar_3".to_string();
///     let asserted_string: String = to_snake_case(mock_string);
///     assert!(asserted_string == expected_string);
///
/// ```
pub fn to_snake_case(non_snake_case_string: String) -> String {
    if non_snake_case_string.contains(' ') ||
        non_snake_case_string.contains('_') ||
            non_snake_case_string.contains('-') {
        let seperators: &[char] = &[' ', '-', '_'];
        let tokens: Vec<&str> = non_snake_case_string.split(seperators).collect();
        tokens.join("_").to_lowercase()
    } else {
        let converted: Vec<String> = non_snake_case_string
            .chars()
            .enumerate()
            .map(|(i, s)|
                 if (s.is_uppercase() == true || s.is_numeric()) && (i > 0 as usize) {
                     format!("_{}", s)
                 } else {
                     s.to_string()
                 }
                 )
            .collect();

        converted
            .join("")
            .to_lowercase()
    }
}

/// Determines of a `String` is `snake_case`
///
/// #Examples
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "Foo bar string that is really really long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo-bar-string-that-is-really-really-long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "FooBarIsAReallyReallyLongString".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "Foo Bar Is A Really Really Long String".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "FOO_BAR_IS_A_REALLY_REALLY_LONG_STRING".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "fooBarIsAReallyReallyLongString".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == false);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar1_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
/// ```
///     use inflector::cases::snakecase::is_snake_case;
///     let mock_string: String = "foo_bar_1_string_that_is_really_really_long".to_string();
///     let asserted_bool: bool = is_snake_case(mock_string);
///     assert!(asserted_bool == true);
///
/// ```
pub fn is_snake_case(test_string: String) -> bool {
    test_string == to_snake_case(test_string.clone())
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;

    #[bench]
    fn bench_snake_from_title(b: &mut Bencher) {
        b.iter(|| super::to_snake_case("Foo bar".to_string()));
    }

    #[bench]
    fn bench_snake_from_camel(b: &mut Bencher) {
        b.iter(|| super::to_snake_case("fooBar".to_string()));
    }

    #[bench]
    fn bench_snake_from_snake(b: &mut Bencher) {
        b.iter(|| super::to_snake_case("foo_bar".to_string()));
    }

    #[bench]
    fn bench_is_snake(b: &mut Bencher) {
        b.iter(|| super::is_snake_case("Foo bar".to_string()));
    }
}
<|endoftext|>


<commit_before>use super::super::interconnect;
use super::cp0;
use super::opcode::Opcode::*;
use super::instruction::Instruction;

use std::fmt;

const NUM_GPR: usize = 32;

pub struct Cpu {
    reg_gpr: [u64; NUM_GPR],
    reg_fpr: [f64; NUM_GPR],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool, // TODO: Enum type

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: cp0::Cp0,

    interconnect: interconnect::Interconnect
}

impl Cpu {
    pub fn new(interconnect: interconnect::Interconnect) -> Cpu {
        Cpu {
            reg_gpr: [0; NUM_GPR],
            reg_fpr: [0.0; NUM_GPR],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: cp0::Cp0::default(),

            interconnect: interconnect
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = 0xffff_ffff_bfc0_0000; // TODO: Move to const
    }

    // TODO: Different interface
    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instr = self.read_instruction(self.reg_pc);

        println!("reg_pc {:#018X}: {:?}", self.reg_pc, instr);

        self.reg_pc += 4;
        self.execute_instruction(instr);
    }

    fn read_instruction(&self, addr: u64) -> Instruction {
        Instruction(self.read_word(addr))
    }

    fn execute_instruction(&mut self, instr: Instruction) {
        match instr.opcode() {
            Addi => {
                // TODO: Handle exception overflow
                let res =
                    self.read_reg_gpr(instr.rs()) + instr.imm_sign_extended();
                self.write_reg_gpr(instr.rt(), res);
            },
            Addiu => {
                let res = self.read_reg_gpr(instr.rs()).wrapping_add(
                    instr.imm_sign_extended());
                self.write_reg_gpr(instr.rt(), res);
            },
            Andi => {
                let res = self.read_reg_gpr(instr.rs()) &
                    (instr.imm() as u64);
                self.write_reg_gpr(instr.rt(), res);
            },
            Ori => {
                let res = self.read_reg_gpr(instr.rs()) |
                    (instr.imm() as u64);
                self.write_reg_gpr(instr.rt(), res);
            },
            Lui => {
                let value = ((instr.imm() << 16) as i32) as u64;
                self.write_reg_gpr(instr.rt(), value);
            },
            Mtc0 => {
                let data = self.read_reg_gpr(instr.rt());
                self.cp0.write_reg(instr.rd(), data);
            },
            Beql => {
                if self.read_reg_gpr(instr.rs()) == self.read_reg_gpr(instr.rt()) {
                    let old_pc = self.reg_pc;

                    let sign_extended_offset =
                        instr.offset_sign_extended().wrapping_shl(2);
                    self.reg_pc =
                        self.reg_pc.wrapping_add(sign_extended_offset);

                    let delay_slot_instr = self.read_instruction(old_pc);
                    self.execute_instruction(delay_slot_instr);
                } else {
                    self.reg_pc = self.reg_pc.wrapping_add(4);
                }
            },
            Lw => {
                let base = instr.rs();

                let sign_extended_offset = instr.offset_sign_extended();
                let virt_addr =
                    self.read_reg_gpr(base as usize).wrapping_add(sign_extended_offset);
                let mem = (self.read_word(virt_addr) as i32) as u64;
                self.write_reg_gpr(instr.rt(), mem);
            }
        }
    }

    fn read_word(&self, virt_addr: u64) -> u32 {
        let phys_addr = self.virt_addr_to_phys_addr(virt_addr);
        // TODO: Check endianness
        self.interconnect.read_word(phys_addr as u32)
    }

    fn virt_addr_to_phys_addr(&self, virt_addr: u64) -> u64 {
        // See Table 5-3 in the VR4300 User's Manual
        let addr_bit_values = (virt_addr >> 29) & 0b111;

        if addr_bit_values == 0b101 {
            // kseg1
            virt_addr - 0xffff_ffff_a000_0000
        } else {
            // TODO
            panic!("Unrecognized virtual address: {:#x}", virt_addr);
        }
    }

    fn write_reg_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gpr[index] = value;
        }
    }

    fn read_reg_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gpr[index]
        }
    }
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const REGS_PER_LINE: usize = 2;
        const REG_NAMES: [&'static str; NUM_GPR] = [
        "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
        "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
        "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
        ];

        try!(write!(f,"\nCPU General Purpose Registers:"));
        for reg_num in 0..NUM_GPR {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f,""));
            }
            try!(write!(f,
                "{reg_name}/gpr{num:02}: {value:#018X} ",
                num = reg_num,
                reg_name = REG_NAMES[reg_num],
                value = self.reg_gpr[reg_num],
            ));
        }

        try!(write!(f,"\n\nCPU Floating Point Registers:"));
        for reg_num in 0..NUM_GPR {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f,""));
            }
            try!(write!(f,
                "fpr{num:02}: {value:21} ",
                num = reg_num,
                value = self.reg_fpr[reg_num],)
            );
        }

        try!(writeln!(f,"\n\nCPU Special Registers:"));
        try!(writeln!(f,
            "\
            reg_pc: {:#018X}\n\
            reg_hi: {:#018X}\n\
            reg_lo: {:#018X}\n\
            reg_llbit: {}\n\
            reg_fcr0:  {:#010X}\n\
            reg_fcr31: {:#010X}\n\
            ",
            self.reg_pc,
            self.reg_hi,
            self.reg_lo,
            self.reg_llbit,
            self.reg_fcr0,
            self.reg_fcr31
        ));

        try!(writeln!(f, "{:#?}", self.cp0));
        writeln!(f, "{:#?}", self.interconnect)
    }
}
<commit_msg>Remove unnecessary .wrapping_shl<commit_after>use super::super::interconnect;
use super::cp0;
use super::opcode::Opcode::*;
use super::instruction::Instruction;

use std::fmt;

const NUM_GPR: usize = 32;

pub struct Cpu {
    reg_gpr: [u64; NUM_GPR],
    reg_fpr: [f64; NUM_GPR],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool, // TODO: Enum type

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: cp0::Cp0,

    interconnect: interconnect::Interconnect
}

impl Cpu {
    pub fn new(interconnect: interconnect::Interconnect) -> Cpu {
        Cpu {
            reg_gpr: [0; NUM_GPR],
            reg_fpr: [0.0; NUM_GPR],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: cp0::Cp0::default(),

            interconnect: interconnect
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = 0xffff_ffff_bfc0_0000; // TODO: Move to const
    }

    // TODO: Different interface
    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instr = self.read_instruction(self.reg_pc);

        println!("reg_pc {:#018X}: {:?}", self.reg_pc, instr);

        self.reg_pc += 4;
        self.execute_instruction(instr);
    }

    fn read_instruction(&self, addr: u64) -> Instruction {
        Instruction(self.read_word(addr))
    }

    fn execute_instruction(&mut self, instr: Instruction) {
        match instr.opcode() {
            Addi => {
                // TODO: Handle exception overflow
                let res =
                    self.read_reg_gpr(instr.rs()) + instr.imm_sign_extended();
                self.write_reg_gpr(instr.rt(), res);
            },
            Addiu => {
                let res = self.read_reg_gpr(instr.rs()).wrapping_add(
                    instr.imm_sign_extended());
                self.write_reg_gpr(instr.rt(), res);
            },
            Andi => {
                let res = self.read_reg_gpr(instr.rs()) &
                    (instr.imm() as u64);
                self.write_reg_gpr(instr.rt(), res);
            },
            Ori => {
                let res = self.read_reg_gpr(instr.rs()) |
                    (instr.imm() as u64);
                self.write_reg_gpr(instr.rt(), res);
            },
            Lui => {
                let value = ((instr.imm() << 16) as i32) as u64;
                self.write_reg_gpr(instr.rt(), value);
            },
            Mtc0 => {
                let data = self.read_reg_gpr(instr.rt());
                self.cp0.write_reg(instr.rd(), data);
            },
            Beql => {
                if self.read_reg_gpr(instr.rs()) == self.read_reg_gpr(instr.rt()) {
                    let old_pc = self.reg_pc;

                    let sign_extended_offset =
                        instr.offset_sign_extended() << 2;
                    self.reg_pc =
                        self.reg_pc.wrapping_add(sign_extended_offset);

                    let delay_slot_instr = self.read_instruction(old_pc);
                    self.execute_instruction(delay_slot_instr);
                } else {
                    self.reg_pc = self.reg_pc.wrapping_add(4);
                }
            },
            Lw => {
                let base = instr.rs();

                let sign_extended_offset = instr.offset_sign_extended();
                let virt_addr =
                    self.read_reg_gpr(base as usize).wrapping_add(sign_extended_offset);
                let mem = (self.read_word(virt_addr) as i32) as u64;
                self.write_reg_gpr(instr.rt(), mem);
            }
        }
    }

    fn read_word(&self, virt_addr: u64) -> u32 {
        let phys_addr = self.virt_addr_to_phys_addr(virt_addr);
        // TODO: Check endianness
        self.interconnect.read_word(phys_addr as u32)
    }

    fn virt_addr_to_phys_addr(&self, virt_addr: u64) -> u64 {
        // See Table 5-3 in the VR4300 User's Manual
        let addr_bit_values = (virt_addr >> 29) & 0b111;

        if addr_bit_values == 0b101 {
            // kseg1
            virt_addr - 0xffff_ffff_a000_0000
        } else {
            // TODO
            panic!("Unrecognized virtual address: {:#x}", virt_addr);
        }
    }

    fn write_reg_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gpr[index] = value;
        }
    }

    fn read_reg_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gpr[index]
        }
    }
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const REGS_PER_LINE: usize = 2;
        const REG_NAMES: [&'static str; NUM_GPR] = [
        "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
        "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
        "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
        ];

        try!(write!(f,"\nCPU General Purpose Registers:"));
        for reg_num in 0..NUM_GPR {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f,""));
            }
            try!(write!(f,
                "{reg_name}/gpr{num:02}: {value:#018X} ",
                num = reg_num,
                reg_name = REG_NAMES[reg_num],
                value = self.reg_gpr[reg_num],
            ));
        }

        try!(write!(f,"\n\nCPU Floating Point Registers:"));
        for reg_num in 0..NUM_GPR {
            if (reg_num % REGS_PER_LINE) == 0 {
                try!(writeln!(f,""));
            }
            try!(write!(f,
                "fpr{num:02}: {value:21} ",
                num = reg_num,
                value = self.reg_fpr[reg_num],)
            );
        }

        try!(writeln!(f,"\n\nCPU Special Registers:"));
        try!(writeln!(f,
            "\
            reg_pc: {:#018X}\n\
            reg_hi: {:#018X}\n\
            reg_lo: {:#018X}\n\
            reg_llbit: {}\n\
            reg_fcr0:  {:#010X}\n\
            reg_fcr31: {:#010X}\n\
            ",
            self.reg_pc,
            self.reg_hi,
            self.reg_lo,
            self.reg_llbit,
            self.reg_fcr0,
            self.reg_fcr31
        ));

        try!(writeln!(f, "{:#?}", self.cp0));
        writeln!(f, "{:#?}", self.interconnect)
    }
}
<|endoftext|>


<commit_before>use crate::hotkey::{Hook, KeyCode};
use crate::{HotkeyConfig, SharedTimer};
use alloc::sync::Arc;
use core::sync::atomic::{AtomicBool, Ordering};

pub use crate::hotkey::{Error, Result};

/// With a Hotkey System the runner can use hotkeys on their keyboard to control
/// the Timer. The hotkeys are global, so the application doesn't need to be in
/// focus. The behavior of the hotkeys depends on the platform and is stubbed
/// out on platforms that don't support hotkeys. You can turn off a Hotkey
/// System temporarily. By default the Hotkey System is activated.
pub struct HotkeySystem {
    config: HotkeyConfig,
    hook: Hook,
    timer: SharedTimer,
    is_active: Arc<AtomicBool>,
}

impl HotkeySystem {
    /// Creates a new Hotkey System for a Timer with the default hotkeys.
    pub fn new(timer: SharedTimer) -> Result<Self> {
        Self::with_config(timer, Default::default())
    }

    /// Creates a new Hotkey System for a Timer with a custom configuration for
    /// the hotkeys.
    pub fn with_config(timer: SharedTimer, config: HotkeyConfig) -> Result<Self> {
        let hook = Hook::new()?;

        let is_active = Arc::new(AtomicBool::new(true));

        if let Some(split) = config.split {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(split, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().split_or_start();
                }
            })?;
        }

        if let Some(reset) = config.reset {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(reset, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().reset(true);
                }
            })?;
        }

        if let Some(undo) = config.undo {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(undo, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().undo_split();
                }
            })?;
        }

        if let Some(skip) = config.skip {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(skip, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().skip_split();
                }
            })?;
        }

        if let Some(pause) = config.pause {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(pause, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().toggle_pause_or_start();
                }
            })?;
        }

        if let Some(previous_comparison) = config.previous_comparison {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(previous_comparison, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().switch_to_previous_comparison();
                }
            })?;
        }

        if let Some(next_comparison) = config.next_comparison {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(next_comparison, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().switch_to_next_comparison();
                }
            })?;
        }

        if let Some(undo_all_pauses) = config.undo_all_pauses {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(undo_all_pauses, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().undo_all_pauses();
                }
            })?;
        }

        if let Some(toggle_timing_method) = config.toggle_timing_method {
            let inner = timer.clone();
            let active = is_active.clone();
            hook.register(toggle_timing_method, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().toggle_timing_method();
                }
            })?;
        }

        Ok(Self {
            config,
            hook,
            timer,
            is_active,
        })
    }

    /// Sets the key to use for splitting and starting a new attempt.
    pub fn set_split(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.split == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().split_or_start();
                }
            })?;
        }
        if let Some(split) = self.config.split {
            self.hook.unregister(split)?;
        }
        self.config.split = hotkey;
        Ok(())
    }

    /// Sets the key to use for resetting the current attempt.
    pub fn set_reset(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.reset == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().reset(true);
                }
            })?;
        }
        if let Some(reset) = self.config.reset {
            self.hook.unregister(reset)?;
        }
        self.config.reset = hotkey;
        Ok(())
    }

    /// Sets the key to use for pausing the current attempt and starting a new
    /// attempt.
    pub fn set_pause(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.pause == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().toggle_pause_or_start();
                }
            })?;
        }
        if let Some(pause) = self.config.pause {
            self.hook.unregister(pause)?;
        }
        self.config.pause = hotkey;
        Ok(())
    }

    /// Sets the key to use for skipping the current split.
    pub fn set_skip(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.skip == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().skip_split();
                }
            })?;
        }
        if let Some(skip) = self.config.skip {
            self.hook.unregister(skip)?;
        }
        self.config.skip = hotkey;
        Ok(())
    }

    /// Sets the key to use for undoing the last split.
    pub fn set_undo(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.undo == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().undo_split();
                }
            })?;
        }
        if let Some(undo) = self.config.undo {
            self.hook.unregister(undo)?;
        }
        self.config.undo = hotkey;
        Ok(())
    }

    /// Sets the key to use for switching to the previous comparison.
    pub fn set_previous_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.previous_comparison == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().switch_to_previous_comparison();
                }
            })?;
        }
        if let Some(previous_comparison) = self.config.previous_comparison {
            self.hook.unregister(previous_comparison)?;
        }
        self.config.previous_comparison = hotkey;
        Ok(())
    }

    /// Sets the key to use for switching to the next comparison.
    pub fn set_next_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.next_comparison == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().switch_to_next_comparison();
                }
            })?;
        }
        if let Some(next_comparison) = self.config.next_comparison {
            self.hook.unregister(next_comparison)?;
        }
        self.config.next_comparison = hotkey;
        Ok(())
    }

    /// Sets the key to use for removing all the pause times from the current
    /// time.
    pub fn set_undo_all_pauses(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.undo_all_pauses == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().undo_all_pauses();
                }
            })?;
        }
        if let Some(undo_all_pauses) = self.config.undo_all_pauses {
            self.hook.unregister(undo_all_pauses)?;
        }
        self.config.undo_all_pauses = hotkey;
        Ok(())
    }

    /// Sets the key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub fn set_toggle_timing_method(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        if self.config.toggle_timing_method == hotkey {
            return Ok(());
        }
        let inner = self.timer.clone();
        let active = self.is_active.clone();
        if let Some(hotkey) = hotkey {
            self.hook.register(hotkey, move || {
                if active.load(Ordering::Acquire) {
                    inner.write().toggle_timing_method();
                }
            })?;
        }
        if let Some(toggle_timing_method) = self.config.toggle_timing_method {
            self.hook.unregister(toggle_timing_method)?;
        }
        self.config.toggle_timing_method = hotkey;
        Ok(())
    }

    /// Deactivates the Hotkey System. No hotkeys will go through until it gets
    /// activated again. If it's already deactivated, nothing happens.
    pub fn deactivate(&self) {
        self.is_active.store(false, Ordering::Release);
    }

    /// Activates a previously deactivated Hotkey System. If it's already
    /// active, nothing happens.
    pub fn activate(&self) {
        self.is_active.store(true, Ordering::Release);
    }

    /// Returns the hotkey configuration currently in use by the Hotkey System.
    pub fn config(&self) -> HotkeyConfig {
        self.config
    }

    /// Applies a new hotkey configuration to the Hotkey System. Each hotkey is
    /// changed to the one specified in the configuration. This operation may
    /// fail if you provide a hotkey configuration where a hotkey is used for
    /// multiple operations.
    pub fn set_config(&mut self, config: HotkeyConfig) -> Result<()> {
        self.set_split(config.split)?;
        self.set_reset(config.reset)?;
        self.set_undo(config.undo)?;
        self.set_skip(config.skip)?;
        self.set_pause(config.pause)?;
        self.set_previous_comparison(config.previous_comparison)?;
        self.set_next_comparison(config.next_comparison)?;
        self.set_undo_all_pauses(config.undo_all_pauses)?;
        self.set_toggle_timing_method(config.toggle_timing_method)?;

        Ok(())
    }
}
<commit_msg>(un-)grabbing of keys is now done when (de-)activating HotkeySystem; this breaks the API since now (de-)activative returns Result<()>; we also have a private enum that reduces the amount of boilerplate code<commit_after>use crate::hotkey::{Hook, KeyCode};
use crate::{HotkeyConfig, SharedTimer};

pub use crate::hotkey::{Error, Result};

// This enum might be better situated in hotkey_config, but the last method should stay in this file
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum Hotkey {
    Split,
    /// The key to use for resetting the current attempt.
    Reset,
    /// The key to use for undoing the last split.
    Undo,
    /// The key to use for skipping the current split.
    Skip,
    /// The key to use for pausing the current attempt and starting a new
    /// attempt.
    Pause,
    /// The key to use for removing all the pause times from the current time.
    UndoAllPauses,
    /// The key to use for switching to the previous comparison.
    PreviousComparison,
    /// The key to use for switching to the next comparison.
    NextComparison,
    /// The key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    ToggleTimingMethod,
}

impl Hotkey {
    fn set_keycode(self, config: &mut HotkeyConfig, keycode: Option<KeyCode>) {
        match self {
            Hotkey::Split => config.split = keycode,
            Hotkey::Reset => config.reset = keycode,
            Hotkey::Undo => config.undo = keycode,
            Hotkey::Skip => config.skip = keycode,
            Hotkey::Pause => config.pause = keycode,
            Hotkey::UndoAllPauses => config.undo_all_pauses = keycode,
            Hotkey::PreviousComparison => config.previous_comparison = keycode,
            Hotkey::NextComparison => config.next_comparison = keycode,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method = keycode,
        }
    }
    fn get_keycode(self, config: &HotkeyConfig) -> Option<KeyCode> {
        match self {
            Hotkey::Split => config.split,
            Hotkey::Reset => config.reset,
            Hotkey::Undo => config.undo,
            Hotkey::Skip => config.skip,
            Hotkey::Pause => config.pause,
            Hotkey::UndoAllPauses => config.undo_all_pauses,
            Hotkey::PreviousComparison => config.previous_comparison,
            Hotkey::NextComparison => config.next_comparison,
            Hotkey::ToggleTimingMethod => config.toggle_timing_method,
        }
    }
    fn callback(self, timer: SharedTimer) -> Box<dyn FnMut() + Send + 'static>{
        match self {
            Hotkey::Split => Box::new(move || timer.write().split_or_start()),
            Hotkey::Reset => Box::new(move || timer.write().reset(true)),
            Hotkey::Undo => Box::new(move || timer.write().undo_split()),
            Hotkey::Skip => Box::new(move || timer.write().skip_split()),
            Hotkey::Pause => Box::new(move || timer.write().toggle_pause_or_start()),
            Hotkey::UndoAllPauses => Box::new(move || timer.write().undo_all_pauses()),
            Hotkey::PreviousComparison => Box::new(move || timer.write().switch_to_previous_comparison()),
            Hotkey::NextComparison => Box::new(move || timer.write().switch_to_next_comparison()),
            Hotkey::ToggleTimingMethod => Box::new(move || timer.write().toggle_timing_method()),
        }
    }
}

/// With a Hotkey System the runner can use hotkeys on their keyboard to control
/// the Timer. The hotkeys are global, so the application doesn't need to be in
/// focus. The behavior of the hotkeys depends on the platform and is stubbed
/// out on platforms that don't support hotkeys. You can turn off a Hotkey
/// System temporarily. By default the Hotkey System is activated.
pub struct HotkeySystem {
    config: HotkeyConfig,
    hook: Hook,
    timer: SharedTimer,
    is_active: bool,
}

impl HotkeySystem {
    /// Creates a new Hotkey System for a Timer with the default hotkeys.
    pub fn new(timer: SharedTimer) -> Result<Self> {
        Self::with_config(timer, Default::default())
    }

    /// Creates a new Hotkey System for a Timer with a custom configuration for
    /// the hotkeys.
    pub fn with_config(timer: SharedTimer, config: HotkeyConfig) -> Result<Self> {
        let mut hotkey_system = Self {
            config : config,
            hook : Hook::new()?,
            timer : timer,
            is_active : false,
        };
        hotkey_system.activate()?;
        Ok(hotkey_system)
    }
    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn register_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        let inner = self.timer.clone();
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            println!("Registering Keycode {:?} as {:?}", keycode, hotkey);
            self.hook.register(keycode, hotkey.callback(inner))?;
        }
        Ok(())
    }
    fn register(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        hotkey.set_keycode(&mut self.config, keycode);
        unsafe { self.register_raw(hotkey) }
    }
    // This method should never be public, because it might mess up the internal state and we might
    // leak a registered hotkey
    unsafe fn unregister_raw(&mut self, hotkey: Hotkey) -> Result<()> {
        if let Some(keycode) = hotkey.get_keycode(&self.config) {
            println!("Unregistering Keycode {:?} as {:?}", keycode, hotkey);
            self.hook.unregister(keycode)?;
        }
        Ok(())
    }
    fn unregister(&mut self, hotkey: Hotkey) -> Result<()> {
        hotkey.set_keycode(&mut self.config, None);
        unsafe { self.unregister_raw(hotkey) }
    }
    fn set_hotkey(&mut self, hotkey: Hotkey, keycode: Option<KeyCode>) -> Result<()> {
        // FixMe: We do not check whether the keycode is already in use
        if hotkey.get_keycode(&self.config) == keycode {
            return Ok(());
        }
        if self.is_active {
            self.unregister(hotkey)?;
            self.register(hotkey, keycode)?;
        }
        Ok(())
    }

    /// Sets the key to use for splitting and starting a new attempt.
    pub fn set_split(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Split, hotkey)
    }

    /// Sets the key to use for resetting the current attempt.
    pub fn set_reset(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Reset, hotkey)
    }

    /// Sets the key to use for pausing the current attempt and starting a new
    /// attempt.
    pub fn set_pause(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Pause, hotkey)
    }

    /// Sets the key to use for skipping the current split.
    pub fn set_skip(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Skip, hotkey)
    }

    /// Sets the key to use for undoing the last split.
    pub fn set_undo(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::Undo, hotkey)
    }

    /// Sets the key to use for switching to the previous comparison.
    pub fn set_previous_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::PreviousComparison, hotkey)
    }

    /// Sets the key to use for switching to the next comparison.
    pub fn set_next_comparison(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::NextComparison, hotkey)
    }

    /// Sets the key to use for removing all the pause times from the current
    /// time.
    pub fn set_undo_all_pauses(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::UndoAllPauses, hotkey)
    }

    /// Sets the key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub fn set_toggle_timing_method(&mut self, hotkey: Option<KeyCode>) -> Result<()> {
        self.set_hotkey(Hotkey::ToggleTimingMethod, hotkey)
    }

    /// Deactivates the Hotkey System. No hotkeys will go through until it gets
    /// activated again. If it's already deactivated, nothing happens.
    pub fn deactivate(&mut self) -> Result<()> {
        if self.is_active {
            unsafe {
                self.unregister_raw(Hotkey::Split)?;
                self.unregister_raw(Hotkey::Reset)?;
                self.unregister_raw(Hotkey::Undo)?;
                self.unregister_raw(Hotkey::Skip)?;
                self.unregister_raw(Hotkey::Pause)?;
                self.unregister_raw(Hotkey::UndoAllPauses)?;
                self.unregister_raw(Hotkey::PreviousComparison)?;
                self.unregister_raw(Hotkey::NextComparison)?;
                self.unregister_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = false;
        Ok(())
    }

    /// Activates a previously deactivated Hotkey System. If it's already
    /// active, nothing happens.
    pub fn activate(&mut self) -> Result<()> {
        if !self.is_active {
            unsafe {
                self.register_raw(Hotkey::Split)?;
                self.register_raw(Hotkey::Reset)?;
                self.register_raw(Hotkey::Undo)?;
                self.register_raw(Hotkey::Skip)?;
                self.register_raw(Hotkey::Pause)?;
                self.register_raw(Hotkey::UndoAllPauses)?;
                self.register_raw(Hotkey::PreviousComparison)?;
                self.register_raw(Hotkey::NextComparison)?;
                self.register_raw(Hotkey::ToggleTimingMethod)?;
            }
        }
        self.is_active = true;
        Ok(())
    }

    /// Returns true if the Hotkey System is active, false otherwise.
    pub fn is_active(&self) -> bool {
        self.is_active
    }

    /// Returns the hotkey configuration currently in use by the Hotkey System.
    pub fn config(&self) -> HotkeyConfig {
        self.config
    }

    /// Applies a new hotkey configuration to the Hotkey System. Each hotkey is
    /// changed to the one specified in the configuration. This operation may
    /// fail if you provide a hotkey configuration where a hotkey is used for
    /// multiple operations.
    pub fn set_config(&mut self, config: HotkeyConfig) -> Result<()> {
        self.set_split(config.split)?;
        self.set_reset(config.reset)?;
        self.set_undo(config.undo)?;
        self.set_skip(config.skip)?;
        self.set_pause(config.pause)?;
        self.set_previous_comparison(config.previous_comparison)?;
        self.set_next_comparison(config.next_comparison)?;
        self.set_undo_all_pauses(config.undo_all_pauses)?;
        self.set_toggle_timing_method(config.toggle_timing_method)?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use gfx;
use image;
use image::{
    DynamicImage,
    GenericImage,
    RgbaImage,
};
use texture_lib::ImageSize;

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{}': {}",
                path.filename_str().unwrap(), e)),
        };

        let img = match img {
            DynamicImage::ImageRgba8(img) => img,
            x => x.to_rgba()
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &RgbaImage) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }

    /// Creates a texture from RGBA image.
    pub fn from_rgba8<D: gfx::Device<C>, C: gfx::CommandBuffer>(
        img: RgbaImage,
        d: &mut D
    ) -> Texture {
        let (width, height) = img.dimensions();

        let mut ti = gfx::tex::TextureInfo::new();
        ti.width = width as u16;
        ti.height = height as u16;
        ti.kind = gfx::tex::TextureKind::Texture2D;
        ti.format = gfx::tex::RGBA8;

        let tex = d.create_texture(ti).unwrap();
        d.update_texture(&tex, &ti.to_image_info(),
                         img.into_vec().as_slice()).unwrap();
        d.generate_mipmap(&tex);

        Texture {
            handle: tex,
        }
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(
        device: &mut D,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Texture {
        use std::cmp::max;

        let width = max(width, 1);
        let height = max(height, 1);

        let mut pixels = Vec::new();
        for alpha in buffer.iter() {
            pixels.push(255);
            pixels.push(255);
            pixels.push(255);
            pixels.push(*alpha);
        }

        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };

        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            pixels.as_slice())
            .unwrap();
        Texture {
            handle: texture
        }
    }

    /// Updates the texture with an image.
    pub fn update<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(&mut self, device: &mut D, image: &RgbaImage) {
        device.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            image.as_slice()
        ).unwrap();
    }

    /// Gets the size of the texture.
    #[inline(always)]
    pub fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }

    /// Gets the width of the texture.
    #[inline(always)]
    pub fn get_width(&self) -> u32 {
        let (w, _) = self.get_size();
        w
    }

    /// Gets the height of the texture.
    #[inline(always)]
    pub fn get_height(&self) -> u32 {
        let (_, h) = self.get_size();
        h
    }
}

impl ImageSize for Texture {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}

<commit_msg>Update format string syntax<commit_after>use gfx;
use image;
use image::{
    DynamicImage,
    GenericImage,
    RgbaImage,
};
use texture_lib::ImageSize;

/// Represents a texture.
pub struct Texture {
    /// A handle to the Gfx texture.
    pub handle: gfx::TextureHandle,
}

impl Texture {
    /// Creates a texture from path.
    pub fn from_path<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, path: &Path) -> Result<Texture, String> {
        let img = match image::open(path) {
            Ok(img) => img,
            Err(e)  => return Err(format!("Could not load '{:?}': {:?}",
                path.filename_str().unwrap(), e)),
        };

        let img = match img {
            DynamicImage::ImageRgba8(img) => img,
            x => x.to_rgba()
        };

        let (width, height) = img.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            img.as_slice())
        .unwrap();

        Ok(Texture {
            handle: texture
        })
    }

    /// Creates a texture from image.
    pub fn from_image<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(device: &mut D, image: &RgbaImage) -> Texture {
        let (width, height) = image.dimensions();
        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            image.as_slice())
        .unwrap();

        Texture {
            handle: texture
        }
    }

    /// Creates a texture from RGBA image.
    pub fn from_rgba8<D: gfx::Device<C>, C: gfx::CommandBuffer>(
        img: RgbaImage,
        d: &mut D
    ) -> Texture {
        let (width, height) = img.dimensions();

        let mut ti = gfx::tex::TextureInfo::new();
        ti.width = width as u16;
        ti.height = height as u16;
        ti.kind = gfx::tex::TextureKind::Texture2D;
        ti.format = gfx::tex::RGBA8;

        let tex = d.create_texture(ti).unwrap();
        d.update_texture(&tex, &ti.to_image_info(),
                         img.into_vec().as_slice()).unwrap();
        d.generate_mipmap(&tex);

        Texture {
            handle: tex,
        }
    }

    /// Creates texture from memory alpha.
    pub fn from_memory_alpha<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(
        device: &mut D,
        buffer: &[u8],
        width: u32,
        height: u32,
    ) -> Texture {
        use std::cmp::max;

        let width = max(width, 1);
        let height = max(height, 1);

        let mut pixels = Vec::new();
        for alpha in buffer.iter() {
            pixels.push(255);
            pixels.push(255);
            pixels.push(255);
            pixels.push(*alpha);
        }

        let texture_info = gfx::tex::TextureInfo {
            width: width as u16,
            height: height as u16,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };

        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info).unwrap();
        device.update_texture(&texture, &image_info,
            pixels.as_slice())
            .unwrap();
        Texture {
            handle: texture
        }
    }

    /// Updates the texture with an image.
    pub fn update<
        C: gfx::CommandBuffer,
        D: gfx::Device<C>
    >(&mut self, device: &mut D, image: &RgbaImage) {
        device.update_texture(&self.handle,
            &self.handle.get_info().to_image_info(),
            image.as_slice()
        ).unwrap();
    }

    /// Gets the size of the texture.
    #[inline(always)]
    pub fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }

    /// Gets the width of the texture.
    #[inline(always)]
    pub fn get_width(&self) -> u32 {
        let (w, _) = self.get_size();
        w
    }

    /// Gets the height of the texture.
    #[inline(always)]
    pub fn get_height(&self) -> u32 {
        let (_, h) = self.get_size();
        h
    }
}

impl ImageSize for Texture {
    #[inline(always)]
    fn get_size(&self) -> (u32, u32) {
        let info = self.handle.get_info();
        (info.width as u32, info.height as u32)
    }
}

<|endoftext|>


<commit_before>use std::iter::Fuse;
use alloc::collections::VecDeque;
use crate::size_hint;
use crate::PeekingNext;

/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
pub struct MultiPeek<I>
    where I: Iterator
{
    iter: Fuse<I>,
    buf: VecDeque<I::Item>,
    index: usize,
}

/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
    where I: IntoIterator
{
    MultiPeek {
        iter: iterable.into_iter().fuse(),
        buf: VecDeque::new(),
        index: 0,
    }
}

impl<I> MultiPeek<I>
    where I: Iterator
{
    /// Reset the peeking “cursor”
    pub fn reset_peek(&mut self) {
        self.index = 0;
    }
}

impl<I: Iterator> MultiPeek<I> {
    /// Works exactly like `.next()` with the only difference that it doesn't
    /// advance itself. `.peek()` can be called multiple times, to peek
    /// further ahead.
    pub fn peek(&mut self) -> Option<&I::Item> {
        let ret = if self.index < self.buf.len() {
            Some(&self.buf[self.index])
        } else {
            match self.iter.next() {
                Some(x) => {
                    self.buf.push_back(x);
                    Some(&self.buf[self.index])
                }
                None => return None,
            }
        };

        self.index += 1;
        ret
    }
}

impl<I> PeekingNext for MultiPeek<I>
    where I: Iterator,
{
    fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
        where F: FnOnce(&Self::Item) -> bool
    {
        if self.buf.is_empty() {
            if let Some(r) = self.peek() {
                if !accept(r) { return None }
            }
        } else {
            if let Some(r) = self.buf.get(0) {
                if !accept(r) { return None }
            }
        }
        self.next()
    }
}

impl<I> Iterator for MultiPeek<I>
    where I: Iterator
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.index = 0;
        self.buf.pop_front().or_else(|| self.iter.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
    }
}

// Same size
impl<I> ExactSizeIterator for MultiPeek<I>
    where I: ExactSizeIterator
{}

<commit_msg>Clarify how `next()` interacts with `peek()` in` MultiPeek`.<commit_after>use std::iter::Fuse;
use alloc::collections::VecDeque;
use crate::size_hint;
use crate::PeekingNext;

/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
pub struct MultiPeek<I>
    where I: Iterator
{
    iter: Fuse<I>,
    buf: VecDeque<I::Item>,
    index: usize,
}

/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
    where I: IntoIterator
{
    MultiPeek {
        iter: iterable.into_iter().fuse(),
        buf: VecDeque::new(),
        index: 0,
    }
}

impl<I> MultiPeek<I>
    where I: Iterator
{
    /// Reset the peeking “cursor”
    pub fn reset_peek(&mut self) {
        self.index = 0;
    }
}

impl<I: Iterator> MultiPeek<I> {
    /// Works exactly like `.next()` with the only difference that it doesn't
    /// advance itself. `.peek()` can be called multiple times, to peek
    /// further ahead.
    /// When `.next()` is called, reset the peeking “cursor”.
    pub fn peek(&mut self) -> Option<&I::Item> {
        let ret = if self.index < self.buf.len() {
            Some(&self.buf[self.index])
        } else {
            match self.iter.next() {
                Some(x) => {
                    self.buf.push_back(x);
                    Some(&self.buf[self.index])
                }
                None => return None,
            }
        };

        self.index += 1;
        ret
    }
}

impl<I> PeekingNext for MultiPeek<I>
    where I: Iterator,
{
    fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
        where F: FnOnce(&Self::Item) -> bool
    {
        if self.buf.is_empty() {
            if let Some(r) = self.peek() {
                if !accept(r) { return None }
            }
        } else {
            if let Some(r) = self.buf.get(0) {
                if !accept(r) { return None }
            }
        }
        self.next()
    }
}

impl<I> Iterator for MultiPeek<I>
    where I: Iterator
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.index = 0;
        self.buf.pop_front().or_else(|| self.iter.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
    }
}

// Same size
impl<I> ExactSizeIterator for MultiPeek<I>
    where I: ExactSizeIterator
{}

<|endoftext|>


<commit_before>
pub fn from_hex(hex_in: &str) -> Result<Vec<u8>, &'static str>
{
    if hex_in.len() % 2 == 1 {
        return Err("Odd string length in hex encoded value.");
    }

    let mut bin_out = Vec::new();

    let mut raw_chars = hex_in.chars().peekable();
    while raw_chars.peek() != None {
        let nibble1 = raw_chars.next().unwrap().to_digit(16);
        let nibble2 = raw_chars.next().unwrap().to_digit(16);

        if nibble1 == None || nibble2 == None {
            return Err("Invalid hex characters encountered.");
        }

        bin_out.push((nibble1.unwrap() * 16 + nibble2.unwrap()) as u8);
    }

    Ok(bin_out)
}

pub fn to_hex(binary: &[u8]) -> String {

    fn to_hex_char(byte: u8) -> char { Char::from_digit(byte as uint, 16).unwrap() }

    binary.iter().fold(String::new(),
        |mut s, &b| {
            s.push(to_hex_char(b >> 4));
            s.push(to_hex_char(b & 0x0f));
            s
        }
    )
}

fn encode_single_base64(byte_in: u8) -> Option<char> {
    match byte_in {
        0...25 => Some((65u8 + byte_in) as char),
        26...51 => Some((71u8 + byte_in) as char),
        52...61 => Some((byte_in - 4u8) as char),
        62 => Some('+'),
        63 => Some('/'),
        _ => None
    }
}

#[test]
fn test_encode_single_base64_basics() {
    assert_eq!(encode_single_base64(0), Some('A'));
    assert_eq!(encode_single_base64(27), Some('b'));
    assert_eq!(encode_single_base64(61), Some('9'));
    assert_eq!(encode_single_base64(63), Some('/'));
}

#[test]
fn test_encode_single_base64_fail() {
    assert_eq!(encode_single_base64(64), None);
    assert_eq!(encode_single_base64(255), None);
}

pub fn to_base64(bin_in: &[u8]) -> String {
    let mut result = String::new();

    let mut i = 0u;
    let total = bin_in.len();
    while i < total {
        // combine three bytes
        let mut current = bin_in[i] as u32 << 16;
        let mut fill_bytes = 0u;
        current += if i+1 < total { bin_in[i+1] as u32 << 8 } else { fill_bytes +=1; 0 };
        current += if i+2 < total { bin_in[i+2] as u32 } else { fill_bytes +=1; 0 };

        // encode
        result.push(encode_single_base64(((current & 0x00fc0000) >> 18) as u8).unwrap());
        result.push(encode_single_base64(((current & 0x0003f000) >> 12) as u8).unwrap());
        result.push(if fill_bytes < 2 { encode_single_base64(((current & 0x00000fc0) >> 6) as u8).unwrap() } else { '=' });
        result.push(if fill_bytes < 1 { encode_single_base64((current & 0x0000003f) as u8 ).unwrap() } else { '=' });

        i += 3;
    }

    result
}

#[test]
fn test_from_hex_basics() {
    assert_eq!(from_hex(""), Ok(vec![]));
    assert_eq!(from_hex("01"), Ok(vec![1]));
    assert_eq!(from_hex("ff"), Ok(vec![255]));
    assert_eq!(from_hex("A0"), Ok(vec![160]));
    assert_eq!(from_hex("A00AFf"), Ok(vec![160, 10, 255]));
}

#[test]
fn test_from_hex_fail() {
    assert_eq!(from_hex("A"), Err("Odd string length in hex encoded value."));
    assert_eq!(from_hex("ABCDEFGH"), Err("Invalid hex characters encountered."));
    assert_eq!(from_hex("+#"), Err("Invalid hex characters encountered."));
}

#[test]
fn test_to_base64_rfc4648() {
   assert_eq!(to_base64([]), String::from_str(""));
   assert_eq!(to_base64(b"f"), String::from_str("Zg=="));
   assert_eq!(to_base64(b"fo"), String::from_str("Zm8="));
   assert_eq!(to_base64(b"foo"), String::from_str("Zm9v"));
   assert_eq!(to_base64(b"foob"), String::from_str("Zm9vYg=="));
   assert_eq!(to_base64(b"fooba"), String::from_str("Zm9vYmE="));
   assert_eq!(to_base64(b"foobar"), String::from_str("Zm9vYmFy"));
}

#[test]
fn test_to_hex_basics() {
    assert_eq!(to_hex([]), "".to_string());
    assert_eq!(to_hex([0]), "00".to_string());
    assert_eq!(to_hex([1]), "01".to_string());
    assert_eq!(to_hex([16]), "10".to_string());
    assert_eq!(to_hex([255]), "ff".to_string());
    assert_eq!(to_hex([255,1]), "ff01".to_string());
}
<commit_msg>Add some documentation<commit_after>/// Reads a byte array from a hex encoded string.
/// Case does not matter but if any non-hex character is encountered or the
/// input's length is not even an error is returned.
/// # Arguments
/// * `str` - hex-coded string to convert
pub fn from_hex(hex_in: &str) -> Result<Vec<u8>, &'static str>
{
    if hex_in.len() % 2 == 1 {
        return Err("Odd string length in hex encoded value.");
    }

    let mut bin_out = Vec::new();

    let mut raw_chars = hex_in.chars().peekable();
    while raw_chars.peek() != None {
        let nibble1 = raw_chars.next().unwrap().to_digit(16);
        let nibble2 = raw_chars.next().unwrap().to_digit(16);

        if nibble1 == None || nibble2 == None {
            return Err("Invalid hex characters encountered.");
        }

        bin_out.push((nibble1.unwrap() * 16 + nibble2.unwrap()) as u8);
    }

    Ok(bin_out)
}

/// Converts a byte array into a hex encoded string.
///
/// # Arguments
/// * `binary` - byte array to transform
pub fn to_hex(binary: &[u8]) -> String {

    fn to_hex_char(byte: u8) -> char { Char::from_digit(byte as uint, 16).unwrap() }

    binary.iter().fold(String::new(),
        |mut s, &b| {
            s.push(to_hex_char(b >> 4));
            s.push(to_hex_char(b & 0x0f));
            s
        }
    )
}

fn encode_single_base64(byte_in: u8) -> Option<char> {
    match byte_in {
        0...25 => Some((65u8 + byte_in) as char),
        26...51 => Some((71u8 + byte_in) as char),
        52...61 => Some((byte_in - 4u8) as char),
        62 => Some('+'),
        63 => Some('/'),
        _ => None
    }
}

#[test]
fn test_encode_single_base64_basics() {
    assert_eq!(encode_single_base64(0), Some('A'));
    assert_eq!(encode_single_base64(27), Some('b'));
    assert_eq!(encode_single_base64(61), Some('9'));
    assert_eq!(encode_single_base64(63), Some('/'));
}

#[test]
fn test_encode_single_base64_fail() {
    assert_eq!(encode_single_base64(64), None);
    assert_eq!(encode_single_base64(255), None);
}

pub fn to_base64(bin_in: &[u8]) -> String {
    let mut result = String::new();

    let mut i = 0u;
    let total = bin_in.len();
    while i < total {
        // combine three bytes
        let mut current = bin_in[i] as u32 << 16;
        let mut fill_bytes = 0u;
        current += if i+1 < total { bin_in[i+1] as u32 << 8 } else { fill_bytes +=1; 0 };
        current += if i+2 < total { bin_in[i+2] as u32 } else { fill_bytes +=1; 0 };

        // encode
        result.push(encode_single_base64(((current & 0x00fc0000) >> 18) as u8).unwrap());
        result.push(encode_single_base64(((current & 0x0003f000) >> 12) as u8).unwrap());
        result.push(if fill_bytes < 2 { encode_single_base64(((current & 0x00000fc0) >> 6) as u8).unwrap() } else { '=' });
        result.push(if fill_bytes < 1 { encode_single_base64((current & 0x0000003f) as u8 ).unwrap() } else { '=' });

        i += 3;
    }

    result
}

#[test]
fn test_from_hex_basics() {
    assert_eq!(from_hex(""), Ok(vec![]));
    assert_eq!(from_hex("01"), Ok(vec![1]));
    assert_eq!(from_hex("ff"), Ok(vec![255]));
    assert_eq!(from_hex("A0"), Ok(vec![160]));
    assert_eq!(from_hex("A00AFf"), Ok(vec![160, 10, 255]));
}

#[test]
fn test_from_hex_fail() {
    assert_eq!(from_hex("A"), Err("Odd string length in hex encoded value."));
    assert_eq!(from_hex("ABCDEFGH"), Err("Invalid hex characters encountered."));
    assert_eq!(from_hex("+#"), Err("Invalid hex characters encountered."));
}

#[test]
fn test_to_base64_rfc4648() {
   assert_eq!(to_base64([]), String::from_str(""));
   assert_eq!(to_base64(b"f"), String::from_str("Zg=="));
   assert_eq!(to_base64(b"fo"), String::from_str("Zm8="));
   assert_eq!(to_base64(b"foo"), String::from_str("Zm9v"));
   assert_eq!(to_base64(b"foob"), String::from_str("Zm9vYg=="));
   assert_eq!(to_base64(b"fooba"), String::from_str("Zm9vYmE="));
   assert_eq!(to_base64(b"foobar"), String::from_str("Zm9vYmFy"));
}

#[test]
fn test_to_hex_basics() {
    assert_eq!(to_hex([]), "".to_string());
    assert_eq!(to_hex([0]), "00".to_string());
    assert_eq!(to_hex([1]), "01".to_string());
    assert_eq!(to_hex([16]), "10".to_string());
    assert_eq!(to_hex([255]), "ff".to_string());
    assert_eq!(to_hex([255,1]), "ff01".to_string());
}
<|endoftext|>