<commit_before>extern crate libc;

use array::Array;
use defines::AfError;
use seq::Seq;
use self::libc::{c_int, c_uint, c_longlong};

type MutAfIndex    = *mut self::libc::c_longlong;
type MutAfArray    = *mut self::libc::c_longlong;
type AfArray       = self::libc::c_longlong;
type DimT          = self::libc::c_longlong;
type IndexT        = self::libc::c_longlong;

#[allow(dead_code)]
extern {
    fn af_create_indexers(indexers: MutAfIndex) -> c_int;
    fn af_set_array_indexer(indexer: MutAfIndex, idx: AfArray, dim: DimT) -> c_int;
    fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const Seq, dim: DimT, is_batch: c_int) -> c_int;
    fn af_release_indexers(indexers: MutAfIndex) -> c_int;

    fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const Seq) -> c_int;
    fn af_lookup(out: MutAfArray, arr: AfArray, indices: AfArray, dim: c_uint) -> c_int;
    fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const Seq, rhs: AfArray) -> c_int;
    fn af_index_gen(out: MutAfArray, input: AfArray, ndims: DimT, indices: *const IndexT) -> c_int;
    fn af_assign_gen(out: MutAfArray, lhs: AfArray, ndims: DimT, indices: *const IndexT, rhs: AfArray) -> c_int;
}

pub struct Indexer {
    handle: i64,
    count: u32,
}

pub trait Indexable {
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError>;
}

impl Indexable for Array {
    #[allow(unused_variables)]
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        unsafe {
            let err_val = af_set_array_indexer(idxr.clone().get() as MutAfIndex,
                                             self.get() as AfArray,
                                             dim as DimT);
            match err_val {
                0 => Ok(()),
                _ => Err(AfError::from(err_val)),
            }
        }
    }
}

impl Indexable for Seq {
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        unsafe {
            let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, self as *const Seq,
                                           dim as DimT, is_batch.unwrap() as c_int);
            match err_val {
                0 => Ok(()),
                _ => Err(AfError::from(err_val)),
            }
        }
    }
}

impl Indexer {
    #[allow(unused_mut)]
    pub fn new() -> Result<Indexer, AfError> {
        unsafe {
            let mut temp: i64 = 0;
            let err_val = af_create_indexers(&mut temp as MutAfIndex);
            match err_val {
                0 => Ok(Indexer{handle: temp, count: 0}),
                _ => Err(AfError::from(err_val)),
            }
        }
    }

    pub fn set_index<T: Indexable>(&mut self, idx: &T, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        self.count = self.count + 1;
        idx.set(self, dim, is_batch)
    }

    pub fn get(&self) -> i64 {
        self.handle
    }

    pub fn len(&self) -> u32 {
        self.count
    }
}

impl Drop for Indexer {
    fn drop(&mut self) {
        unsafe {
            let ret_val = af_release_indexers(self.handle as MutAfIndex);
            match ret_val {
                0 => (),
                _ => panic!("Failed to release indexers resource: {}", ret_val),
            }
        }
    }
}

pub fn index(input: &Array, seqs: &[Seq]) -> Result<Array, AfError> {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_index(&mut temp as MutAfArray
                               , input.get() as AfArray, seqs.len() as u32
                               , seqs.as_ptr() as *const Seq);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn row(input: &Array, row_num: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in row(): {}", e),
    };

    index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0)
                    ,Seq::new(0.0, dims[1] as f64 - 1.0, 1.0)])
}

pub fn rows(input: &Array, first: u64, last: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in row(): {}", e),
    };

    index(input, &[Seq::new(first as f64, last as f64, 1.0)
                    ,Seq::new(0.0, dims[1] as f64 - 1.0, 1.0)])
}

pub fn col(input: &Array, col_num: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in row(): {}", e),
    };

    index(input, &[Seq::new(0.0, dims[0] as f64 - 1.0, 1.0)
                    ,Seq::new(col_num as f64, col_num as f64, 1.0)])
}

pub fn cols(input: &Array, first: u64, last: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in row(): {}", e),
    };

    index(input, &[Seq::new(0.0, dims[0] as f64 - 1.0, 1.0)
                    ,Seq::new(first as f64, last as f64, 1.0)])
}

pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result<Array, AfError> {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_lookup(&mut temp as MutAfArray, input.get() as AfArray,
                                indices.get() as AfArray, seq_dim as c_uint);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn assign_seq(lhs: &Array, ndims: usize, seqs: &[Seq], rhs: &Array) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray,
                                    ndims as c_uint, seqs.as_ptr() as *const Seq,
                                    rhs.get() as AfArray);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn index_gen(input: &Array, indices: Indexer) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_index_gen(&mut temp as MutAfArray, input.get() as AfArray,
                                   indices.len() as DimT, indices.get() as *const IndexT);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_assign_gen(&mut temp as MutAfArray, lhs.get() as AfArray,
                                    indices.len() as DimT, indices.get() as *const IndexT,
                                    rhs.get() as AfArray);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}
<commit_msg>cleanup error text<commit_after>extern crate libc;

use array::Array;
use defines::AfError;
use seq::Seq;
use self::libc::{c_int, c_uint, c_longlong};

type MutAfIndex    = *mut self::libc::c_longlong;
type MutAfArray    = *mut self::libc::c_longlong;
type AfArray       = self::libc::c_longlong;
type DimT          = self::libc::c_longlong;
type IndexT        = self::libc::c_longlong;

#[allow(dead_code)]
extern {
    fn af_create_indexers(indexers: MutAfIndex) -> c_int;
    fn af_set_array_indexer(indexer: MutAfIndex, idx: AfArray, dim: DimT) -> c_int;
    fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const Seq, dim: DimT, is_batch: c_int) -> c_int;
    fn af_release_indexers(indexers: MutAfIndex) -> c_int;

    fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const Seq) -> c_int;
    fn af_lookup(out: MutAfArray, arr: AfArray, indices: AfArray, dim: c_uint) -> c_int;
    fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const Seq, rhs: AfArray) -> c_int;
    fn af_index_gen(out: MutAfArray, input: AfArray, ndims: DimT, indices: *const IndexT) -> c_int;
    fn af_assign_gen(out: MutAfArray, lhs: AfArray, ndims: DimT, indices: *const IndexT, rhs: AfArray) -> c_int;
}

pub struct Indexer {
    handle: i64,
    count: u32,
}

pub trait Indexable {
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError>;
}

impl Indexable for Array {
    #[allow(unused_variables)]
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        unsafe {
            let err_val = af_set_array_indexer(idxr.clone().get() as MutAfIndex,
                                             self.get() as AfArray,
                                             dim as DimT);
            match err_val {
                0 => Ok(()),
                _ => Err(AfError::from(err_val)),
            }
        }
    }
}

impl Indexable for Seq {
    fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        unsafe {
            let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, self as *const Seq,
                                           dim as DimT, is_batch.unwrap() as c_int);
            match err_val {
                0 => Ok(()),
                _ => Err(AfError::from(err_val)),
            }
        }
    }
}

impl Indexer {
    #[allow(unused_mut)]
    pub fn new() -> Result<Indexer, AfError> {
        unsafe {
            let mut temp: i64 = 0;
            let err_val = af_create_indexers(&mut temp as MutAfIndex);
            match err_val {
                0 => Ok(Indexer{handle: temp, count: 0}),
                _ => Err(AfError::from(err_val)),
            }
        }
    }

    pub fn set_index<T: Indexable>(&mut self, idx: &T, dim: u32, is_batch: Option<bool>) -> Result<(), AfError> {
        self.count = self.count + 1;
        idx.set(self, dim, is_batch)
    }

    pub fn get(&self) -> i64 {
        self.handle
    }

    pub fn len(&self) -> u32 {
        self.count
    }
}

impl Drop for Indexer {
    fn drop(&mut self) {
        unsafe {
            let ret_val = af_release_indexers(self.handle as MutAfIndex);
            match ret_val {
                0 => (),
                _ => panic!("Failed to release indexers resource: {}", ret_val),
            }
        }
    }
}

pub fn index(input: &Array, seqs: &[Seq]) -> Result<Array, AfError> {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_index(&mut temp as MutAfArray
                               , input.get() as AfArray, seqs.len() as u32
                               , seqs.as_ptr() as *const Seq);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn row(input: &Array, row_num: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in row(): {}", e),
    };

    index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0)
                    ,Seq::new(0.0, dims[1] as f64 - 1.0, 1.0)])
}

pub fn rows(input: &Array, first: u64, last: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in rows(): {}", e),
    };

    index(input, &[Seq::new(first as f64, last as f64, 1.0)
                    ,Seq::new(0.0, dims[1] as f64 - 1.0, 1.0)])
}

pub fn col(input: &Array, col_num: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in col(): {}", e),
    };

    index(input, &[Seq::new(0.0, dims[0] as f64 - 1.0, 1.0)
                    ,Seq::new(col_num as f64, col_num as f64, 1.0)])
}

pub fn cols(input: &Array, first: u64, last: u64) -> Result<Array, AfError> {
    let dims_err = input.dims();
    let dims = match dims_err {
        Ok(dim) =>  dim.clone(),
        Err(e)  =>  panic!("Error unwrapping dims in cols(): {}", e),
    };

    index(input, &[Seq::new(0.0, dims[0] as f64 - 1.0, 1.0)
                    ,Seq::new(first as f64, last as f64, 1.0)])
}

pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result<Array, AfError> {
    unsafe {
        let mut temp: i64 = 0;
        let err_val = af_lookup(&mut temp as MutAfArray, input.get() as AfArray,
                                indices.get() as AfArray, seq_dim as c_uint);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn assign_seq(lhs: &Array, ndims: usize, seqs: &[Seq], rhs: &Array) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray,
                                    ndims as c_uint, seqs.as_ptr() as *const Seq,
                                    rhs.get() as AfArray);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn index_gen(input: &Array, indices: Indexer) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_index_gen(&mut temp as MutAfArray, input.get() as AfArray,
                                   indices.len() as DimT, indices.get() as *const IndexT);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}

pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result<Array, AfError> {
    unsafe{
        let mut temp: i64 = 0;
        let err_val = af_assign_gen(&mut temp as MutAfArray, lhs.get() as AfArray,
                                    indices.len() as DimT, indices.get() as *const IndexT,
                                    rhs.get() as AfArray);
        match err_val {
            0 => Ok(Array::from(temp)),
            _ => Err(AfError::from(err_val)),
        }
    }
}
<|endoftext|>


<commit_before>//! Emulates the controller ports `$4016 - $401f`

use frontend::{InputSource, DummyInput};

/// Controller input management.
pub struct Input {
    sources: [Box<InputSource>; 4],
    states: [InputState; 4],
    /// Reset on frame render, set on lazy input update. Lazy input update is done the first time
    /// the game reads any controller state in the current frame and is supposed to improve input
    /// latency.
    updated_this_frame: bool,

    /// Bit in the input state (where 0 = MSb, 15 = LSb) returned by next $4016/$4017 read resp.
    bitpos4016: u8,
    bitpos4017: u8,
}

impl Default for Input {
    /// Create the default input config. No controllers are attached.
    fn default() -> Input {
        Input {
            sources: [
                Box::new(DummyInput),
                Box::new(DummyInput),
                Box::new(DummyInput),
                Box::new(DummyInput)
            ],
            states: [InputState::default(); 4],
            updated_this_frame: false,
            bitpos4016: 0,
            bitpos4017: 0,
        }
    }
}

impl Input {
    pub fn new_frame(&mut self) { self.updated_this_frame = false; }

    /// Polls all controllers and stores their state. Called lazily when the game reads from an
    /// input register.
    fn update(&mut self) {
        self.updated_this_frame = true;
        for i in 0..4 {
            self.states[i] = self.sources[i].poll();
        }
    }

    /// 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 {
        // Do we still need to fetch this frame's input data?
        if !self.updated_this_frame { self.update(); }

        match reg {
            0x4016 => {
                let bitpos = self.bitpos4016;
                if bitpos == 16 { 1 } else {
                    // Read controller 1 and 3
                    let a = self.states[0].0 & (0x8000 >> bitpos as u16) != 0;
                    let c = self.states[2].0 & (0x8000 >> bitpos as u16) != 0;
                    self.bitpos4016 += 1;

                    (if c {0x02} else {0x00}) | (if a {0x01} else {0x00})
                }
            }
            0x4017 => {
                let bitpos = self.bitpos4017;
                if bitpos == 16 { 1 } else {
                    // Read controller 2 and 4
                    let a = self.states[1].0 & (0x8000 >> bitpos as u16) != 0;
                    let c = self.states[3].0 & (0x8000 >> bitpos as u16) != 0;
                    self.bitpos4017 += 1;

                    (if c {0x02} else {0x00}) | (if a {0x01} else {0x00})
                }
            }
            0x4218 ... 0x421f => {
                // "Full" read
                let controller = (reg - 0x4218) / 2;
                let hi = reg & 1 != 0;
                let state = &self.states[controller as usize];
                match hi {
                    false => state.0 as u8,
                    true => (state.0 >> 8) as u8,
                }
            }
            _ => panic!("${:04X} is not an input register", reg)
        }
    }

    /// Store to an input register. Will just latch the serial input.
    pub fn store(&mut self, reg: u16, val: u8) {
        if reg == 0x4016 {
            // No idea what this actually does, and no way to test it. Great! Let's just reset so
            // the MSb is read next time.
            assert!(val & 0xfe == val);
            self.bitpos4016 = 0;
            self.bitpos4017 = 0;
        } else {
            panic!("invalid input reg store to ${:04X}", reg);
        }
    }
}

/// State of a SNES joypad. The low byte can be read from `$4218`, the high byte from `$4219` (for
/// controller 1).
///
/// Bits:
/// `B Y Select Start Up Down Left Right - A X L R 0 0 0 0`
#[derive(Clone, Copy, Default)]
pub struct InputState(u16);

impl InputState {
    pub fn new() -> Self { Self::default() }

    fn set(&mut self, bit: u8, value: bool) -> &mut Self {
        match value {
            true => self.0 |= 1 << bit,
            false => self.0 &= !(1 << bit),
        };
        self
    }

    pub fn a(&mut self, pressed: bool) -> &mut Self      { self.set(7, pressed) }
    pub fn b(&mut self, pressed: bool) -> &mut Self      { self.set(15, pressed) }
    pub fn x(&mut self, pressed: bool) -> &mut Self      { self.set(6, pressed) }
    pub fn y(&mut self, pressed: bool) -> &mut Self      { self.set(14, pressed) }

    pub fn l(&mut self, pressed: bool) -> &mut Self      { self.set(5, pressed) }
    pub fn r(&mut self, pressed: bool) -> &mut Self      { self.set(4, pressed) }

    pub fn start(&mut self, pressed: bool) -> &mut Self  { self.set(12, pressed) }
    pub fn select(&mut self, pressed: bool) -> &mut Self { self.set(13, pressed) }

    pub fn up(&mut self, pressed: bool) -> &mut Self     { self.set(11, pressed) }
    pub fn down(&mut self, pressed: bool) -> &mut Self   { self.set(10, pressed) }
    pub fn left(&mut self, pressed: bool) -> &mut Self   { self.set(9, pressed) }
    pub fn right(&mut self, pressed: bool) -> &mut Self  { self.set(8, pressed) }
}
<commit_msg>Ensure that input is updated at least once per frame<commit_after>//! Emulates the controller ports `$4016 - $401f`

use frontend::{InputSource, DummyInput};

/// Controller input management.
pub struct Input {
    sources: [Box<InputSource>; 4],
    states: [InputState; 4],
    /// Reset on frame render, set on lazy input update. Lazy input update is done the first time
    /// the game reads any controller state in the current frame and is supposed to improve input
    /// latency.
    updated_this_frame: bool,

    /// Bit in the input state (where 0 = MSb, 15 = LSb) returned by next $4016/$4017 read resp.
    bitpos4016: u8,
    bitpos4017: u8,
}

impl Default for Input {
    /// Create the default input config. No controllers are attached.
    fn default() -> Input {
        Input {
            sources: [
                Box::new(DummyInput),
                Box::new(DummyInput),
                Box::new(DummyInput),
                Box::new(DummyInput)
            ],
            states: [InputState::default(); 4],
            updated_this_frame: false,
            bitpos4016: 0,
            bitpos4017: 0,
        }
    }
}

impl Input {
    /// Called on V-Blank. Ensures that `update` was called this frame, and enabled lazy input
    /// update for the following frame.
    pub fn new_frame(&mut self) {
        if !self.updated_this_frame { self.update(); }
        self.updated_this_frame = false;
    }

    /// Polls all controllers and stores their state. Called lazily when the game reads from an
    /// input register.
    fn update(&mut self) {
        self.updated_this_frame = true;
        for i in 0..4 {
            self.states[i] = self.sources[i].poll();
        }
    }

    /// 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 {
        // Do we still need to fetch this frame's input data?
        if !self.updated_this_frame { self.update(); }

        match reg {
            0x4016 => {
                let bitpos = self.bitpos4016;
                if bitpos == 16 { 1 } else {
                    // Read controller 1 and 3
                    let a = self.states[0].0 & (0x8000 >> bitpos as u16) != 0;
                    let c = self.states[2].0 & (0x8000 >> bitpos as u16) != 0;
                    self.bitpos4016 += 1;

                    (if c {0x02} else {0x00}) | (if a {0x01} else {0x00})
                }
            }
            0x4017 => {
                let bitpos = self.bitpos4017;
                if bitpos == 16 { 1 } else {
                    // Read controller 2 and 4
                    let a = self.states[1].0 & (0x8000 >> bitpos as u16) != 0;
                    let c = self.states[3].0 & (0x8000 >> bitpos as u16) != 0;
                    self.bitpos4017 += 1;

                    (if c {0x02} else {0x00}) | (if a {0x01} else {0x00})
                }
            }
            0x4218 ... 0x421f => {
                // "Full" read
                let controller = (reg - 0x4218) / 2;
                let hi = reg & 1 != 0;
                let state = &self.states[controller as usize];
                match hi {
                    false => state.0 as u8,
                    true => (state.0 >> 8) as u8,
                }
            }
            _ => panic!("${:04X} is not an input register", reg)
        }
    }

    /// Store to an input register. Will just latch the serial input.
    pub fn store(&mut self, reg: u16, val: u8) {
        if reg == 0x4016 {
            // No idea what this actually does, and no way to test it. Great! Let's just reset so
            // the MSb is read next time.
            assert!(val & 0xfe == val);
            self.bitpos4016 = 0;
            self.bitpos4017 = 0;
        } else {
            panic!("invalid input reg store to ${:04X}", reg);
        }
    }
}

/// State of a SNES joypad. The low byte can be read from `$4218`, the high byte from `$4219` (for
/// controller 1).
///
/// Bits:
/// `B Y Select Start Up Down Left Right - A X L R 0 0 0 0`
#[derive(Clone, Copy, Default)]
pub struct InputState(u16);

impl InputState {
    pub fn new() -> Self { Self::default() }

    fn set(&mut self, bit: u8, value: bool) -> &mut Self {
        match value {
            true => self.0 |= 1 << bit,
            false => self.0 &= !(1 << bit),
        };
        self
    }

