<commit_before>use std::path::Path;

#[macro_use] extern crate clap;

extern crate image;

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate onmf;
use onmf::helpers::Array2D;

// `name` and `long` have the same lifetime
fn named_usize_arg<'n, 'h, 'g, 'p, 'r>(name: &'n str, help: &'h str) -> clap::Arg<'n, 'n, 'h, 'g, 'p, 'r> {
    // we don't own `name` but we now own `error_message`
    // which contains `name`.
    let error_message = format!(
        "value provided for argument `{}` is not a valid unsigned integer number",
        name);
    clap::Arg::with_name(name)
         .long(name)
         .help(help)
         // `move` makes it such that the  closure owns `error_message`
         .validator(move |val| {
             match val.parse::<usize>() {
                 Ok(_) => Ok(()),
                 // the closure owns `error_message`.
                 // we can't move `error_message` out of the closure.
                 // we have to clone it instead.
                 Err(_) => Err(error_message.clone())
             }
         })
         .takes_value(true)
}

fn main() {
    let default_nhidden: usize = 10;
    let help_nhidden = format!("number of hidden (latent) variables to find (defaults to `{}`)", default_nhidden);

    let help_input_image_path = "path to image on the the grayscale amounts in the columns of which the NMF should be applied";

    let matches =
        clap::App::new("image-columns-nmf")
            .version(&crate_version!()[..])
            .about("applies NMF on the grayscale amounts of the columns of an image")
            .arg(clap::Arg::with_name("input-image-path")
                 .index(1)
                 .help(&help_input_image_path)
                 .required(true))
            .arg(named_usize_arg("nhidden", &help_nhidden))
            .get_matches();

    let nhidden: usize = value_t!(matches.value_of("nhidden"), usize).unwrap_or(default_nhidden);
    let input_image_path_string = matches.value_of("input-image-path").unwrap();
    let input_image_path = Path::new(input_image_path_string);

    println!("nhidden = {}", nhidden);
    println!("input_image_path = {:?}", input_image_path);
    println!("input_image_path.parent() = {:?}", input_image_path.parent());
    println!("input_image_path.file_name() = {:?}", input_image_path.file_name());
    println!("input_image_path.file_stem() = {:?}", input_image_path.file_stem());
    println!("input_image_path.extension() = {:?}", input_image_path.extension());

    // let mut input_image_file = std::fs::File::open(&input_image_path).unwrap();

    let image = image::open(&input_image_path).unwrap();

    // to grayscale
    let image_luma = image.to_luma();

    println!("image_luma.dimensions() = {:?}", image_luma.dimensions());
    let (width, height) = image_luma.dimensions();

    let nobserved = height as usize;
    let nsamples = width as usize;
    println!("nobserved = {}", nobserved);
    println!("nsamples = {}", nsamples);

    // the indexing of image_array is reversed in respect to image_luma
    let mut samples = Array2D::<f32>::zeros((nsamples, nobserved));

    for (x, y, pixel) in image_luma.enumerate_pixels() {
        let index = (x as usize, y as usize);

        // convert from 0-255 to 0.-1.
        samples[index] = (pixel[0] as f32) / 255.;
    }

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut ortho_nmf = onmf::OrthogonalNMFBlas::new_random01(
        nhidden, nobserved, nsamples, &mut rng);

    // TODO iterate nmf
}
<commit_msg>finish src/bin/image-columns-nmf<commit_after>use std::path::Path;

#[macro_use]
extern crate clap;

extern crate num;
use num::{Float, Zero};

extern crate image;

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate rblas;
use rblas::{Gemm, Matrix};
use rblas::attribute::Transpose;

extern crate ndarray;
use ndarray::{Si, S};
use ndarray::blas::{BlasArrayViewMut, AsBlas};

extern crate nalgebra;
use nalgebra::{DMat};

extern crate onmf;
use onmf::helpers::Array2D;
use onmf::helpers::{ToImage, Normalize, magnify};

// `name` and `long` have the same lifetime
fn named_usize_arg<'n, 'h, 'g, 'p, 'r>(name: &'n str, help: &'h str) -> clap::Arg<'n, 'n, 'h, 'g, 'p, 'r> {
    // we don't own `name` but we now own `error_message`
    // which contains `name`.
    let error_message = format!(
        "value provided for argument `{}` is not a valid unsigned integer number",
        name);
    clap::Arg::with_name(name)
         .long(name)
         .help(help)
         // `move` makes it such that the  closure owns `error_message`
         .validator(move |val| {
             match val.parse::<usize>() {
                 Ok(_) => Ok(()),
                 // the closure owns `error_message`.
                 // we can't move `error_message` out of the closure.
                 // we have to clone it instead.
                 Err(_) => Err(error_message.clone())
             }
         })
         .takes_value(true)
}

fn main() {
    let default_nhidden: usize = 10;
    let help_nhidden = format!("number of hidden (latent) variables to find (defaults to `{}`)", default_nhidden);

    let help_input_image_path = "path to image on the the grayscale amounts in the columns of which the NMF should be applied";

    let matches =
        clap::App::new("image-columns-nmf")
            .version(&crate_version!()[..])
            .about("applies NMF on the grayscale amounts of the columns of an image")
            .arg(clap::Arg::with_name("input-image-path")
                 .index(1)
                 .help(&help_input_image_path)
                 .required(true))
            .arg(named_usize_arg("nhidden", &help_nhidden))
            .get_matches();

    let nhidden: usize = value_t!(matches.value_of("nhidden"), usize).unwrap_or(default_nhidden);
    let input_image_path_string = matches.value_of("input-image-path").unwrap();
    let input_image_path = Path::new(input_image_path_string);

    println!("nhidden = {}", nhidden);
    println!("input_image_path = {:?}", input_image_path);
    println!("input_image_path.parent() = {:?}", input_image_path.parent());
    println!("input_image_path.file_name() = {:?}", input_image_path.file_name());
    println!("input_image_path.file_stem() = {:?}", input_image_path.file_stem());
    println!("input_image_path.extension() = {:?}", input_image_path.extension());

    // let mut input_image_file = std::fs::File::open(&input_image_path).unwrap();

    let image = image::open(&input_image_path).unwrap();

    // to grayscale
    let image_luma = image.to_luma();

    println!("image_luma.dimensions() = {:?}", image_luma.dimensions());
    let (width, height) = image_luma.dimensions();

    let nobserved = height as usize;
    let nsamples = width as usize;
    println!("nobserved = {}", nobserved);
    println!("nsamples = {}", nsamples);

    // the indexing of image_array is reversed in respect to image_luma
    let mut samples = Array2D::<f32>::zeros((nsamples, nobserved));

    for (x, y, pixel) in image_luma.enumerate_pixels() {
        let index = (x as usize, y as usize);

        // convert from 0-255 to 0.-1.
        samples[index] = (pixel[0] as f32) / 255.;
    }

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let mut ortho_nmf = onmf::OrthogonalNMFBlas::new_random01(
        nhidden, nobserved, nsamples, &mut rng);

    let mut reconstruction = Array2D::<f32>::zeros(
        ortho_nmf.samples_shape());

    let mut iteration: i32 = 0;
    loop {
        let alpha: f32 = 0.1 * 1.01.powi(iteration);

        ortho_nmf.iterate(alpha, &mut samples);

        if iteration % 10 == 0 {
            println!("iteration = {} alpha = {}", iteration, alpha);

            // read testimage out of each row of nmf.hidden
            for ihidden in 0..nhidden {
                let i = ihidden as isize;
                let mut coefficients: Array2D<f32> =
                    ortho_nmf.weights
                        .slice(&[S, Si(i, Some(i + 1), 1)])
                       .to_owned();
                let mut base: Array2D<f32> =
                    ortho_nmf.hidden
                        .slice(&[Si(i, Some(i + 1), 1), S])
                        .to_owned();
                Gemm::gemm(
                    &1.,
                    Transpose::NoTrans, &coefficients.blas(),
                    Transpose::NoTrans, &base.blas(),
                    &0.,
                    &mut reconstruction.blas());

                let mut image = DMat::<f32>::new_zeros(
                    nobserved, nsamples);
                for ((row, col), val) in reconstruction.indexed_iter() {
                    image[(col, row)] = val.clone();
                }
                image.normalize()
                    .save_to_png(&format!("image-unmix-{}.png", ihidden)[..]).unwrap();
            }
        }

        iteration += 1;
    }
}
<|endoftext|>


<commit_before>//! Points on the 2D character grid.

use XY;
use num::traits::Zero;
use std::cmp::{Ordering, max, min};

use std::ops::{Add, Div, Mul, Sub};

/// Simple 2D size, in cells.
///
/// Note: due to a bug in rustdoc ([#32077]), the documentation for `Vec2` is
/// currently shown on the [`XY`] page.
///
/// [#32077]: https://github.com/rust-lang/rust/issues/32077
/// [`XY`]: ../struct.XY.html
pub type Vec2 = XY<usize>;

impl PartialOrd for XY<usize> {
    /// `a < b` <=> `a.x < b.x && a.y < b.y`
    fn partial_cmp(&self, other: &Vec2) -> Option<Ordering> {
        if self == other {
            Some(Ordering::Equal)
        } else if self.x < other.x && self.y < other.y {
            Some(Ordering::Less)
        } else if self.x > other.x && self.y > other.y {
            Some(Ordering::Greater)
        } else {
            None
        }
    }
}

impl XY<usize> {
    /// Saturating subtraction. Computes `self - other`, saturating at 0.
    ///
    /// Never panics.
    pub fn saturating_sub<O: Into<Self>>(&self, other: O) -> Self {
        let other = other.into();
        Self::new(self.x.saturating_sub(other.x),
                  self.y.saturating_sub(other.y))
    }

    /// Checked subtraction. Computes `self - other` if possible.
    ///
    /// Returns `None` if `self.x < other.x || self.y < other.y`.
    ///
    /// Never panics.
    pub fn checked_sub<O: Into<Self>>(&self, other: O) -> Option<Self> {
        let other = other.into();
        if self.fits(other) {
            Some(*self - other)
        } else {
            None
        }
    }

    /// Returns a `XY<isize>` from `self`.
    pub fn signed(self) -> XY<isize> {
        self.into()
    }
}

impl<T: Ord> XY<T> {
    /// Returns `true` if `self` could fit inside `other`.
    ///
    /// Shortcut for `self.x <= other.x && self.y <= other.y`.
    ///
    /// If this returns `true`, then `other - self` will not underflow.
    pub fn fits_in<O: Into<Self>>(&self, other: O) -> bool {
        let other = other.into();
        self.x <= other.x && self.y <= other.y
    }

    /// Returns `true` if `other` could fit inside `self`.
    ///
    /// Shortcut for `self.x >= other.x && self.y >= other.y`.
    ///
    /// If this returns `true`, then `self - other` will not underflow.
    pub fn fits<O: Into<Self>>(&self, other: O) -> bool {
        let other = other.into();
        self.x >= other.x && self.y >= other.y
    }