    pub fn a(&mut self, pressed: bool) -> &mut Self      { self.set(7, pressed) }
    pub fn b(&mut self, pressed: bool) -> &mut Self      { self.set(15, pressed) }
    pub fn x(&mut self, pressed: bool) -> &mut Self      { self.set(6, pressed) }
    pub fn y(&mut self, pressed: bool) -> &mut Self      { self.set(14, pressed) }

    pub fn l(&mut self, pressed: bool) -> &mut Self      { self.set(5, pressed) }
    pub fn r(&mut self, pressed: bool) -> &mut Self      { self.set(4, pressed) }

    pub fn start(&mut self, pressed: bool) -> &mut Self  { self.set(12, pressed) }
    pub fn select(&mut self, pressed: bool) -> &mut Self { self.set(13, pressed) }

    pub fn up(&mut self, pressed: bool) -> &mut Self     { self.set(11, pressed) }
    pub fn down(&mut self, pressed: bool) -> &mut Self   { self.set(10, pressed) }
    pub fn left(&mut self, pressed: bool) -> &mut Self   { self.set(9, pressed) }
    pub fn right(&mut self, pressed: bool) -> &mut Self  { self.set(8, pressed) }
}
<|endoftext|>


<commit_before>//! Encoding of AVIF images.
///
/// The [AVIF] specification defines an image derivative of the AV1 bitstream, an open video codec.
///
/// [AVIF]: https://aomediacodec.github.io/av1-avif/
use std::borrow::Cow;
use std::io::Write;
use std::cmp::{min, max};

use crate::{ColorType, ImageBuffer, ImageFormat, Pixel};
use crate::{ImageError, ImageResult};
use crate::buffer::ConvertBuffer;
use crate::color::{FromColor, Luma, LumaA, Bgr, Bgra, Rgb, Rgba};
use crate::error::{EncodingError, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind};

use bytemuck::{Pod, PodCastError, try_cast_slice, try_cast_slice_mut};
use num_traits::Zero;
use ravif::{Img, ColorSpace, Config, RGBA8, encode_rgba};
use rgb::AsPixels;

/// AVIF Encoder.
///
/// Writes one image into the chosen output.
pub struct AvifEncoder<W> {
    inner: W,
    fallback: Vec<u8>,
}

impl<W: Write> AvifEncoder<W> {
    /// Create a new encoder that writes its output to `w`.
    pub fn new(w: W) -> Self {
        AvifEncoder { inner: w, fallback: vec![] }
    }

    /// Encode image data with the indicated color type.
    ///
    /// The encoder currently requires all data to be RGBA8, it will be converted internally if
    /// necessary. When data is suitably aligned, i.e. u16 channels to two bytes, then the
    /// conversion may be more efficient.
    pub fn write_image(mut self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> {
        self.write_image_with_speed_quality(data, width, height, color, 100, 1)
    }

    /// Encode image data with the indicated color type, quality and speed.
    ///
    /// The encoder currently requires all data to be RGBA8, it will be converted internally if
    /// necessary. When data is suitably aligned, i.e. u16 channels to two bytes, then the
    /// conversion may be more efficient.
    pub fn write_image_with_speed_quality(mut self, data: &[u8], width: u32, height: u32, color: ColorType, quality: u8, speed: u8) -> ImageResult<()> {
        // Clamp quality and speed to range
        let quality = max(0, min(quality, 100));
        let speed = max(0, min(speed, 10));

        let config = self.config(color, quality, speed);
        // `ravif` needs strongly typed data so let's convert. We can either use a temporarily
        // owned version in our own buffer or zero-copy if possible by using the input buffer.
        // This requires going through `rgb`.
        let buffer = self.encode_as_img(data, width, height, color)?;
        let (data, _color_size, _alpha_size) = encode_rgba(buffer, &config)
            .map_err(|err| ImageError::Encoding(
                EncodingError::new(ImageFormat::Avif.into(), err)
            ))?;
        self.inner.write_all(&data)?;
        Ok(())
    }

    fn config(&self, _color: ColorType, quality: u8, speed: u8) -> Config {
        Config {
            quality: quality,
            alpha_quality: quality,
            speed: speed,
            premultiplied_alpha: false,
            color_space: ColorSpace::RGB,
        }
    }

    fn encode_as_img<'buf>(&'buf mut self, data: &'buf [u8], width: u32, height: u32, color: ColorType)
        -> ImageResult<Img<&'buf [RGBA8]>>
    {
        // Error wrapping utility for color dependent buffer dimensions.
        fn try_from_raw<P: Pixel + 'static>(data: &[P::Subpixel], width: u32, height: u32)
            -> ImageResult<ImageBuffer<P, &[P::Subpixel]>>
        {
            ImageBuffer::from_raw(width, height, data).ok_or_else(|| {
                ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch))
            })
        };

        // Convert to target color type using few buffer allocations.
        fn convert_into<'buf, P>(buf: &'buf mut Vec<u8>, image: ImageBuffer<P, &[P::Subpixel]>)
            -> Img<&'buf [RGBA8]>
        where
            P: Pixel + 'static,
            Rgba<u8>: FromColor<P>,
        {
            let (width, height) = image.dimensions();
            // TODO: conversion re-using the target buffer?
            let image: ImageBuffer<Rgba<u8>, _> = image.convert();
            *buf = image.into_raw();
            Img::new(buf.as_pixels(), width as usize, height as usize)
        }

        // Cast the input slice using few buffer allocations if possible.
        // In particular try not to allocate if the caller did the infallible reverse.
        fn cast_buffer<Channel>(buf: &[u8]) -> ImageResult<Cow<[Channel]>>
        where
            Channel: Pod + Zero,
        {
            match try_cast_slice(buf) {
                Ok(slice) => Ok(Cow::Borrowed(slice)),
                Err(PodCastError::OutputSliceWouldHaveSlop) => {
                    Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)))
                }
                Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) => {
                    // Sad, but let's allocate.
                    // bytemuck checks alignment _before_ slop but size mismatch before this..
                    if buf.len() % std::mem::size_of::<Channel>() != 0 {
                        Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)))
                    } else {
                        let len = buf.len() / std::mem::size_of::<Channel>();
                        let mut data = vec![Channel::zero(); len];
                        let view = try_cast_slice_mut::<_, u8>(data.as_mut_slice()).unwrap();
                        view.copy_from_slice(buf);
                        Ok(Cow::Owned(data))
                    }
                }
                Err(err) => { // Are you trying to encode a ZST??
                    Err(ImageError::Parameter(ParameterError::from_kind(
                        ParameterErrorKind::Generic(format!("{:?}", err))
                    )))
                }
            }
        }

        match color {
            ColorType::Rgba8 => {
                // ravif doesn't do any checks but has some asserts, so we do the checks.
                let img = try_from_raw::<Rgba<u8>>(data, width, height)?;
                // Now, internally ravif uses u32 but it takes usize. We could do some checked
                // conversion but instead we use that a non-empty image must be addressable.
                if img.pixels().len() == 0 {
                    return Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)));
                }

                Ok(Img::new(rgb::AsPixels::as_pixels(data), width as usize, height as usize))
            },
            // we need a separate buffer..
            ColorType::L8 => {
                let image = try_from_raw::<Luma<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::La8 => {
                let image = try_from_raw::<LumaA<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgb8 => {
                let image = try_from_raw::<Rgb<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Bgr8 => {
                let image = try_from_raw::<Bgr<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Bgra8 => {
                let image = try_from_raw::<Bgra<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            // we need to really convert data..
            ColorType::L16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Luma<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::La16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<LumaA<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgb16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Rgb<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgba16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Rgba<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            // for cases we do not support at all?
            _ => Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                    ImageFormat::Avif.into(),
                    UnsupportedErrorKind::Color(color.into()),
                )))
        }
    }
}
<commit_msg>Rework to set speed and quality on constructor instead of write_image.<commit_after>//! Encoding of AVIF images.
///
/// The [AVIF] specification defines an image derivative of the AV1 bitstream, an open video codec.
///
/// [AVIF]: https://aomediacodec.github.io/av1-avif/
use std::borrow::Cow;
use std::io::Write;
use std::cmp::min;

use crate::{ColorType, ImageBuffer, ImageFormat, Pixel};
use crate::{ImageError, ImageResult};
use crate::buffer::ConvertBuffer;
use crate::color::{FromColor, Luma, LumaA, Bgr, Bgra, Rgb, Rgba};
use crate::error::{EncodingError, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind};

use bytemuck::{Pod, PodCastError, try_cast_slice, try_cast_slice_mut};
use num_traits::Zero;
use ravif::{Img, ColorSpace, Config, RGBA8, encode_rgba};
use rgb::AsPixels;

/// AVIF Encoder.
///
/// Writes one image into the chosen output.
pub struct AvifEncoder<W> {
    inner: W,
    fallback: Vec<u8>,
    config: Config
}

impl<W: Write> AvifEncoder<W> {
    /// Create a new encoder that writes its output to `w`.
    pub fn new(w: W) -> Self {
        AvifEncoder::new_with_speed_quality(w, 1, 100)
    }

    /// Create a new encoder with specified speed and quality,
    /// that writes its output to `w`.
    pub fn new_with_speed_quality(w: W, speed: u8, quality: u8) -> Self {
        // Clamp quality and speed to range
        let quality = min(quality, 100);
        let speed = min(speed, 10);

        AvifEncoder {
            inner: w,
            fallback: vec![],
            config: Config {
                quality,
                alpha_quality: quality,
                speed,
                premultiplied_alpha: false,
                color_space: ColorSpace::RGB,
            }
        }
    }

    /// Encode image data with the indicated color type.
    ///
    /// The encoder currently requires all data to be RGBA8, it will be converted internally if
    /// necessary. When data is suitably aligned, i.e. u16 channels to two bytes, then the
    /// conversion may be more efficient.
    pub fn write_image(mut self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> {
        self.set_color(color);
        let config = self.config;
        // `ravif` needs strongly typed data so let's convert. We can either use a temporarily
        // owned version in our own buffer or zero-copy if possible by using the input buffer.
        // This requires going through `rgb`.
        let buffer = self.encode_as_img(data, width, height, color)?;
        let (data, _color_size, _alpha_size) = encode_rgba(buffer, &config)
            .map_err(|err| ImageError::Encoding(
                EncodingError::new(ImageFormat::Avif.into(), err)
            ))?;
        self.inner.write_all(&data)?;
        Ok(())
    }

    // Does not currently do anything. Mirrors behaviour of old config function.
    fn set_color(&mut self, _color: ColorType) {
        // self.config.color_space = ColorSpace::RGB;
    }

    fn encode_as_img<'buf>(&'buf mut self, data: &'buf [u8], width: u32, height: u32, color: ColorType)
        -> ImageResult<Img<&'buf [RGBA8]>>
    {
        // Error wrapping utility for color dependent buffer dimensions.
        fn try_from_raw<P: Pixel + 'static>(data: &[P::Subpixel], width: u32, height: u32)
            -> ImageResult<ImageBuffer<P, &[P::Subpixel]>>
        {
            ImageBuffer::from_raw(width, height, data).ok_or_else(|| {
                ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch))
            })
        };

        // Convert to target color type using few buffer allocations.
        fn convert_into<'buf, P>(buf: &'buf mut Vec<u8>, image: ImageBuffer<P, &[P::Subpixel]>)
            -> Img<&'buf [RGBA8]>
        where
            P: Pixel + 'static,
            Rgba<u8>: FromColor<P>,
        {
            let (width, height) = image.dimensions();
            // TODO: conversion re-using the target buffer?
            let image: ImageBuffer<Rgba<u8>, _> = image.convert();
            *buf = image.into_raw();
            Img::new(buf.as_pixels(), width as usize, height as usize)
        }

        // Cast the input slice using few buffer allocations if possible.
        // In particular try not to allocate if the caller did the infallible reverse.
        fn cast_buffer<Channel>(buf: &[u8]) -> ImageResult<Cow<[Channel]>>
        where
            Channel: Pod + Zero,
        {
            match try_cast_slice(buf) {
                Ok(slice) => Ok(Cow::Borrowed(slice)),
                Err(PodCastError::OutputSliceWouldHaveSlop) => {
                    Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)))
                }
                Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) => {
                    // Sad, but let's allocate.
                    // bytemuck checks alignment _before_ slop but size mismatch before this..
                    if buf.len() % std::mem::size_of::<Channel>() != 0 {
                        Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)))
                    } else {
                        let len = buf.len() / std::mem::size_of::<Channel>();
                        let mut data = vec![Channel::zero(); len];
                        let view = try_cast_slice_mut::<_, u8>(data.as_mut_slice()).unwrap();
                        view.copy_from_slice(buf);
                        Ok(Cow::Owned(data))
                    }
                }
                Err(err) => { // Are you trying to encode a ZST??
                    Err(ImageError::Parameter(ParameterError::from_kind(
                        ParameterErrorKind::Generic(format!("{:?}", err))
                    )))
                }
            }
        }

        match color {
            ColorType::Rgba8 => {
                // ravif doesn't do any checks but has some asserts, so we do the checks.
                let img = try_from_raw::<Rgba<u8>>(data, width, height)?;
                // Now, internally ravif uses u32 but it takes usize. We could do some checked
                // conversion but instead we use that a non-empty image must be addressable.
                if img.pixels().len() == 0 {
                    return Err(ImageError::Parameter(ParameterError::from_kind(ParameterErrorKind::DimensionMismatch)));
                }

                Ok(Img::new(rgb::AsPixels::as_pixels(data), width as usize, height as usize))
            },
            // we need a separate buffer..
            ColorType::L8 => {
                let image = try_from_raw::<Luma<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::La8 => {
                let image = try_from_raw::<LumaA<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgb8 => {
                let image = try_from_raw::<Rgb<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Bgr8 => {
                let image = try_from_raw::<Bgr<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Bgra8 => {
                let image = try_from_raw::<Bgra<u8>>(data, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            // we need to really convert data..
            ColorType::L16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Luma<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::La16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<LumaA<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgb16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Rgb<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            ColorType::Rgba16 => {
                let buffer = cast_buffer(data)?;
                let image = try_from_raw::<Rgba<u16>>(&buffer, width, height)?;
                Ok(convert_into(&mut self.fallback, image))
            }
            // for cases we do not support at all?
            _ => Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                    ImageFormat::Avif.into(),
                    UnsupportedErrorKind::Color(color.into()),
                )))
        }
    }
}<|endoftext|>


<commit_before>use libc::{c_char, c_ulong, c_int, c_uint, O_RDONLY, read, strerror};
use std::borrow::{Cow, IntoCow};
use std::ffi::{CStr, CString};
use std::{mem, os, str};
use Joystick;

static JSIOCGAXES: c_uint = 2147576337;
static JSIOCGBUTTONS: c_uint = 2147576338;
static JSIOCGID: c_uint = 2151705107;
static JSIOCGID_LEN: usize = 64;

extern {
	fn open(path: *const c_char, oflag: c_int) -> c_int;
	fn close(fd: c_int) -> c_int;
	fn ioctl(fd: c_uint, op: c_uint, result: *mut c_char);
}

fn os_error() -> &'static str {
	unsafe {
		let num = os::errno() as c_int;
		let c_error = CStr::from_ptr(strerror(num) as *const i8);
		str::from_utf8(c_error.to_bytes()).unwrap()
	}
}

/// Scan for joysticks
pub fn scan() -> Vec<NativeJoystick> {
	use std::fs;
	// So many ifs...
	let mut joysticks = Vec::with_capacity(4);
	for entry in fs::walk_dir("/dev/input/").unwrap() {
		if let Ok(entry) = entry {
			let path = entry.path();
			if let Some(name) = path.file_name() {
				if let Some(name) = name.to_str() {
					if name.starts_with("js") {
						if let Ok(index) = name[2..].parse() {
							if let Ok(js) = Joystick::new(index) {
								joysticks.push(js)
							}
						}
					}
				}
			}
		}
	}
	joysticks
}

/// Represents a system joystick
pub struct NativeJoystick {
	index: u8,
	fd: c_int,
	connected: bool
}

impl ::Joystick for NativeJoystick {
	type WithState = StatefulNativeJoystick;
	type NativeEvent = LinuxEvent;
	/// This tries to open the interface `/dev/input/js...` and will return the
	/// OS-level error if it fails to open this
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		let path = format!("/dev/input/js{}", index);
		unsafe {
			let c_path = CString::new(path.as_bytes()).unwrap();
			let fd =  open(c_path.as_ptr(), O_RDONLY | 0x800);
			if fd == -1 {
				Err(os_error())
			} else {
				Ok(NativeJoystick {
					index: index,
					fd: fd,
					connected: true
				})
			}
		}
	}
	/// This reads from the interface in non-blocking mode and converts the native
	/// event into a Reminisce event
	fn poll_native(&mut self) -> Option<LinuxEvent> {
		unsafe {
			let mut event:LinuxEvent = mem::uninitialized();
			loop {
				let event_size = mem::size_of::<LinuxEvent>() as c_ulong;
				if read(self.fd, mem::transmute(&mut event), event_size) == -1 {
					match os::errno() {
						19 => self.connected = false,
						11 => (),
						code =>
							panic!("Error while polling joystick {} - {} - {}", self.index, code, os_error())
					}
					return None
				} else if event._type & 0x80 == 0 {
					return Some(event)
				}
			}
		}
	}
	fn is_connected(&self) -> bool {
		self.connected
	}
	fn get_num_axes(&self) -> u8 {
		unsafe {
			let mut num_axes: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGAXES, &mut num_axes as *mut i8);
			num_axes as u8
		}
	}
	fn get_num_buttons(&self) -> u8 {
		unsafe {
			let mut num_buttons: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGBUTTONS, &mut num_buttons as *mut i8);
			num_buttons as u8
		}
	}
	fn get_id(&self) -> Cow<str> {
		unsafe {
			let text = String::with_capacity(JSIOCGID_LEN);
			ioctl(self.fd as u32, JSIOCGID, text.as_ptr() as *mut i8);
			let mut new_text = String::from_raw_parts(text.as_ptr() as *mut u8, JSIOCGID_LEN, JSIOCGID_LEN);
			let length = CStr::from_ptr(text.as_ptr() as *const i8).to_bytes().len();
			mem::forget(text);
			new_text.truncate(length);
			new_text.shrink_to_fit();
			new_text.into_cow()
		}
	}
	fn get_index(&self) -> u8 {
		self.index
	}
	/// This is not supported on Linux so None is returned every time
	fn get_battery(&self) -> Option<f32> {
		None
	}
	fn with_state(self) -> StatefulNativeJoystick {
		StatefulNativeJoystick::wrap(self)
	}
}

impl Drop for NativeJoystick {
	/// Close the joystick's file descriptor
	fn drop(&mut self) {
		unsafe {
			if close(self.fd) == -1 {
				panic!("Failed to close joystick {} due to {}", self.index, os_error())
			}
		}
	}
}