    /// Returns a new Vec2 that is a maximum per coordinate.
    pub fn max<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
        let a = a.into();
        let b = b.into();
        a.zip_map(b, max)
    }

    /// Returns a new Vec2 that is no larger than any input in both dimensions.
    pub fn min<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
        let a = a.into();
        let b = b.into();
        a.zip_map(b, min)
    }

    /// Returns the minimum of `self` and `other`.
    pub fn or_min<O: Into<XY<T>>>(self, other: O) -> Self {
        Self::min(self, other)
    }

    /// Returns the maximum of `self` and `other`.
    pub fn or_max<O: Into<XY<T>>>(self, other: O) -> Self {
        Self::max(self, other)
    }
}

impl<T: Ord + Add<Output = T> + Clone> XY<T> {
    /// Returns (max(self.x,other.x), self.y+other.y)
    pub fn stack_vertical(&self, other: &Self) -> Self {
        Self::new(max(self.x.clone(), other.x.clone()),
                  self.y.clone() + other.y.clone())
    }

    /// Returns (self.x+other.x, max(self.y,other.y))
    pub fn stack_horizontal(&self, other: &Self) -> Self {
        Self::new(self.x.clone() + other.x.clone(),
                  max(self.y.clone(), other.y.clone()))
    }
}

impl<T: Zero + Clone> XY<T> {
    /// Returns a vector with the X component of self, and y=0.
    pub fn keep_x(&self) -> Self {
        Self::new(self.x.clone(), T::zero())
    }

    /// Returns a vector with the Y component of self, and x=0.
    pub fn keep_y(&self) -> Self {
        Self::new(T::zero(), self.y.clone())
    }

    /// Alias for `Self::new(0,0)`.
    pub fn zero() -> Self {
        Self::new(T::zero(), T::zero())
    }
}

impl<T: Into<XY<usize>>> From<T> for XY<isize> {
    fn from(t: T) -> Self {
        let other = t.into();
        Self::new(other.x as isize, other.y as isize)
    }
}