/// The default joystick that tracks its state
pub struct StatefulNativeJoystick {
	js: NativeJoystick,
	axes: Vec<i16>,
	buttons: Vec<bool>
}
impl StatefulNativeJoystick {
	/// Wrap a joystick
	pub fn wrap(js: NativeJoystick) -> StatefulNativeJoystick {
		StatefulNativeJoystick {
			axes: vec![0; js.get_num_axes() as usize],
			buttons: vec![false; js.get_num_buttons() as usize],
			js: js
		}
	}
}
impl ::Joystick for StatefulNativeJoystick {
	type WithState = StatefulNativeJoystick;
	type NativeEvent = LinuxEvent;
	fn new(index: u8) -> Result<StatefulNativeJoystick, &'static str> {
		let js = try!(::Joystick::new(index));
		Ok(StatefulNativeJoystick::wrap(js))
	}
	fn is_connected(&self) -> bool {
		self.js.is_connected()
	}
	fn get_id(&self) -> Cow<str> {
		self.js.get_id()
	}
	fn get_index(&self) -> u8 {
		self.js.get_index()
	}
	fn get_num_axes(&self) -> u8 {
		self.js.get_num_axes()
	}
	fn get_num_buttons(&self) -> u8 {
		self.js.get_num_buttons()
	}
	fn get_battery(&self) -> Option<f32> {
		None
	}
	fn poll_native(&mut self) -> Option<LinuxEvent> {
		self.js.poll_native()
	}
	fn poll(&mut self) -> Option<::Event> {
		let event = self.js.poll();
		match event {
			Some(::Event::AxisMoved(i, v)) => self.axes[i as usize] = v,
			Some(::Event::ButtonPressed(i)) => self.buttons[i as usize] = true,
			Some(::Event::ButtonReleased(i)) => self.buttons[i as usize] = false,
			_ => ()
		}
		event
	}
	fn with_state(self) -> StatefulNativeJoystick {
		self
	}
}
impl ::StatefulJoystick for StatefulNativeJoystick {
	fn get_axis(&self, index: ::Axis) -> Option<i16> {
		self.axes.get(index as usize).cloned()
	}
	fn get_button(&self, index: ::Button) -> Option<bool> {
		self.buttons.get(index as usize).cloned()
	}
	fn update(&mut self) {
		while let Some(_) = self.poll() {}
	}
}

#[repr(C)]
pub struct LinuxEvent {
	/// timestamp in milleseconds
	time: u32,
	/// value
	value: i16,
	/// event type
	_type: u8,
	/// axis / button number
	number: u8
}
impl ::IntoEvent for LinuxEvent {
	fn into_event(self) -> ::Event {
		use std::mem::transmute as cast;
		match (self._type, self.value) {
			(1, 0) => ::Event::ButtonReleased(unsafe { cast(self.number) }),
			(1, 1) => ::Event::ButtonPressed(unsafe { cast(self.number) }),
			(2, _) => ::Event::AxisMoved(unsafe { cast(self.number) }, self.value),
			_ => panic!("Bad type and value {} {} for joystick", self._type, self.value)
		}
	}
}
<commit_msg>Improve scanning on Linux<commit_after>use libc::{c_char, c_ulong, c_int, c_uint, O_RDONLY, read, strerror};
use std::borrow::{Cow, IntoCow};
use std::ffi::{CStr, CString};
use std::{mem, os, str};
use Joystick;

static JSIOCGAXES: c_uint = 2147576337;
static JSIOCGBUTTONS: c_uint = 2147576338;
static JSIOCGID: c_uint = 2151705107;
static JSIOCGID_LEN: usize = 64;

extern {
	fn open(path: *const c_char, oflag: c_int) -> c_int;
	fn close(fd: c_int) -> c_int;
	fn ioctl(fd: c_uint, op: c_uint, result: *mut c_char);
}

fn os_error() -> &'static str {
	unsafe {
		let num = os::errno() as c_int;
		let c_error = CStr::from_ptr(strerror(num) as *const i8);
		str::from_utf8(c_error.to_bytes()).unwrap()
	}
}

/// Scan for joysticks
pub fn scan() -> Vec<NativeJoystick> {
	use std::fs;
	// So many ifs...
	let mut joysticks = Vec::with_capacity(4);
	if let Ok(entries) = fs::walk_dir("/dev/input/") {
		for entry in entries {
			if let Ok(entry) = entry {
				let path = entry.path();
				if let Some(name) = path.file_name() {
					if let Some(name) = name.to_str() {
						if name.starts_with("js") {
							if let Ok(index) = name[2..].parse() {
								if let Ok(js) = Joystick::new(index) {
									joysticks.push(js)
								}
							}
						}
					}
				}
			}
		}
	}
	joysticks
}

/// Represents a system joystick
pub struct NativeJoystick {
	index: u8,
	fd: c_int,
	connected: bool
}

impl ::Joystick for NativeJoystick {
	type WithState = StatefulNativeJoystick;
	type NativeEvent = LinuxEvent;
	/// This tries to open the interface `/dev/input/js...` and will return the
	/// OS-level error if it fails to open this
	fn new(index: u8) -> Result<NativeJoystick, &'static str> {
		let path = format!("/dev/input/js{}", index);
		unsafe {
			let c_path = CString::new(path.as_bytes()).unwrap();
			let fd =  open(c_path.as_ptr(), O_RDONLY | 0x800);
			if fd == -1 {
				Err(os_error())
			} else {
				Ok(NativeJoystick {
					index: index,
					fd: fd,
					connected: true
				})
			}
		}
	}
	/// This reads from the interface in non-blocking mode and converts the native
	/// event into a Reminisce event
	fn poll_native(&mut self) -> Option<LinuxEvent> {
		unsafe {
			let mut event:LinuxEvent = mem::uninitialized();
			loop {
				let event_size = mem::size_of::<LinuxEvent>() as c_ulong;
				if read(self.fd, mem::transmute(&mut event), event_size) == -1 {
					match os::errno() {
						19 => self.connected = false,
						11 => (),
						code =>
							panic!("Error while polling joystick {} - {} - {}", self.index, code, os_error())
					}
					return None
				} else if event._type & 0x80 == 0 {
					return Some(event)
				}
			}
		}
	}
	fn is_connected(&self) -> bool {
		self.connected
	}
	fn get_num_axes(&self) -> u8 {
		unsafe {
			let mut num_axes: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGAXES, &mut num_axes as *mut i8);
			num_axes as u8
		}
	}
	fn get_num_buttons(&self) -> u8 {
		unsafe {
			let mut num_buttons: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGBUTTONS, &mut num_buttons as *mut i8);
			num_buttons as u8
		}
	}
	fn get_id(&self) -> Cow<str> {
		unsafe {
			let text = String::with_capacity(JSIOCGID_LEN);
			ioctl(self.fd as u32, JSIOCGID, text.as_ptr() as *mut i8);
			let mut new_text = String::from_raw_parts(text.as_ptr() as *mut u8, JSIOCGID_LEN, JSIOCGID_LEN);
			let length = CStr::from_ptr(text.as_ptr() as *const i8).to_bytes().len();
			mem::forget(text);
			new_text.truncate(length);
			new_text.shrink_to_fit();
			new_text.into_cow()
		}
	}
	fn get_index(&self) -> u8 {
		self.index
	}
	/// This is not supported on Linux so None is returned every time
	fn get_battery(&self) -> Option<f32> {
		None
	}
	fn with_state(self) -> StatefulNativeJoystick {
		StatefulNativeJoystick::wrap(self)
	}
}

impl Drop for NativeJoystick {
	/// Close the joystick's file descriptor
	fn drop(&mut self) {
		unsafe {
			if close(self.fd) == -1 {
				panic!("Failed to close joystick {} due to {}", self.index, os_error())
			}
		}
	}
}

/// The default joystick that tracks its state
pub struct StatefulNativeJoystick {
	js: NativeJoystick,
	axes: Vec<i16>,
	buttons: Vec<bool>
}
impl StatefulNativeJoystick {
	/// Wrap a joystick
	pub fn wrap(js: NativeJoystick) -> StatefulNativeJoystick {
		StatefulNativeJoystick {
			axes: vec![0; js.get_num_axes() as usize],
			buttons: vec![false; js.get_num_buttons() as usize],
			js: js
		}
	}
}
impl ::Joystick for StatefulNativeJoystick {
	type WithState = StatefulNativeJoystick;
	type NativeEvent = LinuxEvent;
	fn new(index: u8) -> Result<StatefulNativeJoystick, &'static str> {
		let js = try!(::Joystick::new(index));
		Ok(StatefulNativeJoystick::wrap(js))
	}
	fn is_connected(&self) -> bool {
		self.js.is_connected()
	}
	fn get_id(&self) -> Cow<str> {
		self.js.get_id()
	}
	fn get_index(&self) -> u8 {
		self.js.get_index()
	}
	fn get_num_axes(&self) -> u8 {
		self.js.get_num_axes()
	}
	fn get_num_buttons(&self) -> u8 {
		self.js.get_num_buttons()
	}
	fn get_battery(&self) -> Option<f32> {
		None
	}
	fn poll_native(&mut self) -> Option<LinuxEvent> {
		self.js.poll_native()
	}
	fn poll(&mut self) -> Option<::Event> {
		let event = self.js.poll();
		match event {
			Some(::Event::AxisMoved(i, v)) => self.axes[i as usize] = v,
			Some(::Event::ButtonPressed(i)) => self.buttons[i as usize] = true,
			Some(::Event::ButtonReleased(i)) => self.buttons[i as usize] = false,
			_ => ()
		}
		event
	}
	fn with_state(self) -> StatefulNativeJoystick {
		self
	}
}
impl ::StatefulJoystick for StatefulNativeJoystick {
	fn get_axis(&self, index: ::Axis) -> Option<i16> {
		self.axes.get(index as usize).cloned()
	}
	fn get_button(&self, index: ::Button) -> Option<bool> {
		self.buttons.get(index as usize).cloned()
	}
	fn update(&mut self) {
		while let Some(_) = self.poll() {}
	}
}

#[repr(C)]
pub struct LinuxEvent {
	/// timestamp in milleseconds
	time: u32,
	/// value
	value: i16,
	/// event type
	_type: u8,
	/// axis / button number
	number: u8
}
impl ::IntoEvent for LinuxEvent {
	fn into_event(self) -> ::Event {
		use std::mem::transmute as cast;
		match (self._type, self.value) {
			(1, 0) => ::Event::ButtonReleased(unsafe { cast(self.number) }),
			(1, 1) => ::Event::ButtonPressed(unsafe { cast(self.number) }),
			(2, _) => ::Event::AxisMoved(unsafe { cast(self.number) }, self.value),
			_ => panic!("Bad type and value {} {} for joystick", self._type, self.value)
		}
	}
}
<|endoftext|>


<commit_before>import std::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;

tag deref_t { unbox; field; index; }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [];
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_tag(did, tps) {
                let variants = ty::tag_variants(tcx, did);
                if vec::len(variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [];
    while true {
        alt copy ex.node {
          expr_field(base, ident) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        mut = fld.mt.mut != imm;
                        break;
                    }
                }
              }
              ty::ty_obj(_) { }
            }
            ds += [@{mut: mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut != imm,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str. {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let mut = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { mut = mt.mut != imm; }
                  ty::ty_uniq(mt) { mut = mt.mut != imm; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_tag(_, _) { }
                  ty::ty_ptr(mt) { mut = mt.mut != imm; }
                }
                ds += [@{mut: mut, kind: unbox, outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v =
        @{visit_expr: bind visit_expr(cx, _, _, _),
          visit_decl: bind visit_decl(cx, _, _, _)
             with *visit::default_visitor::<()>()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

tag msg { msg_assign; msg_move_out; msg_mut_ref; }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span,
                         alt msg {
                           msg_assign. { "assigning to " + name }
                           msg_move_out. { "moving out of " + name }
                           msg_mut_ref. {
                             "passing " + name + " by mutable reference"
                           }
                         });
}

fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none. { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args) { check_call(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg == msg_assign { mk_err(cx, dest.span, msg, "non-lvalue"); }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox. { "immutable box" }
                  mut::field. { "immutable field" }
                  mut::index. { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_obj_field(_, _) {
            mk_err(cx, src.span, msg_move_out, "object field");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        if arg_t.mode != by_ref { check_lval(cx, args[i], msg_mut_ref); }
        i += 1u;
    }
}

fn is_immutable_def(def: def) -> option::t<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_obj_field(_, imm.) { some("immutable object field") }
      def_upvar(_, inner, mut) {
        if !mut { some("upvar") } else { is_immutable_def(*inner) }
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref.) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Fix bug in mutability-checking pass<commit_after>import std::{vec, str, option};
import option::{some, none};
import syntax::ast::*;
import syntax::visit;
import syntax::ast_util;

tag deref_t { unbox; field; index; }

type deref = @{mut: bool, kind: deref_t, outer_t: ty::t};

// Finds the root (the thing that is dereferenced) for the given expr, and a
// vec of dereferences that were used on this root. Note that, in this vec,
// the inner derefs come in front, so foo.bar[1] becomes rec(ex=foo,
// ds=[index,field])
fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
   {ex: @expr, ds: @[deref]} {
    fn maybe_auto_unbox(tcx: ty::ctxt, t: ty::t) -> {t: ty::t, ds: [deref]} {
        let ds = [];
        while true {
            alt ty::struct(tcx, t) {
              ty::ty_box(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_uniq(mt) {
                ds += [@{mut: mt.mut != imm, kind: unbox, outer_t: t}];
                t = mt.ty;
              }
              ty::ty_res(_, inner, tps) {
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, inner);
              }
              ty::ty_tag(did, tps) {
                let variants = ty::tag_variants(tcx, did);
                if vec::len(variants) != 1u ||
                       vec::len(variants[0].args) != 1u {
                    break;
                }
                ds += [@{mut: false, kind: unbox, outer_t: t}];
                t = ty::substitute_type_params(tcx, tps, variants[0].args[0]);
              }
              _ { break; }
            }
        }
        ret {t: t, ds: ds};
    }
    let ds: [deref] = [];
    while true {
        alt copy ex.node {
          expr_field(base, ident) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            let mut = false;
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_rec(fields) {
                for fld: ty::field in fields {
                    if str::eq(ident, fld.ident) {
                        mut = fld.mt.mut != imm;
                        break;
                    }
                }
              }
              ty::ty_obj(_) { }
            }
            ds += [@{mut: mut, kind: field, outer_t: auto_unbox.t}];
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_index(base, _) {
            let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
            alt ty::struct(tcx, auto_unbox.t) {
              ty::ty_vec(mt) {
                ds +=
                    [@{mut: mt.mut != imm,
                       kind: index,
                       outer_t: auto_unbox.t}];
              }
              ty::ty_str. {
                ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
              }
            }
            ds += auto_unbox.ds;
            ex = base;
          }
          expr_unary(op, base) {
            if op == deref {
                let base_t = ty::expr_ty(tcx, base);
                let mut = false;
                alt ty::struct(tcx, base_t) {
                  ty::ty_box(mt) { mut = mt.mut != imm; }
                  ty::ty_uniq(mt) { mut = mt.mut != imm; }
                  ty::ty_res(_, _, _) { }
                  ty::ty_tag(_, _) { }
                  ty::ty_ptr(mt) { mut = mt.mut != imm; }
                }
                ds += [@{mut: mut, kind: unbox, outer_t: base_t}];
                ex = base;
            } else { break; }
          }
          _ { break; }
        }
    }
    if autoderef {
        let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, ex));
        ds += auto_unbox.ds;
    }
    ret {ex: ex, ds: @ds};
}

// Actual mut-checking pass

type mut_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt, mut_map: mut_map};

fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map {
    let cx = @{tcx: tcx, mut_map: std::map::new_int_hash()};
    let v =
        @{visit_expr: bind visit_expr(cx, _, _, _),
          visit_decl: bind visit_decl(cx, _, _, _)
             with *visit::default_visitor::<()>()};
    visit::visit_crate(*crate, (), visit::mk_vt(v));
    ret cx.mut_map;
}

tag msg { msg_assign; msg_move_out; msg_mut_ref; }

fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) {
    cx.tcx.sess.span_err(span, alt msg {
      msg_assign. { "assigning to " + name }
      msg_move_out. { "moving out of " + name }
      msg_mut_ref. { "passing " + name + " by mutable reference" }
    });
}

fn visit_decl(cx: @ctx, d: @decl, e: (), v: visit::vt<()>) {
    visit::visit_decl(d, e, v);
    alt d.node {
      decl_local(locs) {
        for (_, loc) in locs {
            alt loc.node.init {
              some(init) {
                if init.op == init_move { check_move_rhs(cx, init.expr); }
              }
              none. { }
            }
        }
      }
      _ { }
    }
}

fn visit_expr(cx: @ctx, ex: @expr, e: (), v: visit::vt<()>) {
    alt ex.node {
      expr_call(f, args) { check_call(cx, f, args); }
      expr_swap(lhs, rhs) {
        check_lval(cx, lhs, msg_assign);
        check_lval(cx, rhs, msg_assign);
      }
      expr_move(dest, src) {
        check_lval(cx, dest, msg_assign);
        check_move_rhs(cx, src);
      }
      expr_assign(dest, src) | expr_assign_op(_, dest, src) {
        check_lval(cx, dest, msg_assign);
      }
      _ { }
    }
    visit::visit_expr(ex, e, v);
}

fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
    alt dest.node {
      expr_path(p) {
        let def = cx.tcx.def_map.get(dest.id);
        alt is_immutable_def(def) {
          some(name) { mk_err(cx, dest.span, msg, name); }
          _ { }
        }
        cx.mut_map.insert(ast_util::def_id_of_def(def).node, ());
      }
      _ {
        let root = expr_root(cx.tcx, dest, false);
        if vec::len(*root.ds) == 0u {
            if msg != msg_move_out {
                mk_err(cx, dest.span, msg, "non-lvalue");
            }
        } else if !root.ds[0].mut {
            let name =
                alt root.ds[0].kind {
                  mut::unbox. { "immutable box" }
                  mut::field. { "immutable field" }
                  mut::index. { "immutable vec content" }
                };
            mk_err(cx, dest.span, msg, name);
        }
      }
    }
}

fn check_move_rhs(cx: @ctx, src: @expr) {
    alt src.node {
      expr_path(p) {
        alt cx.tcx.def_map.get(src.id) {
          def_obj_field(_, _) {
            mk_err(cx, src.span, msg_move_out, "object field");
          }
          _ { }
        }
        check_lval(cx, src, msg_move_out);
      }
      _ {
        let root = expr_root(cx.tcx, src, false);

        // Not a path and no-derefs means this is a temporary.
        if vec::len(*root.ds) != 0u {
            cx.tcx.sess.span_err(src.span, "moving out of a data structure");
        }
      }
    }
}

fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
    let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
    let i = 0u;
    for arg_t: ty::arg in arg_ts {
        alt arg_t.mode {
          by_mut_ref. { check_lval(cx, args[i], msg_mut_ref); }
          by_move. { check_lval(cx, args[i], msg_move_out); }
          by_ref. {}
        }
        i += 1u;
    }
}