impl From<(i32, i32)> for XY<usize> {
    fn from((x, y): (i32, i32)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl From<(u32, u32)> for XY<usize> {
    fn from((x, y): (u32, u32)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl From<(u8, u8)> for XY<usize> {
    fn from((x, y): (u8, u8)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl<T: Add<Output = T>, O: Into<XY<T>>> Add<O> for XY<T> {
    type Output = Self;

    fn add(self, other: O) -> Self {
        self.zip_map(other.into(), Add::add)
    }
}

impl<T: Sub<Output = T>, O: Into<XY<T>>> Sub<O> for XY<T> {
    type Output = Self;

    fn sub(self, other: O) -> Self {
        self.zip_map(other.into(), Sub::sub)
    }
}

impl<T: Clone + Div<Output = T>> Div<T> for XY<T> {
    type Output = Self;

    fn div(self, other: T) -> Self {
        self.map(|s| s / other.clone())
    }
}

impl Mul<usize> for XY<usize> {
    type Output = Vec2;

    fn mul(self, other: usize) -> Vec2 {
        self.map(|s| s * other)
    }
}

/// Four values representing each direction.
#[derive(Clone,Copy)]
pub struct Vec4 {
    /// Left margin
    pub left: usize,
    /// Right margin
    pub right: usize,
    /// Top margin
    pub top: usize,
    /// Bottom margin
    pub bottom: usize,
}

impl Vec4 {
    /// Creates a new Vec4.
    pub fn new(left: usize, right: usize, top: usize, bottom: usize) -> Self {
        Vec4 {
            left: left,
            right: right,
            top: top,
            bottom: bottom,
        }
    }

    /// Returns left + right.
    pub fn horizontal(&self) -> usize {
        self.left + self.right
    }

    /// Returns top + bottom.
    pub fn vertical(&self) -> usize {
        self.top + self.bottom
    }

    /// Returns (left+right, top+bottom).
    pub fn combined(&self) -> Vec2 {
        Vec2::new(self.horizontal(), self.vertical())
    }

    /// Returns (left, top).
    pub fn top_left(&self) -> Vec2 {
        Vec2::new(self.left, self.top)
    }

    /// Returns (right, bottom).
    pub fn bot_right(&self) -> Vec2 {
        Vec2::new(self.right, self.bottom)
    }
}

impl From<(usize, usize, usize, usize)> for Vec4 {
    fn from((left, right, top, bottom): (usize, usize, usize, usize)) -> Vec4 {
        Vec4::new(left, right, top, bottom)
    }
}

impl From<(i32, i32, i32, i32)> for Vec4 {
    fn from((left, right, top, bottom): (i32, i32, i32, i32)) -> Vec4 {
        (left as usize, right as usize, top as usize, bottom as usize).into()
    }
}

impl From<((i32, i32), (i32, i32))> for Vec4 {
    fn from(((left, right), (top, bottom)): ((i32, i32), (i32, i32))) -> Vec4 {
        (left, right, top, bottom).into()
    }
}
impl From<((usize, usize), (usize, usize))> for Vec4 {
    fn from(((left, right), (top, bottom)): ((usize, usize), (usize, usize)))
            -> Vec4 {
        (left, right, top, bottom).into()
    }
}

impl<T: Into<Vec4>> Add<T> for Vec4 {
    type Output = Vec4;

    fn add(self, other: T) -> Vec4 {
        let ov = other.into();

        Vec4 {
            left: self.left + ov.left,
            right: self.right + ov.right,
            top: self.top + ov.top,
            bottom: self.bottom + ov.bottom,
        }
    }
}

impl<T: Into<Vec4>> Sub<T> for Vec4 {
    type Output = Vec4;

    fn sub(self, other: T) -> Vec4 {
        let ov = other.into();

        Vec4 {
            left: self.left - ov.left,
            right: self.right - ov.right,
            top: self.top - ov.top,
            bottom: self.bottom - ov.bottom,
        }
    }
}

impl Div<usize> for Vec4 {
    type Output = Vec4;

    fn div(self, other: usize) -> Vec4 {
        Vec4 {
            left: self.left / other,
            right: self.right / other,
            top: self.top / other,
            bottom: self.bottom / other,
        }
    }
}

impl Mul<usize> for Vec4 {
    type Output = Vec4;

    fn mul(self, other: usize) -> Vec4 {
        Vec4 {
            left: self.left * other,
            right: self.right * other,
            top: self.top * other,
            bottom: self.bottom * other,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Vec2;

    #[test]
    fn test_from() {
        let vi32 = Vec2::from((4i32, 5i32));
        let vu32 = Vec2::from((4u32, 5u32));

        let vusize = Vec2::from((4usize, 5usize));
        let vvec = Vec2::from(Vec2::new(4, 5));

        assert_eq!(vi32 - vu32, vusize - vvec);
    }
}
<commit_msg>Implement From<(u16,u16)> for Vec2<commit_after>//! Points on the 2D character grid.

use XY;
use num::traits::Zero;
use std::cmp::{Ordering, max, min};

use std::ops::{Add, Div, Mul, Sub};

/// Simple 2D size, in cells.
///
/// Note: due to a bug in rustdoc ([#32077]), the documentation for `Vec2` is
/// currently shown on the [`XY`] page.
///
/// [#32077]: https://github.com/rust-lang/rust/issues/32077
/// [`XY`]: ../struct.XY.html
pub type Vec2 = XY<usize>;

impl PartialOrd for XY<usize> {
    /// `a < b` <=> `a.x < b.x && a.y < b.y`
    fn partial_cmp(&self, other: &Vec2) -> Option<Ordering> {
        if self == other {
            Some(Ordering::Equal)
        } else if self.x < other.x && self.y < other.y {
            Some(Ordering::Less)
        } else if self.x > other.x && self.y > other.y {
            Some(Ordering::Greater)
        } else {
            None
        }
    }
}

impl XY<usize> {
    /// Saturating subtraction. Computes `self - other`, saturating at 0.
    ///
    /// Never panics.
    pub fn saturating_sub<O: Into<Self>>(&self, other: O) -> Self {
        let other = other.into();
        Self::new(self.x.saturating_sub(other.x),
                  self.y.saturating_sub(other.y))
    }

    /// Checked subtraction. Computes `self - other` if possible.
    ///
    /// Returns `None` if `self.x < other.x || self.y < other.y`.
    ///
    /// Never panics.
    pub fn checked_sub<O: Into<Self>>(&self, other: O) -> Option<Self> {
        let other = other.into();
        if self.fits(other) {
            Some(*self - other)
        } else {
            None
        }
    }

    /// Returns a `XY<isize>` from `self`.
    pub fn signed(self) -> XY<isize> {
        self.into()
    }
}

impl<T: Ord> XY<T> {
    /// Returns `true` if `self` could fit inside `other`.
    ///
    /// Shortcut for `self.x <= other.x && self.y <= other.y`.
    ///
    /// If this returns `true`, then `other - self` will not underflow.
    pub fn fits_in<O: Into<Self>>(&self, other: O) -> bool {
        let other = other.into();
        self.x <= other.x && self.y <= other.y
    }

    /// Returns `true` if `other` could fit inside `self`.
    ///
    /// Shortcut for `self.x >= other.x && self.y >= other.y`.
    ///
    /// If this returns `true`, then `self - other` will not underflow.
    pub fn fits<O: Into<Self>>(&self, other: O) -> bool {
        let other = other.into();
        self.x >= other.x && self.y >= other.y
    }

    /// Returns a new Vec2 that is a maximum per coordinate.
    pub fn max<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
        let a = a.into();
        let b = b.into();
        a.zip_map(b, max)
    }

    /// Returns a new Vec2 that is no larger than any input in both dimensions.
    pub fn min<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
        let a = a.into();
        let b = b.into();
        a.zip_map(b, min)
    }

    /// Returns the minimum of `self` and `other`.
    pub fn or_min<O: Into<XY<T>>>(self, other: O) -> Self {
        Self::min(self, other)
    }

    /// Returns the maximum of `self` and `other`.
    pub fn or_max<O: Into<XY<T>>>(self, other: O) -> Self {
        Self::max(self, other)
    }
}

impl<T: Ord + Add<Output = T> + Clone> XY<T> {
    /// Returns (max(self.x,other.x), self.y+other.y)
    pub fn stack_vertical(&self, other: &Self) -> Self {
        Self::new(max(self.x.clone(), other.x.clone()),
                  self.y.clone() + other.y.clone())
    }

    /// Returns (self.x+other.x, max(self.y,other.y))
    pub fn stack_horizontal(&self, other: &Self) -> Self {
        Self::new(self.x.clone() + other.x.clone(),
                  max(self.y.clone(), other.y.clone()))
    }
}

impl<T: Zero + Clone> XY<T> {
    /// Returns a vector with the X component of self, and y=0.
    pub fn keep_x(&self) -> Self {
        Self::new(self.x.clone(), T::zero())
    }

    /// Returns a vector with the Y component of self, and x=0.
    pub fn keep_y(&self) -> Self {
        Self::new(T::zero(), self.y.clone())
    }

    /// Alias for `Self::new(0,0)`.
    pub fn zero() -> Self {
        Self::new(T::zero(), T::zero())
    }
}

impl<T: Into<XY<usize>>> From<T> for XY<isize> {
    fn from(t: T) -> Self {
        let other = t.into();
        Self::new(other.x as isize, other.y as isize)
    }
}

impl From<(i32, i32)> for XY<usize> {
    fn from((x, y): (i32, i32)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl From<(u32, u32)> for XY<usize> {
    fn from((x, y): (u32, u32)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl From<(u8, u8)> for XY<usize> {
    fn from((x, y): (u8, u8)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl From<(u16, u16)> for XY<usize> {
    fn from((x, y): (u16, u16)) -> Self {
        (x as usize, y as usize).into()
    }
}

impl<T: Add<Output = T>, O: Into<XY<T>>> Add<O> for XY<T> {
    type Output = Self;

    fn add(self, other: O) -> Self {
        self.zip_map(other.into(), Add::add)
    }
}

impl<T: Sub<Output = T>, O: Into<XY<T>>> Sub<O> for XY<T> {
    type Output = Self;

    fn sub(self, other: O) -> Self {
        self.zip_map(other.into(), Sub::sub)
    }
}

impl<T: Clone + Div<Output = T>> Div<T> for XY<T> {
    type Output = Self;

    fn div(self, other: T) -> Self {
        self.map(|s| s / other.clone())
    }
}

impl Mul<usize> for XY<usize> {
    type Output = Vec2;

    fn mul(self, other: usize) -> Vec2 {
        self.map(|s| s * other)
    }
}

/// Four values representing each direction.
#[derive(Clone,Copy)]
pub struct Vec4 {
    /// Left margin
    pub left: usize,
    /// Right margin
    pub right: usize,
    /// Top margin
    pub top: usize,
    /// Bottom margin
    pub bottom: usize,
}

impl Vec4 {
    /// Creates a new Vec4.
    pub fn new(left: usize, right: usize, top: usize, bottom: usize) -> Self {
        Vec4 {
            left: left,
            right: right,
            top: top,
            bottom: bottom,
        }
    }

    /// Returns left + right.
    pub fn horizontal(&self) -> usize {
        self.left + self.right
    }

    /// Returns top + bottom.
    pub fn vertical(&self) -> usize {
        self.top + self.bottom
    }

    /// Returns (left+right, top+bottom).
    pub fn combined(&self) -> Vec2 {
        Vec2::new(self.horizontal(), self.vertical())
    }

    /// Returns (left, top).
    pub fn top_left(&self) -> Vec2 {
        Vec2::new(self.left, self.top)
    }

    /// Returns (right, bottom).
    pub fn bot_right(&self) -> Vec2 {
        Vec2::new(self.right, self.bottom)
    }
}

impl From<(usize, usize, usize, usize)> for Vec4 {
    fn from((left, right, top, bottom): (usize, usize, usize, usize)) -> Vec4 {
        Vec4::new(left, right, top, bottom)
    }
}

impl From<(i32, i32, i32, i32)> for Vec4 {
    fn from((left, right, top, bottom): (i32, i32, i32, i32)) -> Vec4 {
        (left as usize, right as usize, top as usize, bottom as usize).into()
    }
}

impl From<((i32, i32), (i32, i32))> for Vec4 {
    fn from(((left, right), (top, bottom)): ((i32, i32), (i32, i32))) -> Vec4 {
        (left, right, top, bottom).into()
    }
}
impl From<((usize, usize), (usize, usize))> for Vec4 {
    fn from(((left, right), (top, bottom)): ((usize, usize), (usize, usize)))
            -> Vec4 {
        (left, right, top, bottom).into()
    }
}

impl<T: Into<Vec4>> Add<T> for Vec4 {
    type Output = Vec4;

    fn add(self, other: T) -> Vec4 {
        let ov = other.into();

        Vec4 {
            left: self.left + ov.left,
            right: self.right + ov.right,
            top: self.top + ov.top,
            bottom: self.bottom + ov.bottom,
        }
    }
}

impl<T: Into<Vec4>> Sub<T> for Vec4 {
    type Output = Vec4;

    fn sub(self, other: T) -> Vec4 {
        let ov = other.into();

        Vec4 {
            left: self.left - ov.left,
            right: self.right - ov.right,
            top: self.top - ov.top,
            bottom: self.bottom - ov.bottom,
        }
    }
}

impl Div<usize> for Vec4 {
    type Output = Vec4;

    fn div(self, other: usize) -> Vec4 {
        Vec4 {
            left: self.left / other,
            right: self.right / other,
            top: self.top / other,
            bottom: self.bottom / other,
        }
    }
}

impl Mul<usize> for Vec4 {
    type Output = Vec4;

    fn mul(self, other: usize) -> Vec4 {
        Vec4 {
            left: self.left * other,
            right: self.right * other,
            top: self.top * other,
            bottom: self.bottom * other,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Vec2;

    #[test]
    fn test_from() {
        let vi32 = Vec2::from((4i32, 5i32));
        let vu32 = Vec2::from((4u32, 5u32));

        let vusize = Vec2::from((4usize, 5usize));
        let vvec = Vec2::from(Vec2::new(4, 5));

        assert_eq!(vi32 - vu32, vusize - vvec);
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::ptr;

use ffi;
use libc;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

use InsideCallback;
use LuaTable;

// Called when an object inside Lua is being dropped.
#[inline]
extern "C" fn destructor_wrapper<T>(lua: *mut ffi::lua_State) -> libc::c_int {
    unsafe {
        let obj = ffi::lua_touserdata(lua, -1);
        ptr::drop_in_place(obj as *mut TypeId);
        ptr::drop_in_place((obj as *mut u8).offset(mem::size_of::<TypeId>() as isize) as *mut T);
        0
    }
}

/// Pushes an object as a user data.
///
/// In Lua, a user data is anything that is not recognized by Lua. When the script attempts to
/// copy a user data, instead only a reference to the data is copied.
///
/// The way a Lua script can use the user data depends on the content of the **metatable**, which
/// is a Lua table linked to the object.
///
/// [See this link for more infos.](http://www.lua.org/manual/5.2/manual.html#2.4)
///
/// # About the Drop trait
///
/// When the Lua context detects that a userdata is no longer needed it calls the function at the
/// `__gc` index in the userdata's metatable, if any. The hlua library will automatically fill this
/// index with a function that invokes the `Drop` trait of the userdata.
///
/// You can replace the function if you wish so, although you are strongly discouraged to do it.
/// It is no unsafe to leak data in Rust, so there is no safety issue in doing so.
///
/// # Arguments
///
///  - `metatable`: Function that fills the metatable of the object.
///
#[inline]
pub fn push_userdata<'lua, L, T, F>(data: T, mut lua: L, mut metatable: F) -> PushGuard<L>
    where F: FnMut(LuaTable<&mut PushGuard<&mut L>>),
          L: AsMutLua<'lua>,
          T: Send + 'static + Any
{
    unsafe {
        let typeid = TypeId::of::<T>();

        let lua_data = {
            let tot_size = mem::size_of_val(&typeid) + mem::size_of_val(&data);
            ffi::lua_newuserdata(lua.as_mut_lua().0, tot_size as libc::size_t)
        };

        // We check the alignment requirements.
        debug_assert_eq!(lua_data as usize % mem::align_of_val(&data), 0);
        // Since the size of a `TypeId` should always be a usize, this assert should pass every
        // time as well.
        debug_assert_eq!(mem::size_of_val(&typeid) % mem::align_of_val(&data), 0);

        // We write the `TypeId` first, and the data right next to it.
        ptr::write(lua_data as *mut TypeId, typeid);
        let data_loc = (lua_data as *const u8).offset(mem::size_of_val(&typeid) as isize);
        ptr::write(data_loc as *mut _, data);

        let lua_raw = lua.as_mut_lua();

        // Creating a metatable.
        ffi::lua_newtable(lua.as_mut_lua().0);

        // Index "__gc" in the metatable calls the object's destructor.

        // TODO: Could use std::intrinsics::needs_drop to avoid that if not needed.
        // After some discussion on IRC, it would be acceptable to add a reexport in libcore
        // without going through the RFC process.
        {
            match "__gc".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };

            ffi::lua_pushcfunction(lua.as_mut_lua().0, destructor_wrapper::<T>);
            ffi::lua_settable(lua.as_mut_lua().0, -3);
        }

        // Calling the metatable closure.
        {
            let raw_lua = lua.as_lua();
            let mut guard = PushGuard {
                lua: &mut lua,
                size: 1,
                raw_lua: raw_lua,
            };
            metatable(LuaRead::lua_read(&mut guard).ok().unwrap());
            guard.forget();
        }

        ffi::lua_setmetatable(lua_raw.0, -2);
    }

    let raw_lua = lua.as_lua();
    PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    }
}

///
#[inline]
pub fn read_userdata<'t, 'c, T>(mut lua: &'c mut InsideCallback,
                                index: i32)
                                -> Result<&'t mut T, &'c mut InsideCallback>
    where T: 'static + Any
{
    unsafe {
        let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
        if data_ptr.is_null() {
            return Err(lua);
        }

        let actual_typeid = data_ptr as *const TypeId;
        if *actual_typeid != TypeId::of::<T>() {
            return Err(lua);
        }

        let data = (data_ptr as *const u8).offset(mem::size_of::<TypeId>() as isize);
        Ok(&mut *(data as *mut T))
    }
}

/// Represents a user data located inside the Lua context.
pub struct UserdataOnStack<T, L> {
    variable: L,
    marker: PhantomData<T>,
}

impl<'lua, T, L> LuaRead<L> for UserdataOnStack<T, L>
    where L: AsMutLua<'lua> + AsLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn lua_read_at_position(lua: L, index: i32) -> Result<UserdataOnStack<T, L>, L> {
        unsafe {
            let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
            if data_ptr.is_null() {
                return Err(lua);
            }

            let actual_typeid = data_ptr as *const TypeId;
            if *actual_typeid != TypeId::of::<T>() {
                return Err(lua);
            }

            Ok(UserdataOnStack {
                variable: lua,
                marker: PhantomData,
            })
        }
    }
}

impl<'lua, T, L> Deref for UserdataOnStack<T, L>
    where L: AsLua<'lua>,
          T: 'lua + Any
{
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        unsafe {
            let base = ffi::lua_touserdata(self.variable.as_lua().0, -1);
            let data = (base as *const u8).offset(mem::size_of::<TypeId>() as isize);
            &*(data as *const T)
        }
    }
}

impl<'lua, T, L> DerefMut for UserdataOnStack<T, L>
    where L: AsMutLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        unsafe {
            let base = ffi::lua_touserdata(self.variable.as_mut_lua().0, -1);
            let data = (base as *const u8).offset(mem::size_of::<TypeId>() as isize);
            &mut *(data as *mut T)
        }
    }
}
<commit_msg>Remove unnecessary FnMut bound<commit_after>use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::ptr;

use ffi;
use libc;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

use InsideCallback;
use LuaTable;

// Called when an object inside Lua is being dropped.
#[inline]
extern "C" fn destructor_wrapper<T>(lua: *mut ffi::lua_State) -> libc::c_int {
    unsafe {
        let obj = ffi::lua_touserdata(lua, -1);
        ptr::drop_in_place(obj as *mut TypeId);
        ptr::drop_in_place((obj as *mut u8).offset(mem::size_of::<TypeId>() as isize) as *mut T);
        0
    }
}

/// Pushes an object as a user data.
///
/// In Lua, a user data is anything that is not recognized by Lua. When the script attempts to
/// copy a user data, instead only a reference to the data is copied.
///
/// The way a Lua script can use the user data depends on the content of the **metatable**, which
/// is a Lua table linked to the object.
///
/// [See this link for more infos.](http://www.lua.org/manual/5.2/manual.html#2.4)
///
/// # About the Drop trait
///
/// When the Lua context detects that a userdata is no longer needed it calls the function at the
/// `__gc` index in the userdata's metatable, if any. The hlua library will automatically fill this
/// index with a function that invokes the `Drop` trait of the userdata.
///
/// You can replace the function if you wish so, although you are strongly discouraged to do it.
/// It is no unsafe to leak data in Rust, so there is no safety issue in doing so.
///
/// # Arguments
///
///  - `metatable`: Function that fills the metatable of the object.
///
#[inline]
pub fn push_userdata<'lua, L, T, F>(data: T, mut lua: L, metatable: F) -> PushGuard<L>
    where F: FnOnce(LuaTable<&mut PushGuard<&mut L>>),
          L: AsMutLua<'lua>,
          T: Send + 'static + Any
{
    unsafe {
        let typeid = TypeId::of::<T>();

        let lua_data = {
            let tot_size = mem::size_of_val(&typeid) + mem::size_of_val(&data);
            ffi::lua_newuserdata(lua.as_mut_lua().0, tot_size as libc::size_t)
        };

        // We check the alignment requirements.
        debug_assert_eq!(lua_data as usize % mem::align_of_val(&data), 0);
        // Since the size of a `TypeId` should always be a usize, this assert should pass every
        // time as well.
        debug_assert_eq!(mem::size_of_val(&typeid) % mem::align_of_val(&data), 0);

        // We write the `TypeId` first, and the data right next to it.
        ptr::write(lua_data as *mut TypeId, typeid);
        let data_loc = (lua_data as *const u8).offset(mem::size_of_val(&typeid) as isize);
        ptr::write(data_loc as *mut _, data);

        let lua_raw = lua.as_mut_lua();

        // Creating a metatable.
        ffi::lua_newtable(lua.as_mut_lua().0);

        // Index "__gc" in the metatable calls the object's destructor.

        // TODO: Could use std::intrinsics::needs_drop to avoid that if not needed.
        // After some discussion on IRC, it would be acceptable to add a reexport in libcore
        // without going through the RFC process.
        {
            match "__gc".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };

            ffi::lua_pushcfunction(lua.as_mut_lua().0, destructor_wrapper::<T>);
            ffi::lua_settable(lua.as_mut_lua().0, -3);
        }

        // Calling the metatable closure.
        {
            let raw_lua = lua.as_lua();
            let mut guard = PushGuard {
                lua: &mut lua,
                size: 1,
                raw_lua: raw_lua,
            };
            metatable(LuaRead::lua_read(&mut guard).ok().unwrap());
            guard.forget();
        }

        ffi::lua_setmetatable(lua_raw.0, -2);
    }

    let raw_lua = lua.as_lua();
    PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    }
}

///
#[inline]
pub fn read_userdata<'t, 'c, T>(mut lua: &'c mut InsideCallback,
                                index: i32)
                                -> Result<&'t mut T, &'c mut InsideCallback>
    where T: 'static + Any
{
    unsafe {
        let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
        if data_ptr.is_null() {
            return Err(lua);
        }

        let actual_typeid = data_ptr as *const TypeId;
        if *actual_typeid != TypeId::of::<T>() {
            return Err(lua);
        }

        let data = (data_ptr as *const u8).offset(mem::size_of::<TypeId>() as isize);
        Ok(&mut *(data as *mut T))
    }
}

/// Represents a user data located inside the Lua context.
pub struct UserdataOnStack<T, L> {
    variable: L,
    marker: PhantomData<T>,
}

impl<'lua, T, L> LuaRead<L> for UserdataOnStack<T, L>
    where L: AsMutLua<'lua> + AsLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn lua_read_at_position(lua: L, index: i32) -> Result<UserdataOnStack<T, L>, L> {
        unsafe {
            let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
            if data_ptr.is_null() {
                return Err(lua);
            }

            let actual_typeid = data_ptr as *const TypeId;
            if *actual_typeid != TypeId::of::<T>() {
                return Err(lua);
            }

            Ok(UserdataOnStack {
                variable: lua,
                marker: PhantomData,
            })
        }
    }
}

impl<'lua, T, L> Deref for UserdataOnStack<T, L>
    where L: AsLua<'lua>,
          T: 'lua + Any
{
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        unsafe {
            let base = ffi::lua_touserdata(self.variable.as_lua().0, -1);
            let data = (base as *const u8).offset(mem::size_of::<TypeId>() as isize);
            &*(data as *const T)
        }
    }
}

impl<'lua, T, L> DerefMut for UserdataOnStack<T, L>
    where L: AsMutLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        unsafe {
            let base = ffi::lua_touserdata(self.variable.as_mut_lua().0, -1);
            let data = (base as *const u8).offset(mem::size_of::<TypeId>() as isize);
            &mut *(data as *mut T)
        }
    }
}
<|endoftext|>


<commit_before>//! Input emulation layer
//!
//! Our input emulation is modeled directly after the SNES hardware: We emulate the 2 controller
//! ports separately, down to the individual wires. `Peripheral`s can be plugged into each and
//! emulate a specific kind of device plugged into the port. The frontends provide the actual input
//! reading implementation.
//!
//! This flexible setup should allow emulating all available peripherals: From the standard joypad
//! to light guns and the multitap.
//!
//! However, nothing is stopping the user from building unusable configurations, such as plugging a
//! light gun into port 1 (this doesn't work because the `IOBit` line of port 1 isn't connected to
//! the PPUs counter latch line). The frontend should warn on these.

mod port;

pub use self::port::Peripheral;

use std::io::{BufRead, Write};
use std::mem;
use std::ops::{Index, IndexMut};

/// Represents the 2 controller ports on the SNES
pub struct Ports(pub Option<Peripheral>, pub Option<Peripheral>);

impl Ports {
    /// Run a closure on each attached peripheral
    fn for_each_peripheral<F>(&mut self, mut f: F) where F: FnMut(&mut Peripheral) {
        if let Some(ref mut peripheral) = self.0 {
            f(peripheral)
        }
        if let Some(ref mut peripheral) = self.1 {
            f(peripheral)
        }
    }
}

impl Index<u8> for Ports {
    type Output = Option<Peripheral>;
    fn index(&self, i: u8) -> &Self::Output {
        match i {
            0 => &self.0,
            1 => &self.1,
            _ => panic!("{} is not a valid controller port index (only 0 and 1 are valid)", i),
        }
    }
}

impl IndexMut<u8> for Ports {
    fn index_mut(&mut self, i: u8) -> &mut Self::Output {
        match i {
            0 => &mut self.0,
            1 => &mut self.1,
            _ => panic!("{} is not a valid controller port index (only 0 and 1 are valid)", i),
        }
    }
}

enum InputMode {
    Normal(Ports),
    Recorded(Ports, Box<Write>),
    Replayed(Box<BufRead>),
}

impl Default for InputMode {
    fn default() -> Self {
        InputMode::Normal(Ports(None, None))
    }
}

/// Controller input management.
#[derive(Default)]
pub struct Input {
    mode: InputMode,

    /// Auto-Joypad Data (`$4218` - `$421f`)
    auto_read_data: [u8; 8],
    /// Current latch state. Peripherals will have `set_latch` called when this changes.
    latch: bool,
    latched_this_frame: bool,
}

impl_save_state!(Input { auto_read_data, latch, latched_this_frame } ignore { mode });

impl Input {
    /// Start recording input to a `Write` implementor, often a file.
    ///
    /// When reading data from a controller port, the recorder will write that data to the given
    /// `Box<Write>`.
    pub fn start_recording(&mut self, w: Box<Write>) {
        assert!(!self.is_recording(), "already recording");
        assert!(!self.is_replaying(), "cannot record while already replaying");

        let old_mode = mem::replace(&mut self.mode, InputMode::default());
        self.mode = match old_mode {
            InputMode::Normal(ports) => InputMode::Recorded(ports, w),
            InputMode::Recorded(..) => panic!("already recording"),
            InputMode::Replayed(_) => panic!("cannot record while already replaying"),
        };
    }

    /// Start replaying input from a recording made with `start_recording`. While replaying, user
    /// input is ignored (but input sources are still updated).
    pub fn start_replay(&mut self, r: Box<BufRead>) {
        assert!(!self.is_replaying(), "already replaying");
        assert!(!self.is_recording(), "cannot start a replay while recording input");

        self.mode = InputMode::Replayed(r);
    }

    /// Gets the `Ports` on the SNES.
    ///
    /// If we're replaying input, this will panic (since no ports actually exist).
    pub fn unwrap_ports(&mut self) -> &mut Ports {
        match self.mode {
            InputMode::Normal(ref mut ports) => ports,
            InputMode::Recorded(ref mut ports, _) => ports,
            InputMode::Replayed(_) => panic!("called Input::unwrap_ports while replaying"),
        }
    }

    pub fn is_recording(&self) -> bool {
        match self.mode {
            InputMode::Recorded(..) => true,
            _ => false,
        }
    }

    pub fn is_replaying(&self) -> bool {
        match self.mode {
            InputMode::Replayed(..) => true,
            _ => false,
        }
    }

    pub fn new_frame(&mut self) {
        if self.latch {
            once!(warn!("latch still active from older frame (might interfere with \
                         recording); latch might be changed by emulator!"));
        }

        if !self.latched_this_frame {
            self.store(0x4016, 1);
            self.store(0x4016, 0);
        }

        self.latched_this_frame = false;
        match self.mode {
            InputMode::Normal(ref mut ports)
            | InputMode::Recorded(ref mut ports, _) => {
                ports.for_each_peripheral(|p| p.next_frame())
            }
            InputMode::Replayed(_) => {}
        }
    }

    /// Read the `Data1` and `Data2` line of a controller port.
    fn read_port(&mut self, port: u8) -> (bool, bool) {
        let data = match self.mode {
            InputMode::Normal(ref mut ports) |
            InputMode::Recorded(ref mut ports, _) => match ports[port] {
                Some(ref mut cpa) => cpa.read_bit(),
                None => (false, false),     // If nothing is attached, we read 0s
            },
            InputMode::Replayed(_) => unimplemented!(),
        };

        data
    }

    /// Read from an input register. Updates the controller state if this is the first load in this
    /// frame.
    pub fn load(&mut self, reg: u16) -> u8 {
        match reg {
            // $4016: JOYSER0 - NES-style Joypad Access Port 1
            // Rd: ------ca (Data2, Data1 line)
            // Wr: -------l (Latch)
            // $4017: JOYSER1 - NES-style Joypad Access Port 2
            // Rd: ---111db (Data2, Data1 line)
            0x4016 | 0x4017 => {
                let (data1, data2) = self.read_port((reg - 0x4016) as u8);
                let value = data1 as u8 | (data2 as u8) << 1;
                if reg == 0x4017 {
                    value | 0b00011100
                } else {
                    value
                }
            }
            0x4218 ... 0x421f => {
                // Read from auto-joypad register
                self.auto_read_data[reg as usize - 0x4218]
            }
            _ => panic!("${:04X} is not an input register", reg)
        }
    }

    /// Store to an input register. Stores to `$4016` can change the latch line.
    pub fn store(&mut self, reg: u16, val: u8) {
        if reg == 0x4016 {
            let new_latch = val & 0x01 != 0;
            if self.latch != new_latch {
                // Latch changed state
                if new_latch {
                    if self.latched_this_frame {
                        once!(warn!("already latched input in this frame! (this might interfere \
                                     with recording)"));
                    }
                    self.latched_this_frame = true;
                }

                match self.mode {
                    InputMode::Normal(ref mut ports) | InputMode::Recorded(ref mut ports, _) => {
                        ports.for_each_peripheral(|p| p.set_latch(new_latch))
                    }
                    InputMode::Replayed(_) => {}
                }

                if new_latch {
                    // Input state was updated. Record it if necessary.
                    if let InputMode::Recorded(_, _) = self.mode {
                        unimplemented!();
                    }
                }

                self.latch = new_latch;
            }
        } else {
            panic!("invalid input reg store to ${:04X}", reg);
        }
    }

    /// Called when auto joypad read is enabled and it's time to do one.
    ///
    /// On the real console, auto joypad read takes place in the first few scanline in V-Blank. We
    /// pretend it's instantaneous and set the auto joypad read bit in `$4212` manually.
    pub fn perform_auto_read(&mut self) {
        // Store 1, then 0 to the latch, latching both ports
        self.store(0x4016, 1);
        self.store(0x4016, 0);

        // Read 16 times (16*4=64 bits=8 bytes) from both ports and store the result in `self.auto_read_data`
        // High bytes first (`JOY1H`/`JOY3H` for port 0, `JOY2H`/`JOY4H` for port 1)
        for _ in 0..8 {
            let (a, b) = self.read_port(0);
            self.auto_read_data[1] <<= 1;       // `JOY1H`
            self.auto_read_data[1] |= a as u8;
            self.auto_read_data[5] <<= 1;       // `JOY3H`
            self.auto_read_data[5] |= b as u8;
            let (a, b) = self.read_port(1);
            self.auto_read_data[3] <<= 1;       // `JOY2H`
            self.auto_read_data[3] |= a as u8;
            self.auto_read_data[7] <<= 1;       // `JOY4H`
            self.auto_read_data[7] |= b as u8;
        }
        // Then the low bytes (`JOY1L`/`JOY3L` for port 0, `JOY2L`/`JOY4L` for port 1)
        for _ in 0..8 {
            let (a, b) = self.read_port(0);
            self.auto_read_data[0] <<= 1;       // `JOY1L`
            self.auto_read_data[0] |= a as u8;
            self.auto_read_data[4] <<= 1;       // `JOY3L`
            self.auto_read_data[4] |= b as u8;
            let (a, b) = self.read_port(1);
            self.auto_read_data[2] <<= 1;       // `JOY2L`
            self.auto_read_data[2] |= a as u8;
            self.auto_read_data[6] <<= 1;       // `JOY4L`
            self.auto_read_data[6] |= b as u8;
        }
    }
}
<commit_msg>More sanity warnings<commit_after>//! Input emulation layer
//!
//! Our input emulation is modeled directly after the SNES hardware: We emulate the 2 controller
//! ports separately, down to the individual wires. `Peripheral`s can be plugged into each and
//! emulate a specific kind of device plugged into the port. The frontends provide the actual input
//! reading implementation.
//!
//! This flexible setup should allow emulating all available peripherals: From the standard joypad
//! to light guns and the multitap.
//!
//! However, nothing is stopping the user from building unusable configurations, such as plugging a
//! light gun into port 1 (this doesn't work because the `IOBit` line of port 1 isn't connected to
//! the PPUs counter latch line). The frontend should warn on these.

mod port;

pub use self::port::Peripheral;

use std::io::{BufRead, Write};
use std::mem;
use std::ops::{Index, IndexMut};

/// Represents the 2 controller ports on the SNES
pub struct Ports(pub Option<Peripheral>, pub Option<Peripheral>);

impl Ports {
    /// Run a closure on each attached peripheral
    fn for_each_peripheral<F>(&mut self, mut f: F) where F: FnMut(&mut Peripheral) {
        if let Some(ref mut peripheral) = self.0 {
            f(peripheral)
        }
        if let Some(ref mut peripheral) = self.1 {
            f(peripheral)
        }
    }
}

impl Index<u8> for Ports {
    type Output = Option<Peripheral>;
    fn index(&self, i: u8) -> &Self::Output {
        match i {
            0 => &self.0,
            1 => &self.1,
            _ => panic!("{} is not a valid controller port index (only 0 and 1 are valid)", i),
        }
    }
}

impl IndexMut<u8> for Ports {
    fn index_mut(&mut self, i: u8) -> &mut Self::Output {
        match i {
            0 => &mut self.0,
            1 => &mut self.1,
            _ => panic!("{} is not a valid controller port index (only 0 and 1 are valid)", i),
        }
    }
}

enum InputMode {
    Normal(Ports),
    Recorded(Ports, Box<Write>),
    Replayed(Box<BufRead>),
}

impl Default for InputMode {
    fn default() -> Self {
        InputMode::Normal(Ports(None, None))
    }
}

/// Controller input management.
#[derive(Default)]
pub struct Input {
    mode: InputMode,

    /// Auto-Joypad Data (`$4218` - `$421f`)
    auto_read_data: [u8; 8],
    /// Current latch state. Peripherals will have `set_latch` called when this changes.
    latch: bool,
    latched_this_frame: bool,
}

impl_save_state!(Input { auto_read_data, latch, latched_this_frame } ignore { mode });

impl Input {
    /// Start recording input to a `Write` implementor, often a file.
    ///
    /// When reading data from a controller port, the recorder will write that data to the given
    /// `Box<Write>`.
    pub fn start_recording(&mut self, w: Box<Write>) {
        assert!(!self.is_recording(), "already recording");
        assert!(!self.is_replaying(), "cannot record while already replaying");

        let old_mode = mem::replace(&mut self.mode, InputMode::default());
        self.mode = match old_mode {
            InputMode::Normal(ports) => InputMode::Recorded(ports, w),
            InputMode::Recorded(..) => panic!("already recording"),
            InputMode::Replayed(_) => panic!("cannot record while already replaying"),
        };
    }

    /// Start replaying input from a recording made with `start_recording`. While replaying, user
    /// input is ignored (but input sources are still updated).
    pub fn start_replay(&mut self, r: Box<BufRead>) {
        assert!(!self.is_replaying(), "already replaying");
        assert!(!self.is_recording(), "cannot start a replay while recording input");

        self.mode = InputMode::Replayed(r);
    }

    /// Gets the `Ports` on the SNES.
    ///
    /// If we're replaying input, this will panic (since no ports actually exist).
    pub fn unwrap_ports(&mut self) -> &mut Ports {
        match self.mode {
            InputMode::Normal(ref mut ports) => ports,
            InputMode::Recorded(ref mut ports, _) => ports,
            InputMode::Replayed(_) => panic!("called Input::unwrap_ports while replaying"),
        }
    }

    pub fn is_recording(&self) -> bool {
        match self.mode {
            InputMode::Recorded(..) => true,
            _ => false,
        }
    }

    pub fn is_replaying(&self) -> bool {
        match self.mode {
            InputMode::Replayed(..) => true,
            _ => false,
        }
    }

    pub fn new_frame(&mut self) {
        if self.latch {
            once!(warn!("latch still active from older frame (might interfere with \
                         recording); latch might be changed by emulator!"));
        }

        if !self.latched_this_frame {
            self.store(0x4016, 1);
            self.store(0x4016, 0);
        }

        self.latched_this_frame = false;
        match self.mode {
            InputMode::Normal(ref mut ports)
            | InputMode::Recorded(ref mut ports, _) => {
                ports.for_each_peripheral(|p| p.next_frame())
            }
            InputMode::Replayed(_) => {}
        }
    }

    /// Read the `Data1` and `Data2` line of a controller port.
    fn read_port(&mut self, port: u8) -> (bool, bool) {
        let data = match self.mode {
            InputMode::Normal(ref mut ports) |
            InputMode::Recorded(ref mut ports, _) => match ports[port] {
                Some(ref mut cpa) => {
                    if !self.latched_this_frame {
                        once!(warn!("reading data lines without prior latching (this can interfere \
                                     with input recording)"));
                    }

                    cpa.read_bit()
                }
                None => (false, false),     // If nothing is attached, we read 0s
            },
            InputMode::Replayed(_) => unimplemented!(),
        };

        data
    }

    /// Read from an input register. Updates the controller state if this is the first load in this
    /// frame.
    pub fn load(&mut self, reg: u16) -> u8 {
        match reg {
            // $4016: JOYSER0 - NES-style Joypad Access Port 1
            // Rd: ------ca (Data2, Data1 line)
            // Wr: -------l (Latch)
            // $4017: JOYSER1 - NES-style Joypad Access Port 2
            // Rd: ---111db (Data2, Data1 line)
            0x4016 | 0x4017 => {
                let (data1, data2) = self.read_port((reg - 0x4016) as u8);
                let value = data1 as u8 | (data2 as u8) << 1;
                if reg == 0x4017 {
                    value | 0b00011100
                } else {
                    value
                }
            }
            0x4218 ... 0x421f => {
                // Read from auto-joypad register
                self.auto_read_data[reg as usize - 0x4218]
            }
            _ => panic!("${:04X} is not an input register", reg)
        }
    }

    /// Store to an input register. Stores to `$4016` can change the latch line.
    pub fn store(&mut self, reg: u16, val: u8) {
        if reg == 0x4016 {
            let new_latch = val & 0x01 != 0;
            if self.latch != new_latch {
                // Latch changed state
                if new_latch {
                    if self.latched_this_frame {
                        once!(warn!("already latched input in this frame! (this might interfere \
                                     with recording)"));
                    }
                    self.latched_this_frame = true;
                }

                match self.mode {
                    InputMode::Normal(ref mut ports) | InputMode::Recorded(ref mut ports, _) => {
                        ports.for_each_peripheral(|p| p.set_latch(new_latch))
                    }
                    InputMode::Replayed(_) => {}
                }

                if new_latch {
                    // Input state was updated. Record it if necessary.
                    if let InputMode::Recorded(_, _) = self.mode {
                        unimplemented!();
                    }
                }

                self.latch = new_latch;
            }
        } else {
            panic!("invalid input reg store to ${:04X}", reg);
        }
    }

    /// Called when auto joypad read is enabled and it's time to do one.
    ///
    /// On the real console, auto joypad read takes place in the first few scanline in V-Blank. We
    /// pretend it's instantaneous and set the auto joypad read bit in `$4212` manually.
    pub fn perform_auto_read(&mut self) {
        // Store 1, then 0 to the latch, latching both ports
        self.store(0x4016, 1);
        self.store(0x4016, 0);

        // Read 16 times (16*4=64 bits=8 bytes) from both ports and store the result in `self.auto_read_data`
        // High bytes first (`JOY1H`/`JOY3H` for port 0, `JOY2H`/`JOY4H` for port 1)
        for _ in 0..8 {
            let (a, b) = self.read_port(0);
            self.auto_read_data[1] <<= 1;       // `JOY1H`
            self.auto_read_data[1] |= a as u8;
            self.auto_read_data[5] <<= 1;       // `JOY3H`
            self.auto_read_data[5] |= b as u8;
            let (a, b) = self.read_port(1);
            self.auto_read_data[3] <<= 1;       // `JOY2H`
            self.auto_read_data[3] |= a as u8;
            self.auto_read_data[7] <<= 1;       // `JOY4H`
            self.auto_read_data[7] |= b as u8;
        }
        // Then the low bytes (`JOY1L`/`JOY3L` for port 0, `JOY2L`/`JOY4L` for port 1)
        for _ in 0..8 {
            let (a, b) = self.read_port(0);
            self.auto_read_data[0] <<= 1;       // `JOY1L`
            self.auto_read_data[0] |= a as u8;
            self.auto_read_data[4] <<= 1;       // `JOY3L`
            self.auto_read_data[4] |= b as u8;
            let (a, b) = self.read_port(1);
            self.auto_read_data[2] <<= 1;       // `JOY2L`
            self.auto_read_data[2] |= a as u8;
            self.auto_read_data[6] <<= 1;       // `JOY4L`
            self.auto_read_data[6] |= b as u8;
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

/// Requires crate feature `"serde"`
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

/// Requires crate feature `"serde"`
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K, V>(PhantomData<(K, V)>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::new();
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for value in entries.values() {
            if value.is_none() {
                return Err(M::Error::custom("key not specified"));
            }
        }
        Ok(enum_map! { key => entries[key].take().unwrap() })
    }
}
<commit_msg>Use ok_or_else to hide `return` in `visit_map`<commit_after>#![cfg(feature = "serde")]

extern crate serde;

use EnumMap;
use Internal;

use self::serde::ser::{Serialize, Serializer, SerializeMap};
use self::serde::de::{self, Deserialize, Deserializer, Error, MapAccess};

use core::fmt;
use core::marker::PhantomData;

/// Requires crate feature `"serde"`
impl<K: Internal<V> + Serialize, V: Serialize> Serialize for EnumMap<K, V> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (key, value) in self {
            map.serialize_entry(&key, value)?;
        }
        map.end()
    }
}

/// Requires crate feature `"serde"`
impl<'de, K, V> Deserialize<'de> for EnumMap<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_map(Visitor(PhantomData))
    }
}

struct Visitor<K, V>(PhantomData<(K, V)>);

impl<'de, K, V> de::Visitor<'de> for Visitor<K, V>
where
    K: Internal<V>
        + Internal<Option<V>>
        + Deserialize<'de>,
    V: Deserialize<'de>,
{
    type Value = EnumMap<K, V>;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a map")
    }

    fn visit_map<M: MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
        let mut entries = EnumMap::new();
        while let Some((key, value)) = access.next_entry()? {
            entries[key] = Some(value);
        }
        for value in entries.values() {
            value.ok_or_else(|| M::Error::custom("key not specified"))?;
        }
        Ok(enum_map! { key => entries[key].take().unwrap() })
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::vec::Vec;
use {Publish, TopicPath, PacketIdentifier, QoS, LastWill, Error, Result};

#[derive(Debug, Clone)]
pub struct Message {
    pub topic: TopicPath,
    pub qos: QoS,
    pub retain: bool,
    // Only for QoS 1,2
    pub pid: Option<PacketIdentifier>,
    pub payload: Arc<Vec<u8>>
}

impl Message {
    pub fn from_pub(publish: Arc<Publish>) -> Result<Arc<Message>> {
        let topic = TopicPath::from(publish.topic_name.as_str());
        if topic.wildcards {
            return Err(Error::TopicNameMustNotContainWildcard);
        }
        Ok(Arc::new(Message {
            topic: topic,
            qos: publish.qos,
            retain: publish.retain,
            pid: publish.pid,
            payload: publish.payload.clone()
        }))
    }