fn is_immutable_def(def: def) -> option::t<str> {
    alt def {
      def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
      def_use(_) {
        some("static item")
      }
      def_obj_field(_, imm.) { some("immutable object field") }
      def_upvar(_, inner, mut) {
        if !mut { some("upvar") } else { is_immutable_def(*inner) }
      }
      def_binding(_) { some("binding") }
      def_local(_, let_ref.) { some("by-reference binding") }
      _ { none }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::collections::HashSet;

use super::{Graphics, Drawer};
use draw::resize;
use time::precise_time_s as time_s;

use glium::glutin::{Event, ElementState};

pub use glium::glutin::{VirtualKeyCode, MouseButton};

/// Describes a way to handle an update
pub trait State{
    /// Function that gets called each frame update, when this `State` is being run
    ///
    /// Returns whether to do something after the update has been handled
    fn frame(&mut self, closed: bool, FrameInfo, Drawer) -> StateAction;
}

impl<F> State for F where F: FnMut(bool, FrameInfo, Drawer) -> StateAction{
    fn frame(&mut self, c: bool, i: FrameInfo, d: Drawer) -> StateAction{
        (self)(c, i, d)
    }
}

/// Describes what to do after a frame update
pub enum StateAction{
    /// Says to continue without changing the state
    Continue,
    /// Says to change the state to the one specified
    ChangeTo(Box<State>),
    /// Says to close the game
    Close
}

/// Manages events and frames
pub struct GameManager<'a>{
    graphics: Graphics<'a>,
    last: f64,
    down_keys: HashSet<VirtualKeyCode>,
    mousepos: (f32, f32),
}

impl<'a> GameManager<'a>{
    #[inline]
    /// Creates a new `GameManager` from a `Graphics` object
    pub fn new(graphics: Graphics<'a>) -> Self {
        GameManager{
            graphics: graphics,
            last: time_s(),
            mousepos: (0., 0.),
            down_keys: HashSet::new()
        }
    }

<<<<<<< HEAD
    /// Returns an optional tuple of a `FrameInfo` and a `Drawer` or `None`, if the window has been closed.
    ///
    /// The window doesn't actually close when `None` is returned; you can just
    /// ignore it, and it will just keep running: The window only closes when the `GameManager` object is dropped.
    pub fn next_frame(&mut self) -> Option<(FrameInfo, Drawer)>{
=======
    /// Runs the game with the specified initial state
    pub fn run(&mut self, initial_state: Box<State>){
        let mut current_state = initial_state;

        loop{
            let (c, fi, d) = self.next_frame();

            match current_state.frame(c, fi, d){
                StateAction::ChangeTo(new) => current_state = new,
                StateAction::Continue      => (),
                StateAction::Close         => break,
            }
        }
    }

    /// Runs the game until the user tries to close the window
    pub fn run_until_closed<F: FnMut(FrameInfo, Drawer)>(&mut self, mut f: F){
        while let (false, frame_info, drawer) = self.next_frame() {
            f(frame_info, drawer)
        }
    }

    /// Returns a tuple of a `bool` (which is `true` if the user tried
    /// to close the window), a `FrameInfo` and a `Drawer`
    pub fn next_frame(&mut self) -> (bool, FrameInfo, Drawer){
>>>>>>> feauture-game-states
        let mut keys = Vec::new();
        let mut mouses = Vec::new();
        let mut closed = false;

        let mut resized = None::<(u32, u32)>;

        for ev in self.graphics.poll_events() {
            match ev {
                Event::Closed => closed = true,
                Event::KeyboardInput(es, _, Some(vkc)) => match es{
                    ElementState::Pressed  => {
                        self.down_keys.insert( vkc);
                        keys.push((true , vkc));
                    },
                    ElementState::Released => {
                        self.down_keys.remove(&vkc);
                        keys.push((false, vkc));
                    }
                },
                Event::MouseMoved(pos) => {
                    let (w, h) = self.graphics.get_h_size();
                    let (x, y) = pos;

                    self.mousepos = (x as f32 - w, h - y as f32);
                },
                // This is only neccessary because `graphics` gets immutably borrowed for this for-loop
                Event::Resized(w, h) => resized = Some((w, h)),
                Event::MouseInput(state, button) => mouses.push((state == ElementState::Pressed, button)),
                _ => ()
            }
        }

        if let Some((w, h)) = resized{
            resize(&mut self.graphics, w, h);
        }

        let now = time_s();
        let delta = now - self.last;
        self.last = now;

        let update = FrameInfo{
            delta    : delta,
            key_events: keys,
            mouse_events: mouses,
            down_keys: &self.down_keys,
            mousepos : self.mousepos
        };

        (closed, update, Drawer::new(&self.graphics))
    }
}

/// Wraps together useful data about what has happened (e.g. events)
#[derive(Debug)]
pub struct FrameInfo<'a>{
    /// The amount of time passed since last frame
    pub delta: f64,
    /// The last position of the mouse on the screen
    pub mousepos: (f32, f32),
    mouse_events: Vec<(bool, MouseButton)>,
    key_events: Vec<(bool, VirtualKeyCode)>,

    // All keys that are pressed down
    down_keys: &'a HashSet<VirtualKeyCode>
}

impl<'a> FrameInfo<'a>{
    #[inline]
    /// Returns a slice of all key events that have happened
    pub fn get_key_events(&self) -> &[(bool, VirtualKeyCode)]{
        &self.key_events
    }
    #[inline]
    /// Returns a slice of all key events that have happened
    pub fn get_mouse_events(&self) -> &[(bool, MouseButton)]{
        &self.mouse_events
    }
    #[inline]
    /// Checks whether a key is pressed down
    pub fn is_down(&self, key: &VirtualKeyCode) -> bool{
        self.down_keys.contains(key)
    }
}

/// Describes objects that can change because of events
pub trait Update{
    /// Changes the object depending on what has happened
    fn update(&mut self, &FrameInfo);
}

/// Macro for easily doing things if particular keys are down
/// # Example
///
/// ```rust
/// # macro_rules! is_down{($l_args:ident; $($($key:ident),+ => $b:block),+) => {}}
/// fn logic(player_y: &mut f32, info: korome::FrameInfo){
///     is_down!{info;
///         W, Up => {
///             player_y -= l_args.delta() as f32;
///         },
///         S, Down => {
///             player_y += l_args.delta() as f32;
///         }
///     };
/// }
/// ```
#[macro_export]
macro_rules! is_down{
    ( $info:ident; $( $( $key:ident ),+ => $b:block ),+ ) => {{
        $( if $( $info.is_down(&$crate::VirtualKeyCode::$key) )||+ $b )+
    }}
}
<commit_msg>Resolve conflict<commit_after>use std::collections::HashSet;

use super::{Graphics, Drawer};
use draw::resize;
use time::precise_time_s as time_s;

use glium::glutin::{Event, ElementState};

pub use glium::glutin::{VirtualKeyCode, MouseButton};

/// Describes a way to handle an update
pub trait State{
    /// Function that gets called each frame update, when this `State` is being run
    ///
    /// Returns whether to do something after the update has been handled
    fn frame(&mut self, closed: bool, FrameInfo, Drawer) -> StateAction;
}

impl<F> State for F where F: FnMut(bool, FrameInfo, Drawer) -> StateAction{
    fn frame(&mut self, c: bool, i: FrameInfo, d: Drawer) -> StateAction{
        (self)(c, i, d)
    }
}

/// Describes what to do after a frame update
pub enum StateAction{
    /// Says to continue without changing the state
    Continue,
    /// Says to change the state to the one specified
    ChangeTo(Box<State>),
    /// Says to close the game
    Close
}

/// Manages events and frames
pub struct GameManager<'a>{
    graphics: Graphics<'a>,
    last: f64,
    down_keys: HashSet<VirtualKeyCode>,
    mousepos: (f32, f32),
}

impl<'a> GameManager<'a>{
    #[inline]
    /// Creates a new `GameManager` from a `Graphics` object
    pub fn new(graphics: Graphics<'a>) -> Self {
        GameManager{
            graphics: graphics,
            last: time_s(),
            mousepos: (0., 0.),
            down_keys: HashSet::new()
        }
    }
    /// Runs the game with the specified initial state
    pub fn run(&mut self, initial_state: Box<State>){
        let mut current_state = initial_state;

        loop{
            let (c, fi, d) = self.next_frame();

            match current_state.frame(c, fi, d){
                StateAction::ChangeTo(new) => current_state = new,
                StateAction::Continue      => (),
                StateAction::Close         => break,
            }
        }
    }

    /// Runs the game until the user tries to close the window
    pub fn run_until_closed<F: FnMut(FrameInfo, Drawer)>(&mut self, mut f: F){
        while let (false, frame_info, drawer) = self.next_frame() {
            f(frame_info, drawer)
        }
    }

    /// Returns a tuple of a `bool` (which is `true` if the user tried
    /// to close the window), a `FrameInfo` and a `Drawer`
    pub fn next_frame(&mut self) -> (bool, FrameInfo, Drawer){
        let mut keys = Vec::new();
        let mut mouses = Vec::new();
        let mut closed = false;

        let mut resized = None::<(u32, u32)>;

        for ev in self.graphics.poll_events() {
            match ev {
                Event::Closed => closed = true,
                Event::KeyboardInput(es, _, Some(vkc)) => match es{
                    ElementState::Pressed  => {
                        self.down_keys.insert( vkc);
                        keys.push((true , vkc));
                    },
                    ElementState::Released => {
                        self.down_keys.remove(&vkc);
                        keys.push((false, vkc));
                    }
                },
                Event::MouseMoved(pos) => {
                    let (w, h) = self.graphics.get_h_size();
                    let (x, y) = pos;

                    self.mousepos = (x as f32 - w, h - y as f32);
                },
                // This is only neccessary because `graphics` gets immutably borrowed for this for-loop
                Event::Resized(w, h) => resized = Some((w, h)),
                Event::MouseInput(state, button) => mouses.push((state == ElementState::Pressed, button)),
                _ => ()
            }
        }

        if let Some((w, h)) = resized{
            resize(&mut self.graphics, w, h);
        }

        let now = time_s();
        let delta = now - self.last;
        self.last = now;

        let update = FrameInfo{
            delta    : delta,
            key_events: keys,
            mouse_events: mouses,
            down_keys: &self.down_keys,
            mousepos : self.mousepos
        };

        (closed, update, Drawer::new(&self.graphics))
    }
}