    pub fn from_last_will(last_will: LastWill) -> Arc<Message> {
        let topic = TopicPath::from(last_will.topic);

        Arc::new(Message {
            topic: topic,
            qos: last_will.qos,
            retain: last_will.retain,
            pid: None,
            payload: Arc::new(last_will.message.into_bytes())
        })
    }

    pub fn to_pub(&self, qos: Option<QoS>, dup: bool) -> Arc<Publish> {
        let qos = qos.unwrap_or(self.qos);
        Arc::new(Publish {
            dup: dup,
            qos: qos,
            retain: false,
            topic_name: self.topic.path.clone(),
            pid: self.pid,
            payload: self.payload.clone()
        })
    }

    pub fn transform(&self, pid: Option<PacketIdentifier>, qos: Option<QoS>) -> Arc<Message> {
        let pid = pid.or(self.pid);
        let qos = qos.unwrap_or(self.qos);
        Arc::new(Message {
            topic: self.topic.clone(),
            qos: qos,
            retain: self.retain,
            pid: pid,
            payload: self.payload.clone()
        })
    }
}

#[cfg(test)]
mod test {
    use std::sync::Arc;
    use super::{Message};
    use {Publish, QoS, ToTopicPath, PacketIdentifier};

    #[test]
    fn message_to_pub_test() {
        let msg = Message {
            topic: "/a/b".to_topic_path().unwrap(),
            qos: QoS::AtLeastOnce,
            retain: false,
            pid: Some(PacketIdentifier(1)),
            payload: Arc::new(vec![0x80, 0x40])
        };
        let publish = msg.to_pub(None, false);

        assert_eq!(publish, Arc::new(Publish {
            dup: false,
            qos: QoS::AtLeastOnce,
            retain: false,
            topic_name: "/a/b".to_owned(),
            pid: Some(PacketIdentifier(1)),
            payload: Arc::new(vec![0x80, 0x40])
        }));
    }

    #[test]
    fn message_from_pub_test() {
        let publish = Arc::new(Publish {
            dup: true,
            qos: QoS::ExactlyOnce,
            retain: true,
            topic_name: "/a/b/c".to_owned(),
            pid: Some(PacketIdentifier(2)),
            payload: Arc::new(vec![0x10, 0x20, 0x30])
        });
        let msg = Message::from_pub(publish).unwrap();

        assert_eq!(msg.topic.path(), "/a/b/c".to_string());
        assert_eq!(msg.qos, QoS::ExactlyOnce);
        assert_eq!(msg.pid, Some(PacketIdentifier(2)));
        assert_eq!(msg.payload, Arc::new(vec![0x10, 0x20, 0x30]));
        assert!(msg.retain);
    }

    #[test]
    fn to_topic_name_test() {
        assert!("/a/b/c".to_topic_name().is_ok());
        assert!("/a/+/c".to_topic_name().is_err());
    }
}
<commit_msg>mqtt3: Replace Arc with Box in msg<commit_after>use std::sync::Arc;
use std::vec::Vec;
use {Publish, TopicPath, PacketIdentifier, QoS, LastWill, Error, Result};

#[derive(Debug, Clone)]
pub struct Message {
    pub topic: TopicPath,
    pub qos: QoS,
    pub retain: bool,
    // Only for QoS 1,2
    pub pid: Option<PacketIdentifier>,
    pub payload: Arc<Vec<u8>>
}

impl Message {
    pub fn from_pub(publish: Box<Publish>) -> Result<Box<Message>> {
        let topic = TopicPath::from(publish.topic_name.as_str());
        if topic.wildcards {
            return Err(Error::TopicNameMustNotContainWildcard);
        }
        Ok(Box::new(Message {
            topic: topic,
            qos: publish.qos,
            retain: publish.retain,
            pid: publish.pid,
            payload: publish.payload.clone()
        }))
    }

    pub fn from_last_will(last_will: LastWill) -> Box<Message> {
        let topic = TopicPath::from(last_will.topic);

        Box::new(Message {
            topic: topic,
            qos: last_will.qos,
            retain: last_will.retain,
            pid: None,
            payload: Arc::new(last_will.message.into_bytes())
        })
    }

    pub fn to_pub(&self, qos: Option<QoS>, dup: bool) -> Box<Publish> {
        let qos = qos.unwrap_or(self.qos);
        Box::new(Publish {
            dup: dup,
            qos: qos,
            retain: false,
            topic_name: self.topic.path.clone(),
            pid: self.pid,
            payload: self.payload.clone()
        })
    }

    pub fn transform(&self, pid: Option<PacketIdentifier>, qos: Option<QoS>) -> Box<Message> {
        let pid = pid.or(self.pid);
        let qos = qos.unwrap_or(self.qos);
        Box::new(Message {
            topic: self.topic.clone(),
            qos: qos,
            retain: self.retain,
            pid: pid,
            payload: self.payload.clone()
        })
    }
}

#[cfg(test)]
mod test {
    use std::sync::Arc;
    use super::{Message};
    use {Publish, QoS, ToTopicPath, PacketIdentifier};

    #[test]
    fn message_to_pub_test() {
        let msg = Message {
            topic: "/a/b".to_topic_path().unwrap(),
            qos: QoS::AtLeastOnce,
            retain: false,
            pid: Some(PacketIdentifier(1)),
            payload: Arc::new(vec![0x80, 0x40])
        };
        let publish = msg.to_pub(None, false);

        assert_eq!(publish, Box::new(Publish {
            dup: false,
            qos: QoS::AtLeastOnce,
            retain: false,
            topic_name: "/a/b".to_owned(),
            pid: Some(PacketIdentifier(1)),
            payload: Arc::new(vec![0x80, 0x40])
        }));
    }