/// Wraps together useful data about what has happened (e.g. events)
#[derive(Debug)]
pub struct FrameInfo<'a>{
    /// The amount of time passed since last frame
    pub delta: f64,
    /// The last position of the mouse on the screen
    pub mousepos: (f32, f32),
    mouse_events: Vec<(bool, MouseButton)>,
    key_events: Vec<(bool, VirtualKeyCode)>,

    // All keys that are pressed down
    down_keys: &'a HashSet<VirtualKeyCode>
}

impl<'a> FrameInfo<'a>{
    #[inline]
    /// Returns a slice of all key events that have happened
    pub fn get_key_events(&self) -> &[(bool, VirtualKeyCode)]{
        &self.key_events
    }
    #[inline]
    /// Returns a slice of all key events that have happened
    pub fn get_mouse_events(&self) -> &[(bool, MouseButton)]{
        &self.mouse_events
    }
    #[inline]
    /// Checks whether a key is pressed down
    pub fn is_down(&self, key: &VirtualKeyCode) -> bool{
        self.down_keys.contains(key)
    }
}

/// Describes objects that can change because of events
pub trait Update{
    /// Changes the object depending on what has happened
    fn update(&mut self, &FrameInfo);
}

/// Macro for easily doing things if particular keys are down
/// # Example
///
/// ```rust
/// # macro_rules! is_down{($l_args:ident; $($($key:ident),+ => $b:block),+) => {}}
/// fn logic(player_y: &mut f32, info: korome::FrameInfo){
///     is_down!{info;
///         W, Up => {
///             player_y -= l_args.delta() as f32;
///         },
///         S, Down => {
///             player_y += l_args.delta() as f32;
///         }
///     };
/// }
/// ```
#[macro_export]
macro_rules! is_down{
    ( $info:ident; $( $( $key:ident ),+ => $b:block ),+ ) => {{
        $( if $( $info.is_down(&$crate::VirtualKeyCode::$key) )||+ $b )+
    }}
}
<|endoftext|>


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

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Ben Hirsch <benhirsch24@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate collections;

use collections::string::String;
use std::old_io::File;

#[derive(Debug)]
enum Radix { Decimal, Hexadecimal, Octal, Binary }

pub fn uumain(args: Vec<String>) -> i32 {
    let opts = [
        getopts::optopt("A", "address-radix",
                        "Select the base in which file offsets are printed.", "RADIX"),
        getopts::optopt("j", "skip-bytes",
                        "Skip bytes input bytes before formatting and writing.", "BYTES"),
        getopts::optopt("N", "read-bytes",
                        "limit dump to BYTES input bytes", "BYTES"),
        getopts::optopt("S", "strings",
                        ("output strings of at least BYTES graphic chars. 3 is assumed when \
                          BYTES is not specified."),
                        "BYTES"),
        getopts::optopt("t", "format", "select output format or formats", "TYPE"),
        getopts::optflag("v", "output-duplicates", "do not use * to mark line suppression"),
        getopts::optopt("w", "width",
                        ("output BYTES bytes per output line. 32 is implied when BYTES is not \
                          specified."),
                        "BYTES"),
        getopts::optflag("h", "help", "display this help and exit."),
        getopts::optflag("", "version", "output version information and exit."),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let input_offset_base = match parse_radix(matches.opt_str("A")) {
        Ok(r) => r,
        Err(f) => { panic!("Invalid -A/--address-radix\n{}", f) }
    };

    let fname = match args.last() {
        Some(n) => n,
        None => { panic!("Need fname for now") ; }
    };

    main(&input_offset_base, fname.as_slice());

    0
}

fn main(input_offset_base: &Radix, fname: &str) {
    let mut f = match File::open(&Path::new(fname)) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e)
    };

    let mut addr = 0;
    let bytes = &mut [b'\x00'; 16];
    loop {
        match f.read(bytes) {
            Ok(n) => {
                print_with_radix(input_offset_base, addr);
                for b in range(0, n / std::u16::BYTES as usize) {
                    let bs = &bytes[(2 * b) .. (2 * b + 2)];
                    let p: u16 = (bs[1] as u16) << 8 | bs[0] as u16;
                    print!(" {:06o}", p);
                }
                if n % std::u16::BYTES as usize == 1 {
                    print!(" {:06o}", bytes[n - 1]);
                }
                print!("\n");
                addr += n;
            },
            Err(_) => {
                print_with_radix(input_offset_base, addr);
                break;
            }
        };
    };
}

fn parse_radix(radix_str: Option<String>) -> Result<Radix, &'static str> {
    match radix_str {
        None => Ok(Radix::Octal),
        Some(s) => {
            let st = s.into_bytes();
            if st.len() != 1 {
                Err("Radix must be one of [d, o, b, x]\n")
            } else {
                let radix: char = *(st.get(0)
                                      .expect("byte string of length 1 lacks a 0th elem")) as char;
                match radix {
                    'd' => Ok(Radix::Decimal),
                    'x' => Ok(Radix::Hexadecimal),
                    'o' => Ok(Radix::Octal),
                    'b' => Ok(Radix::Binary),
                    _ => Err("Radix must be one of [d, o, b, x]\n")
                }
            }
        }
    }
}

fn print_with_radix(r: &Radix, x: usize) {
    // TODO(keunwoo): field widths should be based on sizeof(x), or chosen dynamically based on the
    // expected range of address values.  Binary in particular is not great here.
    match *r {
        Radix::Decimal => print!("{:07}", x),
        Radix::Hexadecimal => print!("{:07X}", x),
        Radix::Octal => print!("{:07o}", x),
        Radix::Binary => print!("{:07b}", x)
    }
}
<commit_msg>Fix od.<commit_after>#![crate_name = "od"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Ben Hirsch <benhirsch24@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;

use std::fs::File;
use std::io::Read;
use std::mem;
use std::path::Path;

#[derive(Debug)]
enum Radix { Decimal, Hexadecimal, Octal, Binary }

pub fn uumain(args: Vec<String>) -> i32 {
    let opts = [
        getopts::optopt("A", "address-radix",
                        "Select the base in which file offsets are printed.", "RADIX"),
        getopts::optopt("j", "skip-bytes",
                        "Skip bytes input bytes before formatting and writing.", "BYTES"),
        getopts::optopt("N", "read-bytes",
                        "limit dump to BYTES input bytes", "BYTES"),
        getopts::optopt("S", "strings",
                        ("output strings of at least BYTES graphic chars. 3 is assumed when \
                          BYTES is not specified."),
                        "BYTES"),
        getopts::optopt("t", "format", "select output format or formats", "TYPE"),
        getopts::optflag("v", "output-duplicates", "do not use * to mark line suppression"),
        getopts::optopt("w", "width",
                        ("output BYTES bytes per output line. 32 is implied when BYTES is not \
                          specified."),
                        "BYTES"),
        getopts::optflag("h", "help", "display this help and exit."),
        getopts::optflag("", "version", "output version information and exit."),
    ];

    let matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => panic!("Invalid options\n{}", f)
    };

    let input_offset_base = match parse_radix(matches.opt_str("A")) {
        Ok(r) => r,
        Err(f) => { panic!("Invalid -A/--address-radix\n{}", f) }
    };

    let fname = match args.last() {
        Some(n) => n,
        None => { panic!("Need fname for now") ; }
    };

    main(&input_offset_base, &fname);

    0
}

fn main(input_offset_base: &Radix, fname: &str) {
    let mut f = match File::open(Path::new(fname)) {
        Ok(f) => f,
        Err(e) => panic!("file error: {}", e)
    };

    let mut addr = 0;
    let bytes = &mut [b'\x00'; 16];
    loop {
        match f.read(bytes) {
            Ok(n) => {
                print_with_radix(input_offset_base, addr);
                for b in 0 .. n / mem::size_of::<u16>() {
                    let bs = &bytes[(2 * b) .. (2 * b + 2)];
                    let p: u16 = (bs[1] as u16) << 8 | bs[0] as u16;
                    print!(" {:06o}", p);
                }
                if n % mem::size_of::<u16>() == 1 {
                    print!(" {:06o}", bytes[n - 1]);
                }
                print!("\n");
                addr += n;
            },
            Err(_) => {
                print_with_radix(input_offset_base, addr);
                break;
            }
        };
    };
}

fn parse_radix(radix_str: Option<String>) -> Result<Radix, &'static str> {
    match radix_str {
        None => Ok(Radix::Octal),
        Some(s) => {
            let st = s.into_bytes();
            if st.len() != 1 {
                Err("Radix must be one of [d, o, b, x]\n")
            } else {
                let radix: char = *(st.get(0)
                                      .expect("byte string of length 1 lacks a 0th elem")) as char;
                match radix {
                    'd' => Ok(Radix::Decimal),
                    'x' => Ok(Radix::Hexadecimal),
                    'o' => Ok(Radix::Octal),
                    'b' => Ok(Radix::Binary),
                    _ => Err("Radix must be one of [d, o, b, x]\n")
                }
            }
        }
    }
}

fn print_with_radix(r: &Radix, x: usize) {
    // TODO(keunwoo): field widths should be based on sizeof(x), or chosen dynamically based on the
    // expected range of address values.  Binary in particular is not great here.
    match *r {
        Radix::Decimal => print!("{:07}", x),
        Radix::Hexadecimal => print!("{:07X}", x),
        Radix::Octal => print!("{:07o}", x),
        Radix::Binary => print!("{:07b}", x)
    }
}
<|endoftext|>