    #[test]
    fn message_from_pub_test() {
        let publish = Box::new(Publish {
            dup: true,
            qos: QoS::ExactlyOnce,
            retain: true,
            topic_name: "/a/b/c".to_owned(),
            pid: Some(PacketIdentifier(2)),
            payload: Arc::new(vec![0x10, 0x20, 0x30])
        });
        let msg = Message::from_pub(publish).unwrap();

        assert_eq!(msg.topic.path(), "/a/b/c".to_string());
        assert_eq!(msg.qos, QoS::ExactlyOnce);
        assert_eq!(msg.pid, Some(PacketIdentifier(2)));
        assert_eq!(msg.payload, Arc::new(vec![0x10, 0x20, 0x30]));
        assert!(msg.retain);
    }

    #[test]
    fn to_topic_name_test() {
        assert!("/a/b/c".to_topic_name().is_ok());
        assert!("/a/+/c".to_topic_name().is_err());
    }
}
<|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.

//! Networking primitives not covered by the standard library.

/// A MAC address.
///
/// MAC addresses are defined as 48-bit numbers in a IEEE 802 standard [1].
///
/// [1]: https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/macgrp.pdf
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct MacAddr {
    /// Octets forming up the 48-bit MAC address number.
    octets: [u8; 6],
}

impl MacAddr {

    /// Return the six 8-bit integers that make up this address.
    pub fn octets(&self) -> [u8; 6] {
        self.octets
    }
}

impl From<[u8; 6]> for MacAddr {

    fn from(octets: [u8; 6]) -> MacAddr {
        MacAddr { octets }
    }
}
<commit_msg>Define a network interface type.<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.

//! Networking primitives not covered by the standard library.

/// A MAC address.
///
/// MAC addresses are defined as 48-bit numbers in a IEEE 802 standard [1].
///
/// [1]: https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/macgrp.pdf
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct MacAddr {
    /// Octets forming up the 48-bit MAC address number.
    octets: [u8; 6],
}

impl MacAddr {

    /// Return the six 8-bit integers that make up this address.
    pub fn octets(&self) -> [u8; 6] {
        self.octets
    }
}

impl From<[u8; 6]> for MacAddr {

    fn from(octets: [u8; 6]) -> MacAddr {
        MacAddr { octets }
    }
}

/// A network interface information.
struct Interface {
    /// A name of this interface as reported by the system.
    name: std::ffi::OsString,
    /// IP addresses associated with this interface.
    ip_addrs: Vec<std::net::IpAddr>,
    /// The MAC address associated with this interface.
    mac_addr: Option<MacAddr>,
}

impl Interface {

    /// Returns the name of this interface as reported by the system.
    pub fn name(&self) -> &std::ffi::OsStr {
        self.name.as_os_str()
    }

    /// Returns the IP addresses associated with this interface.
    pub fn ip_addrs(&self) -> &[std::net::IpAddr] {
        self.ip_addrs.as_slice()
    }

    /// Returns the MAC address associated with this interface (if any).
    pub fn mac_addr(&self) -> Option<&MacAddr> {
        self.mac_addr.as_ref()
    }
}
<|endoftext|>


<commit_before>use std::net::TcpStream;
use std::sync::mpsc;

use protocol::cmd::Resp;
use tcp_transport::TcpTransport;

use super::CmdSender;
use super::RespReceiver;
use super::RespSender;
use super::TransportId;

pub struct TransportTask {
    id: TransportId,
    cmd_tx: CmdSender,
}

impl TransportTask {
    pub fn new(id: TransportId, cmd_tx: CmdSender) -> TransportTask {
        TransportTask {
            id: id,
            cmd_tx: cmd_tx,
        }
    }

    pub fn run(&self, stream: TcpStream) {
        let mut transport = TcpTransport::new(stream);
        let (resp_tx, resp_rx): (RespSender, RespReceiver) = mpsc::channel();

        loop {
            println!("Ready to read command...");
            let rv = transport.read_cmd();

            // If we couldn't parse the command return an error
            if !rv.is_ok() {
                println!("Failed to read command, returning error");
                transport.write_resp(&Resp::Error);
                return; // Here we just drop the connection
            }

            // cmd -> resp
            let cmd = rv.unwrap();
            self.cmd_tx.send((self.id, resp_tx.clone(), cmd)).unwrap();
            let resp = resp_rx.recv().unwrap();

            // Return a response
            println!("Returning response: {:?}", &resp);
            let rv = transport.write_resp(&resp);
            if !rv.is_ok() {
                println!("Failed to write response :(");
            }
        }
    }
}
<commit_msg>improve comment<commit_after>use std::net::TcpStream;
use std::sync::mpsc;

use protocol::cmd::Resp;
use tcp_transport::TcpTransport;

use super::CmdSender;
use super::RespReceiver;
use super::RespSender;
use super::TransportId;

pub struct TransportTask {
    id: TransportId,
    cmd_tx: CmdSender,
}

impl TransportTask {
    pub fn new(id: TransportId, cmd_tx: CmdSender) -> TransportTask {
        TransportTask {
            id: id,
            cmd_tx: cmd_tx,
        }
    }

    pub fn run(&self, stream: TcpStream) {
        let mut transport = TcpTransport::new(stream);
        let (resp_tx, resp_rx): (RespSender, RespReceiver) = mpsc::channel();

        loop {
            println!("Ready to read command...");
            let rv = transport.read_cmd();

            // If we couldn't parse the command return an error
            if !rv.is_ok() {
                println!("Failed to read command, returning error");
                transport.write_resp(&Resp::Error);
                return; // Here we just drop the connection
            }

            // Send the command to the driver and obtain a response
            let cmd = rv.unwrap();
            self.cmd_tx.send((self.id, resp_tx.clone(), cmd)).unwrap();
            let resp = resp_rx.recv().unwrap();

            // Return a response
            println!("Returning response: {:?}", &resp);
            let rv = transport.write_resp(&resp);
            if !rv.is_ok() {
                println!("Failed to write response :(");
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::env;
use std::ffi::OsStr;
use std::io;
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches};
use console::style;
use failure::Error;
use if_chain::if_chain;
use serde::Serialize;
use symbolic::common::byteview::ByteView;
use symbolic::debuginfo::DebugId;
use symbolic::proguard::ProguardMappingView;
use uuid::Version as UuidVersion;
use walkdir::WalkDir;

use crate::utils::args::validate_id;
use crate::utils::dif::{DifFile, DifType};
use crate::utils::progress::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use crate::utils::system::QuietExit;

// text files larger than 32 megabytes are not considered to be
// valid mapping files when scanning
const MAX_MAPPING_FILE: u64 = 32 * 1024 * 1024;

#[derive(Serialize, Debug)]
struct DifMatch {
    #[serde(rename = "type")]
    pub ty: DifType,
    pub id: DebugId,
    pub path: PathBuf,
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Locate debug information files for given debug identifiers.")
        .arg(
            Arg::with_name("types")
                .long("type")
                .short("t")
                .value_name("TYPE")
                .multiple(true)
                .number_of_values(1)
                .possible_values(&["dsym", "elf", "proguard", "breakpad"])
                .help(
                    "Only consider debug information files of the given \
                     type.  By default all types are considered.",
                ),
        )
        .arg(
            Arg::with_name("no_well_known")
                .long("no-well-known")
                .help("Do not look for debug symbols in well known locations."),
        )
        .arg(
            Arg::with_name("no_cwd")
                .long("no-cwd")
                .help("Do not look for debug symbols in the current working directory."),
        )
        .arg(
            Arg::with_name("paths")
                .long("path")
                .short("p")
                .multiple(true)
                .number_of_values(1)
                .help("Add a path to search recursively for debug info files."),
        )
        .arg(
            Arg::with_name("json")
                .long("json")
                .help("Format outputs as JSON."),
        )
        .arg(
            Arg::with_name("ids")
                .index(1)
                .value_name("ID")
                .help("The debug identifiers of the files to search for.")
                .validator(validate_id)
                .multiple(true)
                .number_of_values(1),
        )
}

fn id_hint(id: &DebugId) -> &'static str {
    if id.appendix() > 0 {
        return "likely PDB";
    }

    match id.uuid().get_version() {
        Some(UuidVersion::Sha1) => "likely Proguard",
        Some(UuidVersion::Md5) => "likely dSYM",
        None => "likely ELF Debug",
        _ => "unknown",
    }
}

// TODO: Reduce complexity of this function
#[allow(clippy::cyclomatic_complexity)]
fn find_ids(
    paths: &HashSet<PathBuf>,
    types: &HashSet<DifType>,
    ids: &HashSet<DebugId>,
    as_json: bool,
) -> Result<bool, Error> {
    let mut remaining = ids.clone();
    let mut proguard_uuids: HashSet<_> = ids
        .iter()
        .map(|x| x.uuid())
        .filter(|&x| x.get_version() == Some(UuidVersion::Sha1))
        .collect();

    let iter = paths
        .iter()
        .flat_map(WalkDir::new)
        .filter_map(|e| e.ok())
        .filter(|e| e.file_type().is_file());

    let mut found_files = vec![];
    let pb = ProgressBar::new_spinner();
    pb.set_draw_target(ProgressDrawTarget::stdout());
    pb.set_style(
        ProgressStyle::default_spinner()
            .tick_chars("/|\\- ")
            .template(
                "{spinner} Looking for debug info files... {msg:.dim}\
                 \n  debug info files found: {prefix:.yellow}",
            ),
    );

    for dirent in iter {
        if remaining.is_empty() {
            break;
        }

        if let Some(p) = dirent.file_name().to_str() {
            pb.set_message(&p);
        }
        pb.tick();
        pb.set_prefix(&format!("{}", found_files.len()));

        let mut found = vec![];

        // specifically look for proguard files.  We only look for UUID5s
        // and only if the file is a text file.
        if_chain! {
            if !proguard_uuids.is_empty();
            if types.contains(&DifType::Proguard);
            if dirent.path().extension() == Some(OsStr::new("txt"));
            if let Ok(md) = dirent.metadata();
            if md.len() < MAX_MAPPING_FILE;
            if let Ok(byteview) = ByteView::from_path(dirent.path());
            if let Ok(mapping) = ProguardMappingView::parse(byteview);
            if proguard_uuids.contains(&mapping.uuid());
            then {
                found.push((mapping.uuid().into(), DifType::Proguard));
            }
        }

        // look for dsyms
        if_chain! {
            if types.contains(&DifType::Dsym);
            // we regularly match on .class files but the will never be
            // dsyms, so we can quickly skip them here
            if dirent.path().extension() != Some(OsStr::new("class"));
            if let Ok(dif) = DifFile::open_path(dirent.path(), Some(DifType::Dsym));
            then {
                for id in dif.ids() {
                    if remaining.contains(&id) {
                        found.push((id, DifType::Dsym));
                    }
                }
            }
        }

        // look for breakpad files
        if_chain! {
            if types.contains(&DifType::Breakpad);
            if dirent.path().extension() == Some(OsStr::new("sym"));
            if let Ok(dif) = DifFile::open_path(dirent.path(), Some(DifType::Breakpad));
            then {
                for id in dif.ids() {
                    if remaining.contains(&id) {
                        found.push((id, DifType::Breakpad));
                    }
                }
            }
        }

        for (id, ty) in found {
            let path = dirent.path().to_path_buf();
            found_files.push(DifMatch { ty, id, path });
            remaining.remove(&id);
            proguard_uuids.remove(&id.uuid());
        }
    }

    pb.finish_and_clear();

    if as_json {
        serde_json::to_writer_pretty(&mut io::stdout(), &found_files)?;
        println!();
    } else {
        for m in found_files {
            println!(
                "{} {} [{}]",
                style(m.id).dim(),
                m.path.display(),
                style(m.ty).yellow()
            );
        }
        if !remaining.is_empty() {
            eprintln!("");
            eprintln!("missing debug information files:");
            for id in &remaining {
                eprintln!("  {} ({})", id, id_hint(&id),);
            }
        }
    }

    Ok(remaining.is_empty())
}

pub fn execute<'a>(matches: &ArgMatches<'a>) -> Result<(), Error> {
    let mut paths = HashSet::new();
    let mut types = HashSet::new();
    let mut ids = HashSet::new();

    // which types should we consider?
    if let Some(t) = matches.values_of("types") {
        for ty in t {
            types.insert(ty.parse().unwrap());
        }
    } else {
        types.insert(DifType::Dsym);
        types.insert(DifType::Breakpad);
        types.insert(DifType::Proguard);
    }

    let with_well_known = !matches.is_present("no_well_known");
    let with_cwd = !matches.is_present("no_cwd");

    // start adding well known locations
    if_chain! {
        if with_well_known;
        if types.contains(&DifType::Dsym);
        if let Some(path) = dirs::home_dir().map(|x| x.join("Library/Developer/Xcode/DerivedData"));
        if path.is_dir();
        then {
            paths.insert(path);
        }
    }

    // current folder if wanted
    if_chain! {
        if with_cwd;
        if let Ok(path) = env::current_dir();
        then {
            paths.insert(path);
        }
    }

    // extra paths
    if let Some(p) = matches.values_of("paths") {
        for path in p {
            paths.insert(PathBuf::from(path));
        }
    }

    // which ids are we looking for?
    if let Some(i) = matches.values_of("ids") {
        for id in i {
            ids.insert(id.parse().unwrap());
        }
    } else {
        return Ok(());
    }

    if !find_ids(&paths, &types, &ids, matches.is_present("json"))? {
        return Err(QuietExit(1).into());
    }

    Ok(())
}
<commit_msg>ref(difutil): Enable search for ELF files<commit_after>use std::collections::HashSet;
use std::env;
use std::ffi::OsStr;
use std::io;
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches};
use console::style;
use failure::Error;
use if_chain::if_chain;
use serde::Serialize;
use symbolic::common::byteview::ByteView;
use symbolic::debuginfo::DebugId;
use symbolic::proguard::ProguardMappingView;
use uuid::Version as UuidVersion;
use walkdir::WalkDir;

use crate::utils::args::validate_id;
use crate::utils::dif::{DifFile, DifType};
use crate::utils::progress::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use crate::utils::system::QuietExit;

// text files larger than 32 megabytes are not considered to be
// valid mapping files when scanning
const MAX_MAPPING_FILE: u64 = 32 * 1024 * 1024;

#[derive(Serialize, Debug)]
struct DifMatch {
    #[serde(rename = "type")]
    pub ty: DifType,
    pub id: DebugId,
    pub path: PathBuf,
}

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Locate debug information files for given debug identifiers.")
        .arg(
            Arg::with_name("types")
                .long("type")
                .short("t")
                .value_name("TYPE")
                .multiple(true)
                .number_of_values(1)
                .possible_values(&["dsym", "elf", "proguard", "breakpad"])
                .help(
                    "Only consider debug information files of the given \
                     type.  By default all types are considered.",
                ),
        )
        .arg(
            Arg::with_name("no_well_known")
                .long("no-well-known")
                .help("Do not look for debug symbols in well known locations."),
        )
        .arg(
            Arg::with_name("no_cwd")
                .long("no-cwd")
                .help("Do not look for debug symbols in the current working directory."),
        )
        .arg(
            Arg::with_name("paths")
                .long("path")
                .short("p")
                .multiple(true)
                .number_of_values(1)
                .help("Add a path to search recursively for debug info files."),
        )
        .arg(
            Arg::with_name("json")
                .long("json")
                .help("Format outputs as JSON."),
        )
        .arg(
            Arg::with_name("ids")
                .index(1)
                .value_name("ID")
                .help("The debug identifiers of the files to search for.")
                .validator(validate_id)
                .multiple(true)
                .number_of_values(1),
        )
}

fn id_hint(id: &DebugId) -> &'static str {
    if id.appendix() > 0 {
        return "likely PDB";
    }

    match id.uuid().get_version() {
        Some(UuidVersion::Sha1) => "likely Proguard",
        Some(UuidVersion::Md5) => "likely dSYM",
        None => "likely ELF Debug",
        _ => "unknown",
    }
}

// TODO: Reduce complexity of this function
#[allow(clippy::cyclomatic_complexity)]
fn find_ids(
    paths: &HashSet<PathBuf>,
    types: &HashSet<DifType>,
    ids: &HashSet<DebugId>,
    as_json: bool,
) -> Result<bool, Error> {
    let mut remaining = ids.clone();
    let mut proguard_uuids: HashSet<_> = ids
        .iter()
        .map(|x| x.uuid())
        .filter(|&x| x.get_version() == Some(UuidVersion::Sha1))
        .collect();

    let iter = paths
        .iter()
        .flat_map(WalkDir::new)
        .filter_map(|e| e.ok())
        .filter(|e| e.file_type().is_file());

    let mut found_files = vec![];
    let pb = ProgressBar::new_spinner();
    pb.set_draw_target(ProgressDrawTarget::stdout());
    pb.set_style(
        ProgressStyle::default_spinner()
            .tick_chars("/|\\- ")
            .template(
                "{spinner} Looking for debug info files... {msg:.dim}\
                 \n  debug info files found: {prefix:.yellow}",
            ),
    );

    for dirent in iter {
        if remaining.is_empty() {
            break;
        }

        if let Some(p) = dirent.file_name().to_str() {
            pb.set_message(&p);
        }
        pb.tick();
        pb.set_prefix(&format!("{}", found_files.len()));

        let mut found = vec![];

        // specifically look for proguard files.  We only look for UUID5s
        // and only if the file is a text file.
        if_chain! {
            if !proguard_uuids.is_empty();
            if types.contains(&DifType::Proguard);
            if dirent.path().extension() == Some(OsStr::new("txt"));
            if let Ok(md) = dirent.metadata();
            if md.len() < MAX_MAPPING_FILE;
            if let Ok(byteview) = ByteView::from_path(dirent.path());
            if let Ok(mapping) = ProguardMappingView::parse(byteview);
            if proguard_uuids.contains(&mapping.uuid());
            then {
                found.push((mapping.uuid().into(), DifType::Proguard));
            }
        }

        // look for dsyms
        if_chain! {
            if types.contains(&DifType::Dsym);
            // we regularly match on .class files but the will never be
            // dsyms, so we can quickly skip them here
            if dirent.path().extension() != Some(OsStr::new("class"));
            if let Ok(dif) = DifFile::open_path(dirent.path(), Some(DifType::Dsym));
            then {
                for id in dif.ids() {
                    if remaining.contains(&id) {
                        found.push((id, DifType::Dsym));
                    }
                }
            }
        }

        // look for elfs
        if_chain! {
            if types.contains(&DifType::Elf);
            if let Ok(dif) = DifFile::open_path(dirent.path(), Some(DifType::Elf));
            then {
                for id in dif.ids() {
                    if remaining.contains(&id) {
                        found.push((id, DifType::Elf));
                    }
                }
            }
        }

        // look for breakpad files
        if_chain! {
            if types.contains(&DifType::Breakpad);
            if dirent.path().extension() == Some(OsStr::new("sym"));
            if let Ok(dif) = DifFile::open_path(dirent.path(), Some(DifType::Breakpad));
            then {
                for id in dif.ids() {
                    if remaining.contains(&id) {
                        found.push((id, DifType::Breakpad));
                    }
                }
            }
        }

        for (id, ty) in found {
            let path = dirent.path().to_path_buf();
            found_files.push(DifMatch { ty, id, path });
            remaining.remove(&id);
            proguard_uuids.remove(&id.uuid());
        }
    }

    pb.finish_and_clear();

    if as_json {
        serde_json::to_writer_pretty(&mut io::stdout(), &found_files)?;
        println!();
    } else {
        for m in found_files {
            println!(
                "{} {} [{}]",
                style(m.id).dim(),
                m.path.display(),
                style(m.ty).yellow()
            );
        }
        if !remaining.is_empty() {
            eprintln!("");
            eprintln!("missing debug information files:");
            for id in &remaining {
                eprintln!("  {} ({})", id, id_hint(&id),);
            }
        }
    }

    Ok(remaining.is_empty())
}

pub fn execute<'a>(matches: &ArgMatches<'a>) -> Result<(), Error> {
    let mut paths = HashSet::new();
    let mut types = HashSet::new();
    let mut ids = HashSet::new();

    // which types should we consider?
    if let Some(t) = matches.values_of("types") {
        for ty in t {
            types.insert(ty.parse().unwrap());
        }
    } else {
        types.insert(DifType::Dsym);
        types.insert(DifType::Breakpad);
        types.insert(DifType::Proguard);
    }

    let with_well_known = !matches.is_present("no_well_known");
    let with_cwd = !matches.is_present("no_cwd");

    // start adding well known locations
    if_chain! {
        if with_well_known;
        if types.contains(&DifType::Dsym);
        if let Some(path) = dirs::home_dir().map(|x| x.join("Library/Developer/Xcode/DerivedData"));
        if path.is_dir();
        then {
            paths.insert(path);
        }
    }

    // current folder if wanted
    if_chain! {
        if with_cwd;
        if let Ok(path) = env::current_dir();
        then {
            paths.insert(path);
        }
    }

    // extra paths
    if let Some(p) = matches.values_of("paths") {
        for path in p {
            paths.insert(PathBuf::from(path));
        }
    }

    // which ids are we looking for?
    if let Some(i) = matches.values_of("ids") {
        for id in i {
            ids.insert(id.parse().unwrap());
        }
    } else {
        return Ok(());
    }

    if !find_ids(&paths, &types, &ids, matches.is_present("json"))? {
        return Err(QuietExit(1).into());
    }

    Ok(())
}
<|endoftext|>