<commit_before>use std::io::{self, Read, Write};

use IntoRawMode;

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    F(u8),
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Invalid character code.
    Invalid,
    /// Null byte.
    Null,

    #[allow(missing_docs)]
    #[doc(hidden)]
    __IsNotComplete
}

/// An iterator over input keys.
#[cfg(feature = "nightly")]
pub struct Keys<I> {
    chars: I,
}

#[cfg(feature = "nightly")]
impl<I: Iterator<Item = Result<char, io::CharsError>>> Iterator for Keys<I> {
    type Item = Result<Key, io::CharsError>;

    fn next(&mut self) -> Option<Result<Key, io::CharsError>> {
        Some(match self.chars.next() {
            Some(Ok('\x1B')) => Ok(match self.chars.next() {
                Some(Ok('O')) => match self.chars.next() {
                    Some(Ok('P')) => Key::F(1),
                    Some(Ok('Q')) => Key::F(2),
                    Some(Ok('R')) => Key::F(3),
                    Some(Ok('S')) => Key::F(4),
                    _ => Key::Invalid,
                },
                Some(Ok('[')) => match self.chars.next() {
                    Some(Ok('D')) => Key::Left,
                    Some(Ok('C')) => Key::Right,
                    Some(Ok('A')) => Key::Up,
                    Some(Ok('B')) => Key::Down,
                    Some(Ok('H')) => Key::Home,
                    Some(Ok('F')) => Key::End,
                    Some(Ok(c @ '1' ... '6')) => match self.chars.next() {
                        Some(Ok('~')) => match c {
                            '1' | '7' => Key::Home,
                            '2' | '8' => Key::Insert,
                            '3' => Key::Delete,
                            '4' => Key::End,
                            '5' => Key::PageUp,
                            '6' => Key::PageDown,
                            _ => Key::Invalid,
                        },
                        Some(Ok(k @ '0' ... '9')) => match self.chars.next() {
                            Some(Ok('~')) => match (c, k) {
                                ('1', '1') => Key::F(1),
                                ('1', '2') => Key::F(2),
                                ('1', '3') => Key::F(3),
                                ('1', '4') => Key::F(4),
                                ('1', '5') => Key::F(5),
                                ('1', '7') => Key::F(6),
                                ('1', '8') => Key::F(7),
                                ('1', '9') => Key::F(8),
                                ('2', '0') => Key::F(9),
                                ('2', '1') => Key::F(10),
                                ('2', '3') => Key::F(11),
                                ('2', '4') => Key::F(12),
                                _ => Key::Invalid,
                            },
                            _ => Key::Invalid,
                        },
                        _ => Key::Invalid,
                    },
                    _ => Key::Invalid,
                },
                Some(Ok(c)) => Key::Alt(c),
                Some(Err(_)) | None => Key::Invalid,
            }),
            Some(Ok('\n')) | Some(Ok('\r')) => Ok(Key::Char('\n')),
            Some(Ok('\t')) => Ok(Key::Char('\t')),
            Some(Ok('\x7F')) => Ok(Key::Backspace),
            Some(Ok(c @ '\x01' ... '\x1A')) => Ok(Key::Ctrl((c as u8 - 0x1  + b'a') as char)),
            Some(Ok(c @ '\x1C' ... '\x1F')) => Ok(Key::Ctrl((c as u8 - 0x1C + b'4') as char)),
            Some(Ok('\0')) => Ok(Key::Null),
            Some(Ok(c)) => Ok(Key::Char(c)),
            Some(Err(e)) => Err(e),
            None => return None,
        })
    }
}

/// Extension to `Read` trait.
pub trait TermRead {
    /// An iterator over key inputs.
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<Self>> where Self: Sized;

    /// Read a line.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_line(&mut self) -> io::Result<Option<String>>;

    /// Read a password.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_passwd<W: Write>(&mut self, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = try!(writer.into_raw_mode());
        self.read_line()
    }
}

impl<R: Read> TermRead for R {
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<R>> {
        Keys {
            chars: self.chars(),
        }
    }

    fn read_line(&mut self) -> io::Result<Option<String>> {
        let mut buf = Vec::with_capacity(30);

        for c in self.bytes() {
            match c {
                Err(e) => return Err(e),
                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
                Ok(0x7f) => { buf.pop(); },
                Ok(b'\n') | Ok(b'\r') => break,
                Ok(c) => buf.push(c),
            }
        }

        let string = try!(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
        Ok(Some(string))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io;

    #[cfg(feature = "nightly")]
    #[test]
    fn test_keys() {
        let mut i = b"\x1Bayo\x7F\x1B[D".keys();

        assert_eq!(i.next().unwrap().unwrap(), Key::Alt('a'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('y'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('o'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Backspace);
        assert_eq!(i.next().unwrap().unwrap(), Key::Left);
        assert!(i.next().is_none());
    }

    fn line_match(a: &str, b: Option<&str>) {
        let mut sink = io::sink();

        let line = a.as_bytes().read_line().unwrap();
        let pass = a.as_bytes().read_passwd(&mut sink).unwrap();

        // godammit rustc

        assert_eq!(line, pass);

        if let Some(l) = line {
            assert_eq!(Some(l.as_str()), b);
        } else {
            assert!(b.is_none());
        }
    }

    #[test]
    fn test_read() {
        let test1 = "this is the first test";
        let test2 = "this is the second test";

        line_match(test1, Some(test1));
        line_match(test2, Some(test2));
    }

    #[test]
    fn test_backspace() {
        line_match("this is the\x7f first\x7f\x7f test", Some("this is th fir test"));
        line_match("this is the seco\x7fnd test\x7f", Some("this is the secnd tes"));
    }

    #[test]
    fn test_end() {
        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ", Some("abc"));
        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA", Some("hello"));
    }

    #[test]
    fn test_abort() {
        line_match("abc\x03https://www.youtube.com/watch?v=dQw4w9WgXcQ", None);
        line_match("hello\x04https://www.youtube.com/watch?v=yPYZpwSpKmA", None);
    }
}
<commit_msg>added doc for function keys<commit_after>use std::io::{self, Read, Write};

use IntoRawMode;

/// A key.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    ///
    /// Only function keys 1 through 12 are supported.
    F(u8),
    /// Normal character.
    Char(char),
    /// Alt modified character.
    Alt(char),
    /// Ctrl modified character.
    ///
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    /// Invalid character code.
    Invalid,
    /// Null byte.
    Null,

    #[allow(missing_docs)]
    #[doc(hidden)]
    __IsNotComplete
}

/// An iterator over input keys.
#[cfg(feature = "nightly")]
pub struct Keys<I> {
    chars: I,
}

#[cfg(feature = "nightly")]
impl<I: Iterator<Item = Result<char, io::CharsError>>> Iterator for Keys<I> {
    type Item = Result<Key, io::CharsError>;

    fn next(&mut self) -> Option<Result<Key, io::CharsError>> {
        Some(match self.chars.next() {
            Some(Ok('\x1B')) => Ok(match self.chars.next() {
                Some(Ok('O')) => match self.chars.next() {
                    Some(Ok('P')) => Key::F(1),
                    Some(Ok('Q')) => Key::F(2),
                    Some(Ok('R')) => Key::F(3),
                    Some(Ok('S')) => Key::F(4),
                    _ => Key::Invalid,
                },
                Some(Ok('[')) => match self.chars.next() {
                    Some(Ok('D')) => Key::Left,
                    Some(Ok('C')) => Key::Right,
                    Some(Ok('A')) => Key::Up,
                    Some(Ok('B')) => Key::Down,
                    Some(Ok('H')) => Key::Home,
                    Some(Ok('F')) => Key::End,
                    Some(Ok(c @ '1' ... '6')) => match self.chars.next() {
                        Some(Ok('~')) => match c {
                            '1' | '7' => Key::Home,
                            '2' | '8' => Key::Insert,
                            '3' => Key::Delete,
                            '4' => Key::End,
                            '5' => Key::PageUp,
                            '6' => Key::PageDown,
                            _ => Key::Invalid,
                        },
                        Some(Ok(k @ '0' ... '9')) => match self.chars.next() {
                            Some(Ok('~')) => match (c, k) {
                                ('1', '1') => Key::F(1),
                                ('1', '2') => Key::F(2),
                                ('1', '3') => Key::F(3),
                                ('1', '4') => Key::F(4),
                                ('1', '5') => Key::F(5),
                                ('1', '7') => Key::F(6),
                                ('1', '8') => Key::F(7),
                                ('1', '9') => Key::F(8),
                                ('2', '0') => Key::F(9),
                                ('2', '1') => Key::F(10),
                                ('2', '3') => Key::F(11),
                                ('2', '4') => Key::F(12),
                                _ => Key::Invalid,
                            },
                            _ => Key::Invalid,
                        },
                        _ => Key::Invalid,
                    },
                    _ => Key::Invalid,
                },
                Some(Ok(c)) => Key::Alt(c),
                Some(Err(_)) | None => Key::Invalid,
            }),
            Some(Ok('\n')) | Some(Ok('\r')) => Ok(Key::Char('\n')),
            Some(Ok('\t')) => Ok(Key::Char('\t')),
            Some(Ok('\x7F')) => Ok(Key::Backspace),
            Some(Ok(c @ '\x01' ... '\x1A')) => Ok(Key::Ctrl((c as u8 - 0x1  + b'a') as char)),
            Some(Ok(c @ '\x1C' ... '\x1F')) => Ok(Key::Ctrl((c as u8 - 0x1C + b'4') as char)),
            Some(Ok('\0')) => Ok(Key::Null),
            Some(Ok(c)) => Ok(Key::Char(c)),
            Some(Err(e)) => Err(e),
            None => return None,
        })
    }
}

/// Extension to `Read` trait.
pub trait TermRead {
    /// An iterator over key inputs.
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<Self>> where Self: Sized;

    /// Read a line.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_line(&mut self) -> io::Result<Option<String>>;

    /// Read a password.
    ///
    /// EOT and ETX will abort the prompt, returning `None`. Newline or carriage return will
    /// complete the input.
    fn read_passwd<W: Write>(&mut self, writer: &mut W) -> io::Result<Option<String>> {
        let _raw = try!(writer.into_raw_mode());
        self.read_line()
    }
}

impl<R: Read> TermRead for R {
    #[cfg(feature = "nightly")]
    fn keys(self) -> Keys<io::Chars<R>> {
        Keys {
            chars: self.chars(),
        }
    }

    fn read_line(&mut self) -> io::Result<Option<String>> {
        let mut buf = Vec::with_capacity(30);

        for c in self.bytes() {
            match c {
                Err(e) => return Err(e),
                Ok(0) | Ok(3) | Ok(4) => return Ok(None),
                Ok(0x7f) => { buf.pop(); },
                Ok(b'\n') | Ok(b'\r') => break,
                Ok(c) => buf.push(c),
            }
        }

        let string = try!(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
        Ok(Some(string))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io;

    #[cfg(feature = "nightly")]
    #[test]
    fn test_keys() {
        let mut i = b"\x1Bayo\x7F\x1B[D".keys();

        assert_eq!(i.next().unwrap().unwrap(), Key::Alt('a'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('y'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Char('o'));
        assert_eq!(i.next().unwrap().unwrap(), Key::Backspace);
        assert_eq!(i.next().unwrap().unwrap(), Key::Left);
        assert!(i.next().is_none());
    }

    fn line_match(a: &str, b: Option<&str>) {
        let mut sink = io::sink();

        let line = a.as_bytes().read_line().unwrap();
        let pass = a.as_bytes().read_passwd(&mut sink).unwrap();

        // godammit rustc

        assert_eq!(line, pass);

        if let Some(l) = line {
            assert_eq!(Some(l.as_str()), b);
        } else {
            assert!(b.is_none());
        }
    }

    #[test]
    fn test_read() {
        let test1 = "this is the first test";
        let test2 = "this is the second test";

        line_match(test1, Some(test1));
        line_match(test2, Some(test2));
    }

    #[test]
    fn test_backspace() {
        line_match("this is the\x7f first\x7f\x7f test", Some("this is th fir test"));
        line_match("this is the seco\x7fnd test\x7f", Some("this is the secnd tes"));
    }

    #[test]
    fn test_end() {
        line_match("abc\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ", Some("abc"));
        line_match("hello\rhttps://www.youtube.com/watch?v=yPYZpwSpKmA", Some("hello"));
    }

    #[test]
    fn test_abort() {
        line_match("abc\x03https://www.youtube.com/watch?v=dQw4w9WgXcQ", None);
        line_match("hello\x04https://www.youtube.com/watch?v=yPYZpwSpKmA", None);
    }
}
<|endoftext|>


<commit_before>use std;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum IpNet {
    V4(Ipv4Net),
    V6(Ipv6Net),
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv4Net {
    addr: Ipv4Addr,
    prefix_len: u8,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv6Net {
    addr: Ipv6Addr,
    prefix_len: u8,
}

// For the time being deref method calls to the IpAddr implemenations.

/*impl std::ops::Deref for IpNet {
    type Target = IpAddr;
    fn deref(&self) -> &Self::Target {
        match *self {
            IpNet::V4(ref a) => a.addr,
            IpNet::V6(ref a) => a.addr,
        }
    }
}*/

impl std::ops::Deref for Ipv4Net {
    type Target = Ipv4Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl std::ops::Deref for Ipv6Net {
    type Target = Ipv6Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl IpNet {
    pub fn supernet(&self) -> IpNet {
        match *self {
            IpNet::V4(ref a) => IpNet::V4(a.supernet()),
            IpNet::V6(ref a) => IpNet::V6(a.supernet()),
        }
    }

    pub fn contains(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
            (_, _) => false,
        }
    }

    pub fn sibling(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.sibling(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.sibling(b),
            (_, _) => false,
        }
    }
}

impl Ipv4Net {
    pub fn new(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
        // TODO: Should error if prefix_len > 32 as prefix_len <= 32 is
        // assumed in subsequent methods.
        Ipv4Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn netmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len > 0 {
                0xffffffff << 32 - self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn hostmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(
            // Avoid deny(exceeding_bitshifts)
            if self.prefix_len < 32 {
                0xffffffff >> self.prefix_len
            }
            else {
                0x00000000
            }
        )
    }

    pub fn network(&self) -> Ipv4Addr {
        // BitAnd is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) & u32::from(self.netmask()))
    }

    pub fn broadcast(&self) -> Ipv4Addr {
        // BitOr is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) | u32::from(self.hostmask()))
    }

    pub fn supernet(&self) -> Ipv4Net {
        Ipv4Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Should the parameter be depth, as in the number of
    // divisions to make, or new_prefix_len (self explanatory), or
    // num_subnets? I suspect in use the later two will be more useful.
    // TODO: Should this be an iterator?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv4Net> {
        // TODO: Need to test bounds of new_prefix_len and error.
        // Or perhaps just set to 32 in that case.
        // TODO: std::ops::Add missing for Ipv4Addr
        let rng = 2u32.pow(32 - new_prefix_len as u32);
        let mut net = u32::from(self.network());
        let end = u32::from(self.broadcast());
        let mut res: Vec<Ipv4Net> = Vec::new();

        while net < end {
            res.push(Ipv4Net::new(Ipv4Addr::from(net), new_prefix_len));
            net += rng;
        }
        res

    }

    pub fn contains(&self, other: &Ipv4Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv4Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

impl Ipv6Net {
    pub fn new(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
        // TODO: Should error if prefix_len > 128 as prefix_len <= 128
        // is assumed in subsequent methods.
        Ipv6Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn addr(&self) -> Ipv6Addr {
        self.addr
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn netmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len > 0 { 0xffff_ffff_ffff_ffff << 64u8.saturating_sub(self.prefix_len) } else { 0x0 };
        let b: u64 = if self.prefix_len > 64 { 0xffff_ffff_ffff_ffff << 128 - self.prefix_len } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn hostmask(&self) -> Ipv6Addr {
        // Avoid deny(exceeding_bitshifts)
        let a: u64 = if self.prefix_len < 64 { 0xffff_ffff_ffff_ffff >> self.prefix_len } else { 0x0 };
        let b: u64 = if self.prefix_len < 128 { 0xffff_ffff_ffff_ffff >> self.prefix_len.saturating_sub(64) } else { 0x0 };

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn network(&self) -> Ipv6Addr {
        // BitAnd is not implemented for Ipv6Addr.
        let ip = self.segments();
        let m = self.netmask().segments();

        Ipv6Addr::new(
            ip[0] & m[0], ip[1] & m[1], ip[2] & m[2], ip[3] & m[3],
            ip[4] & m[4], ip[5] & m[5], ip[6] & m[6], ip[7] & m[7]
        )
    }

    // TODO: Technically there is no such thing as a broadcast. Perhaps
    // we should change the network() and broadcast() methods to be
    // first() and last() or similar.
    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn broadcast(&self) -> Ipv6Addr {
        // BitOr is not implemented for Ipv4Addr.
        let ip = self.segments();
        let m = self.hostmask().segments();

        Ipv6Addr::new(
            ip[0] | m[0], ip[1] | m[1], ip[2] | m[2], ip[3] | m[3],
            ip[4] | m[4], ip[5] | m[5], ip[6] | m[6], ip[7] | m[7]
        )
    }

    pub fn supernet(&self) -> Ipv6Net {
        Ipv6Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Is there a nicer way to do this? Using u128 types would be
    // nice but they're not marked as stable yet. Should this return an
    // iterator instead of a vector?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv6Net> {
        // TODO: Need to implement a proper error handling scheme.
        if new_prefix_len <= self.prefix_len {
            return Vec::new();
        }

        let mut network = ipv6_addr_into_double_u64(self.network());
        let broadcast = ipv6_addr_into_double_u64(self.broadcast());

        let mask: [u64; 2] = [
            if new_prefix_len < 64 { 0xffff_ffff_ffff_ffff >> new_prefix_len } else { 0x0 },
            if new_prefix_len >= 64 && new_prefix_len < 128 { 0xffff_ffff_ffff_ffff >> new_prefix_len - 64 } else { 0x0 }
        ];

        let mut res: Vec<Ipv6Net> = Vec::new();

        while network < broadcast {
            res.push(Ipv6Net::new(ipv6_addr_from_double_u64(network), new_prefix_len));

            network[0] |= mask[0];
            network[1] |= mask[1];

            let (lo, ov) = network[1].overflowing_add(1);
            network[1] = lo;

            if ov {
                network[0] += 1;
            }
        }

        res
    }

    pub fn contains(&self, other: &Ipv6Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv6Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_from_double_u64(segments: [u64; 2]) -> Ipv6Addr {
    let (hi, lo) = (segments[0], segments[1]);
    Ipv6Addr::new(
        (hi >> 48) as u16, (hi >> 32) as u16, (hi >> 16) as u16, hi as u16,
        (lo >> 48) as u16, (lo >> 32) as u16, (lo >> 16) as u16, lo as u16
    )
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_into_double_u64(ip: Ipv6Addr) -> [u64; 2] {
    let ip = ip.octets();
    [
        ((ip[0] as u64) << 56) + ((ip[1] as u64) << 48) +
        ((ip[2] as u64) << 40) + ((ip[3] as u64) << 32) +
        ((ip[4] as u64) << 24) + ((ip[5] as u64) << 16) +
        ((ip[6] as u64) << 8) + (ip[7] as u64),
        ((ip[8] as u64) << 56) + ((ip[9] as u64) << 48) +
        ((ip[10] as u64) << 40) + ((ip[11] as u64) << 32) +
        ((ip[12] as u64) << 24) + ((ip[13] as u64) << 16) +
        ((ip[14] as u64) << 8) + (ip[15] as u64),
    ]
}

impl fmt::Display for IpNet {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNet::V4(ref a) => a.fmt(fmt),
            IpNet::V6(ref a) => a.fmt(fmt),
        }
    }
}

impl fmt::Display for Ipv4Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}

impl fmt::Display for Ipv6Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}
<commit_msg>Implemented SaturatingShl and SaturatingShr traits to make all of the necessary bitshifting easier.<commit_after>use std;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};

// TODO: Would it be possible to get something like this in libcore?
trait SaturatingShl<RHS> {
    type Output;
    fn saturating_shl(self, rhs: RHS) -> Self::Output;
}

macro_rules! saturating_shl_impl {
    ($t:ty, $f:ty, $w:expr) => (
        impl SaturatingShl<$f> for $t {
            type Output = $t;

            #[inline]
            fn saturating_shl(self, other: $f) -> $t {
                if other < $w { self << other } else { 0 }
            }
        }
    )
}

trait SaturatingShr<RHS> {
    type Output;
    fn saturating_shr(self, rhs: RHS) -> Self::Output;
}

macro_rules! saturating_shr_impl {
    ($t:ty, $f:ty, $w:expr) => (
        impl SaturatingShr<$f> for $t {
            type Output = $t;

            #[inline]
            fn saturating_shr(self, other: $f) -> $t {
                if other < $w { self >> other } else { 0 }
            }
        }
    )
}

saturating_shl_impl!(u32, u8, 32);
saturating_shr_impl!(u32, u8, 32);
saturating_shl_impl!(u64, u8, 64);
saturating_shr_impl!(u64, u8, 64);

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub enum IpNet {
    V4(Ipv4Net),
    V6(Ipv6Net),
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv4Net {
    addr: Ipv4Addr,
    prefix_len: u8,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
pub struct Ipv6Net {
    addr: Ipv6Addr,
    prefix_len: u8,
}

// For the time being deref method calls to the IpAddr implemenations.

/*impl std::ops::Deref for IpNet {
    type Target = IpAddr;
    fn deref(&self) -> &Self::Target {
        match *self {
            IpNet::V4(ref a) => a.addr,
            IpNet::V6(ref a) => a.addr,
        }
    }
}*/

impl std::ops::Deref for Ipv4Net {
    type Target = Ipv4Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl std::ops::Deref for Ipv6Net {
    type Target = Ipv6Addr;
    fn deref(&self) -> &Self::Target {
        &self.addr
    }
}

impl IpNet {
    pub fn supernet(&self) -> IpNet {
        match *self {
            IpNet::V4(ref a) => IpNet::V4(a.supernet()),
            IpNet::V6(ref a) => IpNet::V6(a.supernet()),
        }
    }

    pub fn contains(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
            (_, _) => false,
        }
    }

    pub fn sibling(&self, other: &IpNet) -> bool {
        match (*self, *other) {
            (IpNet::V4(ref a), IpNet::V4(ref b)) => a.sibling(b),
            (IpNet::V6(ref a), IpNet::V6(ref b)) => a.sibling(b),
            (_, _) => false,
        }
    }
}

impl Ipv4Net {
    pub fn new(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
        // TODO: Should error if prefix_len > 32 as prefix_len <= 32 is
        // assumed in subsequent methods.
        Ipv4Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn netmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(0xffffffffu32.saturating_shl(32 - self.prefix_len))
    }

    pub fn hostmask(&self) -> Ipv4Addr {
        Ipv4Addr::from(0xffffffffu32.saturating_shr(self.prefix_len))
    }

    pub fn network(&self) -> Ipv4Addr {
        // BitAnd is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) & u32::from(self.netmask()))
    }

    pub fn broadcast(&self) -> Ipv4Addr {
        // BitOr is not implemented for Ipv4Addr.
        Ipv4Addr::from(u32::from(self.addr) | u32::from(self.hostmask()))
    }

    pub fn supernet(&self) -> Ipv4Net {
        Ipv4Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Should the parameter be depth, as in the number of
    // divisions to make, or new_prefix_len (self explanatory), or
    // num_subnets? I suspect in use the later two will be more useful.
    // TODO: Should this be an iterator?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv4Net> {
        // TODO: Need to test bounds of new_prefix_len and error.
        // Or perhaps just set to 32 in that case.
        // TODO: std::ops::Add missing for Ipv4Addr
        let rng = 2u32.pow(32 - new_prefix_len as u32);
        let mut net = u32::from(self.network());
        let end = u32::from(self.broadcast());
        let mut res: Vec<Ipv4Net> = Vec::new();

        while net < end {
            res.push(Ipv4Net::new(Ipv4Addr::from(net), new_prefix_len));
            net += rng;
        }
        res

    }

    pub fn contains(&self, other: &Ipv4Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv4Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

impl Ipv6Net {
    pub fn new(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
        // TODO: Should error if prefix_len > 128 as prefix_len <= 128
        // is assumed in subsequent methods.
        Ipv6Net { addr: ip, prefix_len: prefix_len, }
    }

    pub fn addr(&self) -> Ipv6Addr {
        self.addr
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn netmask(&self) -> Ipv6Addr {
        let a = 0xffff_ffff_ffff_ffffu64.saturating_shl(64u8.saturating_sub(self.prefix_len));
        let b = 0xffff_ffff_ffff_ffffu64.saturating_shl(128u8.saturating_sub(self.prefix_len));

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn hostmask(&self) -> Ipv6Addr {
        let a = 0xffff_ffff_ffff_ffffu64.saturating_shr(self.prefix_len);
        let b = 0xffff_ffff_ffff_ffffu64.saturating_shr(self.prefix_len.saturating_sub(64));

        Ipv6Addr::new(
            (a >> 48) as u16, (a >> 32) as u16, (a >> 16) as u16, a as u16,
            (b >> 48) as u16, (b >> 32) as u16, (b >> 16) as u16, b as u16
        )
    }

    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn network(&self) -> Ipv6Addr {
        // BitAnd is not implemented for Ipv6Addr.
        let ip = self.segments();
        let m = self.netmask().segments();

        Ipv6Addr::new(
            ip[0] & m[0], ip[1] & m[1], ip[2] & m[2], ip[3] & m[3],
            ip[4] & m[4], ip[5] & m[5], ip[6] & m[6], ip[7] & m[7]
        )
    }

    // TODO: Technically there is no such thing as a broadcast. Perhaps
    // we should change the network() and broadcast() methods to be
    // first() and last() or similar.
    // The u128 type would be nice here, but it's not marked stable yet.
    pub fn broadcast(&self) -> Ipv6Addr {
        // BitOr is not implemented for Ipv4Addr.
        let ip = self.segments();
        let m = self.hostmask().segments();

        Ipv6Addr::new(
            ip[0] | m[0], ip[1] | m[1], ip[2] | m[2], ip[3] | m[3],
            ip[4] | m[4], ip[5] | m[5], ip[6] | m[6], ip[7] | m[7]
        )
    }

    pub fn supernet(&self) -> Ipv6Net {
        Ipv6Net::new(self.addr.clone(), self.prefix_len - 1)
    }

    // TODO: Is there a nicer way to do this? Using u128 types would be
    // nice but they're not marked as stable yet. Should this return an
    // iterator instead of a vector?
    pub fn subnets(&self, new_prefix_len: u8) -> Vec<Ipv6Net> {
        // TODO: Need to implement a proper error handling scheme.
        if new_prefix_len <= self.prefix_len {
            return Vec::new();
        }

        let mut network = ipv6_addr_into_double_u64(self.network());
        let broadcast = ipv6_addr_into_double_u64(self.broadcast());

        let mask: [u64; 2] = [
            0xffff_ffff_ffff_ffffu64.saturating_shr(new_prefix_len),
            0xffff_ffff_ffff_ffffu64.saturating_shr(new_prefix_len.saturating_sub(64)),
        ];

        let mut res: Vec<Ipv6Net> = Vec::new();

        while network < broadcast {
            res.push(Ipv6Net::new(ipv6_addr_from_double_u64(network), new_prefix_len));

            network[0] |= mask[0];
            network[1] |= mask[1];

            let (lo, ov) = network[1].overflowing_add(1);
            network[1] = lo;

            if ov {
                network[0] += 1;
            }
        }

        res
    }

    pub fn contains(&self, other: &Ipv6Net) -> bool {
        self.network() <= other.network() && self.broadcast() >= other.broadcast()
    }

    pub fn sibling(&self, other: &Ipv6Net) -> bool {
        self.prefix_len == other.prefix_len && self.supernet().contains(other)
    }
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_from_double_u64(segments: [u64; 2]) -> Ipv6Addr {
    let (hi, lo) = (segments[0], segments[1]);
    Ipv6Addr::new(
        (hi >> 48) as u16, (hi >> 32) as u16, (hi >> 16) as u16, hi as u16,
        (lo >> 48) as u16, (lo >> 32) as u16, (lo >> 16) as u16, lo as u16
    )
}

// TODO: It would be nice to implement From on Ipv6Addr for this.
pub fn ipv6_addr_into_double_u64(ip: Ipv6Addr) -> [u64; 2] {
    let ip = ip.octets();
    [
        ((ip[0] as u64) << 56) + ((ip[1] as u64) << 48) +
        ((ip[2] as u64) << 40) + ((ip[3] as u64) << 32) +
        ((ip[4] as u64) << 24) + ((ip[5] as u64) << 16) +
        ((ip[6] as u64) << 8) + (ip[7] as u64),
        ((ip[8] as u64) << 56) + ((ip[9] as u64) << 48) +
        ((ip[10] as u64) << 40) + ((ip[11] as u64) << 32) +
        ((ip[12] as u64) << 24) + ((ip[13] as u64) << 16) +
        ((ip[14] as u64) << 8) + (ip[15] as u64),
    ]
}

impl fmt::Display for IpNet {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            IpNet::V4(ref a) => a.fmt(fmt),
            IpNet::V6(ref a) => a.fmt(fmt),
        }
    }
}

impl fmt::Display for Ipv4Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}

impl fmt::Display for Ipv6Net {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.addr, self.prefix_len)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::BufferedReader;
use std::io::File;
use std::rc::Rc;

use display::Display;
use sdl2;
use player;
use player::Player;

#[deriving(FromPrimitive)]
#[deriving(Hash)]
#[deriving(Eq)]
#[deriving(PartialEq)]
pub enum SquareType {
    EMPTY = 0i,
    WALL = 1i,
    BOX = 2i,
    TARGET = 3i,
    TARGETVALID = 4i
}

pub struct Level {
    columns: int,
    rows: int,
    boxsize: int,
    renderer: Display,
    textures: HashMap<SquareType, Rc<sdl2::render::Texture>>,
    player_textures: HashMap<player::Orientation, Rc<sdl2::render::Texture>>,
    grid: Vec<Vec<Square>>,
    start_position: (uint, uint)
}

impl Level {
    pub fn new() -> Level {
        let width = 20 * 34;
        let height = 20 * 34;
        let renderer = Display::new(width, height);

        Level {
            columns: 20,
            rows: 20,
            boxsize: 34,
            renderer: renderer,
            textures: HashMap::new(),
            player_textures: HashMap::new(),
            grid: Vec::new(),
            start_position: (0, 0)
        }
    }

    pub fn init(&mut self) {
        self.textures = self.renderer.get_grid_textures();
        self.player_textures = self.renderer.get_player_textures();
        let grid_content: Vec<Vec<SquareType>> = self.get_level_content();
        self.grid = Level::create_grid(grid_content, &self.textures);
    }

    pub fn get_start_position(&self) -> (uint, uint) {
        self.start_position
    }

    fn get_level_content(&mut self) -> Vec<Vec<SquareType>> {
        let level_path = Path::new("./resources/level.txt");
        let mut file = BufferedReader::new(File::open(&level_path));
        let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

        let mut grid: Vec<Vec<SquareType>> = Vec::new();
        for line in lines.iter() {
            let mut row: Vec<SquareType> = Vec::new();
            let mut myline = line.clone();
            myline.pop();
            let slice: &str = myline.as_slice();
            for c in slice.chars() {
                if c == 'P' {
                    self.start_position = (row.len(), grid.len());
                }
                let code: int = match c.to_digit(4) {
                    Some(d) => d as int,
                    None => 0i
                };
                let square_type = match FromPrimitive::from_int(code) {
                    Some(t) => t,
                    None => SquareType::EMPTY
                };
                row.push(square_type);
            }
            grid.push(row);
        }
        return grid;
    }

    fn create_grid(content: Vec<Vec<SquareType>>, textures: & HashMap<SquareType, Rc<sdl2::render::Texture>>) -> Vec<Vec<Square>> {
        let mut grid: Vec<Vec<Square>> = Vec::new();
        let mut i = 0i;

        for content_row in content.iter() {
            let mut row: Vec<Square> = Vec::new();
            let mut j = 0i;
            for square_type in content_row.iter() {
                let mut tex: Option<Rc<sdl2::render::Texture>> = None;
                if *square_type != SquareType::EMPTY {
                    tex = match textures.get(square_type) {
                        Some(t) => {let tcopy = t.clone(); Some(tcopy)},
                        None => panic!(format!("error on texture retrieval for type {}", *square_type as int))
                    };
                }
                row.push(create_square(j, i, *square_type, tex));
                j += 1;
            }
            i += 1;
            grid.push(row);
        }
        return grid;
    }

    pub fn update_display(&self, player: &Player) {
        self.renderer.clear_screen();
        self.renderer.render_grid(&self.grid, self.boxsize as i32, &self.textures);
        let player_texture = match self.player_textures.find(&player.orientation) {
            Some(t) => t,
            None => panic!(format!("error on texture retrieval for player orientation {}", player.orientation as int))
        };
        self.renderer.render_player(&**player_texture, player.get_position(), self.boxsize as i32);
        self.renderer.renderer.present();
    }

    pub fn is_move_allowed(&self, player: &Player, movement: (i8, i8)) -> bool {
        let (x, y) = player.get_position();
        let (dx, dy) = movement;
        let new_x = x as int + dx as int;
        let new_y = y as int + dy as int;

        match self.grid[new_y as uint][new_x as uint].square_type {
            SquareType::EMPTY => true,
            SquareType::WALL => false,
            SquareType::BOX | SquareType::TARGETVALID => {
                let pos = ((new_x + dx as int) as uint, (new_y + dy as int) as uint);
                self.is_free(pos)
            },
            SquareType::TARGET => true
        }
    }
    pub fn is_free(&self, position: (uint, uint)) -> bool {
        let (x, y) = position;
        match self.grid[y][x].square_type {
            SquareType::EMPTY | SquareType::TARGET => true,
            _ => false
        }
    }
    pub fn is_box_present(&self, position: (uint, uint)) -> bool {
        let (x, y) = position;
        match self.grid[y][x].square_type {
            SquareType::BOX | SquareType::TARGETVALID => true,
            _ => false
        }
    }

    pub fn move_box(&mut self, position: (uint, uint), delta: (i8, i8)) {
        let (x, y) = position;
        let (dx, dy) = delta;
        let new_x = (x as int + dx as int) as uint;
        let new_y = (y as int + dy as int) as uint;
        match self.grid[y][x].square_type {
            SquareType::BOX => self.grid[y][x].square_type = SquareType::EMPTY,
            SquareType::TARGETVALID => self.grid[y][x].square_type = SquareType::TARGET,
            _ => ()
        };

        match self.grid[new_y][new_x].square_type {
            SquareType::EMPTY => self.grid[new_y][new_x].square_type = SquareType::BOX,
            SquareType::TARGET => self.grid[new_y][new_x].square_type = SquareType::TARGETVALID,
            _ => ()
        };
    }
}

pub struct Square {
    pub x: int,
    pub y: int,
    pub square_type: SquareType,
    pub texture: Option<Rc<sdl2::render::Texture>>
}

pub fn create_square(x: int, y: int, square_type: SquareType, texture: Option<Rc<sdl2::render::Texture>>) -> Square {
    Square{x:x, y:y, square_type: square_type, texture:texture}
}
<commit_msg>remove texture data from the grid squares<commit_after>use std::collections::HashMap;
use std::io::BufferedReader;
use std::io::File;
use std::rc::Rc;

use display::Display;
use sdl2;
use player;
use player::Player;

#[deriving(FromPrimitive)]
#[deriving(Hash)]
#[deriving(Eq)]
#[deriving(PartialEq)]
pub enum SquareType {
    EMPTY = 0i,
    WALL = 1i,
    BOX = 2i,
    TARGET = 3i,
    TARGETVALID = 4i
}

pub struct Level {
    columns: int,
    rows: int,
    boxsize: int,
    renderer: Display,
    textures: HashMap<SquareType, Rc<sdl2::render::Texture>>,
    player_textures: HashMap<player::Orientation, Rc<sdl2::render::Texture>>,
    grid: Vec<Vec<Square>>,
    start_position: (uint, uint)
}

impl Level {
    pub fn new() -> Level {
        let width = 20 * 34;
        let height = 20 * 34;
        let renderer = Display::new(width, height);

        Level {
            columns: 20,
            rows: 20,
            boxsize: 34,
            renderer: renderer,
            textures: HashMap::new(),
            player_textures: HashMap::new(),
            grid: Vec::new(),
            start_position: (0, 0)
        }
    }

    pub fn init(&mut self) {
        self.textures = self.renderer.get_grid_textures();
        self.player_textures = self.renderer.get_player_textures();
        let grid_content: Vec<Vec<SquareType>> = self.get_level_content();
        self.grid = Level::create_grid(grid_content, &self.textures);
    }

    pub fn get_start_position(&self) -> (uint, uint) {
        self.start_position
    }

    fn get_level_content(&mut self) -> Vec<Vec<SquareType>> {
        let level_path = Path::new("./resources/level.txt");
        let mut file = BufferedReader::new(File::open(&level_path));
        let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

        let mut grid: Vec<Vec<SquareType>> = Vec::new();
        for line in lines.iter() {
            let mut row: Vec<SquareType> = Vec::new();
            let mut myline = line.clone();
            myline.pop();
            let slice: &str = myline.as_slice();
            for c in slice.chars() {
                if c == 'P' {
                    self.start_position = (row.len(), grid.len());
                }
                let code: int = match c.to_digit(4) {
                    Some(d) => d as int,
                    None => 0i
                };
                let square_type = match FromPrimitive::from_int(code) {
                    Some(t) => t,
                    None => SquareType::EMPTY
                };
                row.push(square_type);
            }
            grid.push(row);
        }
        return grid;
    }

    fn create_grid(content: Vec<Vec<SquareType>>, textures: & HashMap<SquareType, Rc<sdl2::render::Texture>>) -> Vec<Vec<Square>> {
        let mut grid: Vec<Vec<Square>> = Vec::new();
        let mut i = 0i;

        for content_row in content.iter() {
            let mut row: Vec<Square> = Vec::new();
            let mut j = 0i;
            for square_type in content_row.iter() {
                row.push(create_square(j, i, *square_type));
                j += 1;
            }
            i += 1;
            grid.push(row);
        }
        return grid;
    }

    pub fn update_display(&self, player: &Player) {
        self.renderer.clear_screen();
        self.renderer.render_grid(&self.grid, self.boxsize as i32, &self.textures);
        let player_texture = match self.player_textures.find(&player.orientation) {
            Some(t) => t,
            None => panic!(format!("error on texture retrieval for player orientation {}", player.orientation as int))
        };
        self.renderer.render_player(&**player_texture, player.get_position(), self.boxsize as i32);
        self.renderer.renderer.present();
    }

    pub fn is_move_allowed(&self, player: &Player, movement: (i8, i8)) -> bool {
        let (x, y) = player.get_position();
        let (dx, dy) = movement;
        let new_x = x as int + dx as int;
        let new_y = y as int + dy as int;

        match self.grid[new_y as uint][new_x as uint].square_type {
            SquareType::EMPTY => true,
            SquareType::WALL => false,
            SquareType::BOX | SquareType::TARGETVALID => {
                let pos = ((new_x + dx as int) as uint, (new_y + dy as int) as uint);
                self.is_free(pos)
            },
            SquareType::TARGET => true
        }
    }
    pub fn is_free(&self, position: (uint, uint)) -> bool {
        let (x, y) = position;
        match self.grid[y][x].square_type {
            SquareType::EMPTY | SquareType::TARGET => true,
            _ => false
        }
    }
    pub fn is_box_present(&self, position: (uint, uint)) -> bool {
        let (x, y) = position;
        match self.grid[y][x].square_type {
            SquareType::BOX | SquareType::TARGETVALID => true,
            _ => false
        }
    }

    pub fn move_box(&mut self, position: (uint, uint), delta: (i8, i8)) {
        let (x, y) = position;
        let (dx, dy) = delta;
        let new_x = (x as int + dx as int) as uint;
        let new_y = (y as int + dy as int) as uint;
        match self.grid[y][x].square_type {
            SquareType::BOX => self.grid[y][x].square_type = SquareType::EMPTY,
            SquareType::TARGETVALID => self.grid[y][x].square_type = SquareType::TARGET,
            _ => ()
        };

        match self.grid[new_y][new_x].square_type {
            SquareType::EMPTY => self.grid[new_y][new_x].square_type = SquareType::BOX,
            SquareType::TARGET => self.grid[new_y][new_x].square_type = SquareType::TARGETVALID,
            _ => ()
        };
    }
}

pub struct Square {
    pub x: int,
    pub y: int,
    pub square_type: SquareType,
}

pub fn create_square(x: int, y: int, square_type: SquareType) -> Square {
    Square{x:x, y:y, square_type: square_type}
}
<|endoftext|>


<commit_before>/// There are utilities that can be used to do an inner join between
/// ordered iterators. This can be useful to do selects between multiple
/// tables of items

use std::collections::{
    btree_map,
    tree_map, tree_set,
    trie_map, trie_set,
    vec_map
};

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a map like structure
pub trait InnerJoinMap<K, A>: Iterator<(K, A)> {
    /// join two ordered maps together
    fn inner_join_map<B, T: InnerJoinMap<K, B>>(self, map: T)
        -> InnerJoinMapIterator<Self, T> {
        InnerJoinMapIterator {
            a: self,
            b: map
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<B, T: InnerJoinSet<K>>(self, set: T)
        -> InnerJoinMapSetIterator<Self, T> {
        InnerJoinMapSetIterator {
            map: self,
            set: set
        }
    }
}

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a set like structure
pub trait InnerJoinSet<K>: Iterator<K> {
    /// join two ordered maps together
    fn inner_join_map<B, T: InnerJoinMap<K, B>>(self, map: T)
        -> InnerJoinMapSetIterator<T, Self> {
        InnerJoinMapSetIterator {
            map: map,
            set: self
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<T: InnerJoinSet<K>>(self, map: T)
        -> InnerJoinSetIterator<Self, T> {
        InnerJoinSetIterator {
            a: self,
            b: map
        }
    }
}

pub struct InnerJoinMapIterator<A, B> {a: A, b: B}
pub struct InnerJoinMapSetIterator<A, B> {map: A, set: B}
pub struct InnerJoinSetIterator<A, B> {a: A, b: B}

impl<K: Ord, DataA, DataB,
     A: InnerJoinMap<K, DataA>,
     B: InnerJoinMap<K, DataB>>
     Iterator<(K, (DataA, DataB))> for InnerJoinMapIterator<A, B> {

    fn next(&mut self) -> Option<(K, (DataA, DataB))> {
        let (mut key_a, mut data_a) = match self.a.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        let (mut key_b, mut data_b) = match self.b.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_a = key;
                            data_a = data;
                        }
                    };
                },
                Equal => return Some((key_a, (data_a, data_b))),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_b = key;
                            data_b = data;
                        }
                    };
                }
            }
        }
    }
}

impl<K: Ord,
     A: InnerJoinSet<K>,
     B: InnerJoinSet<K>>
     Iterator<K> for InnerJoinSetIterator<A, B> {
    fn next(&mut self) -> Option<K> {
        let mut key_a = match self.a.next() {
            None => return None,
            Some(key) => key
        };

        let mut key_b = match self.b.next() {
            None => return None,
            Some(key) => key
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some(key) => { key_a = key; }
                    };
                },
                Equal => return Some(key_a),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some(key) => { key_b = key; }
                    };
                }
            }
        }
    }
}

impl<K: Ord,
     V,
     SetIter: InnerJoinSet<K>,
     MapIter: InnerJoinMap<K, V>>
     Iterator<(K, V)> for InnerJoinMapSetIterator<MapIter, SetIter> {
    fn next(&mut self) -> Option<(K, V)> {
        let mut key_set = match self.set.next() {
            None => return None,
            Some(key) => key
        };

        let (mut key_map, mut data) = match self.map.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_set.cmp(&key_map) {
                Less => {
                    match self.set.next() {
                        None => return None,
                        Some(key) => { key_set = key; }
                    };
                },
                Equal => return Some((key_set, data)),
                Greater => {
                    match self.map.next() {
                        None => return None,
                        Some((key, d)) => {
                            key_map = key;
                            data = d;
                        }
                    };
                }
            }
        }
    }
}

impl<'a, K: Ord, V> InnerJoinSet<&'a K> for btree_map::Keys<'a, K, V> {}
impl<'a, K: Ord, V> InnerJoinMap<&'a K, &'a V> for btree_map::Entries<'a, K, V> {}
impl<'a, K: Ord> InnerJoinSet<&'a K> for tree_set::SetItems<'a, K> {}
impl<'a, K: Ord, V> InnerJoinMap<&'a K, &'a V> for tree_map::Entries<'a, K, V> {}
impl<'a> InnerJoinSet<uint> for trie_set::SetItems<'a> {}
impl<'a, V> InnerJoinMap<uint, &'a V> for trie_map::Entries<'a, V> {}
impl<'a, V> InnerJoinMap<uint, &'a V> for vec_map::Entries<'a, V> {}

impl<K: Ord, VA, VB,
     A: InnerJoinMap<K, VA>,
     B: InnerJoinMap<K, VB>> InnerJoinMap<K, (VA, VB)> for InnerJoinMapIterator<A, B> {}
impl<K: Ord, V,
     A: InnerJoinSet<K>,
     B: InnerJoinMap<K, V>> InnerJoinMap<K, V> for InnerJoinMapSetIterator<B, A> {}
impl<K: Ord,
     A: InnerJoinSet<K>,
     B: InnerJoinSet<K>> InnerJoinSet<K> for InnerJoinSetIterator<A, B> {}

#[test]
fn join_two_sets() {
    use std::collections::BTreeSet;

    let powers_of_two: BTreeSet<int> = range(1, 10).map(|x| x * 2).collect();
    let powers_of_three: BTreeSet<int> = range(1, 10).map(|x| x * 3).collect();

    let expected = vec![6, 12, 18];

    let powers_of_two_and_three =
        powers_of_two.iter()
        .inner_join_set(powers_of_three.iter())
        .map(|&x| x)
        .collect();

    assert_eq!(expected, powers_of_two_and_three);
}

#[test]
fn join_three_sets() {
    use std::collections::BTreeSet;

    let powers_of_two: BTreeSet<int> = range(1, 100).map(|x| x * 2).collect();
    let powers_of_three: BTreeSet<int> = range(1, 100).map(|x| x * 3).collect();
    let powers_of_five: BTreeSet<int> = range(1, 100).map(|x| x * 5).collect();

    let expected = vec![30, 60, 90, 120, 150, 180];

    let powers_of_two_and_three =
        powers_of_two.iter()
        .inner_join_set(powers_of_three.iter())
        .inner_join_set(powers_of_five.iter())
        .map(|&x| x)
        .collect();

    assert_eq!(expected, powers_of_two_and_three);
}

#[test]
fn join_two_maps() {
    use std::collections::BTreeMap;

    let powers_of_two: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 2, x)).collect();
    let powers_of_three: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 3, x)).collect();

    let mut powers_of_two_and_three =
        powers_of_two.iter().inner_join_map(powers_of_three.iter())
        .map(|(&k, (&a, &b))| (k, a, b));

    assert_eq!(Some((6, 3, 2)), powers_of_two_and_three.next())
    assert_eq!(Some((12, 6, 4)), powers_of_two_and_three.next())
    assert_eq!(Some((18, 9, 6)), powers_of_two_and_three.next())
    assert_eq!(None, powers_of_two_and_three.next())
}

#[test]
fn join_two_maps_to_set() {
    use std::collections::{BTreeMap, BTreeSet};

    let powers_of_two: BTreeSet<int> = range(1, 10).map(|x| x * 2).collect();
    let powers_of_three: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 3, x)).collect();

    let mut powers_of_two_and_three =
        powers_of_two.iter().inner_join_map(powers_of_three.iter())
        .map(|(&k, &a)| (k, a));

    assert_eq!(Some((6, 2)), powers_of_two_and_three.next())
    assert_eq!(Some((12, 4)), powers_of_two_and_three.next())
    assert_eq!(Some((18, 6)), powers_of_two_and_three.next())
    assert_eq!(None, powers_of_two_and_three.next())
}
<commit_msg>added btree_set and bitv_set<commit_after>/// There are utilities that can be used to do an inner join between
/// ordered iterators. This can be useful to do selects between multiple
/// tables of items

use std::collections::{
    btree_map, btree_set,
    tree_map, tree_set,
    trie_map, trie_set,
    vec_map,
    bitv_set
};

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a map like structure
pub trait InnerJoinMap<K, A>: Iterator<(K, A)> {
    /// join two ordered maps together
    fn inner_join_map<B, T: InnerJoinMap<K, B>>(self, map: T)
        -> InnerJoinMapIterator<Self, T> {
        InnerJoinMapIterator {
            a: self,
            b: map
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<B, T: InnerJoinSet<K>>(self, set: T)
        -> InnerJoinMapSetIterator<Self, T> {
        InnerJoinMapSetIterator {
            map: self,
            set: set
        }
    }
}

/// Allows an iterator to be do an inner join with another
/// iterator to combine their values or filter based on their keys.
/// this trait is applied to an iterator over a set like structure
pub trait InnerJoinSet<K>: Iterator<K> {
    /// join two ordered maps together
    fn inner_join_map<B, T: InnerJoinMap<K, B>>(self, map: T)
        -> InnerJoinMapSetIterator<T, Self> {
        InnerJoinMapSetIterator {
            map: map,
            set: self
        }
    }

    /// filter an ordered map with an ordered set
    fn inner_join_set<T: InnerJoinSet<K>>(self, map: T)
        -> InnerJoinSetIterator<Self, T> {
        InnerJoinSetIterator {
            a: self,
            b: map
        }
    }
}

pub struct InnerJoinMapIterator<A, B> {a: A, b: B}
pub struct InnerJoinMapSetIterator<A, B> {map: A, set: B}
pub struct InnerJoinSetIterator<A, B> {a: A, b: B}

impl<K: Ord, DataA, DataB,
     A: InnerJoinMap<K, DataA>,
     B: InnerJoinMap<K, DataB>>
     Iterator<(K, (DataA, DataB))> for InnerJoinMapIterator<A, B> {

    fn next(&mut self) -> Option<(K, (DataA, DataB))> {
        let (mut key_a, mut data_a) = match self.a.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        let (mut key_b, mut data_b) = match self.b.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_a = key;
                            data_a = data;
                        }
                    };
                },
                Equal => return Some((key_a, (data_a, data_b))),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some((key, data)) => {
                            key_b = key;
                            data_b = data;
                        }
                    };
                }
            }
        }
    }
}

impl<K: Ord,
     A: InnerJoinSet<K>,
     B: InnerJoinSet<K>>
     Iterator<K> for InnerJoinSetIterator<A, B> {
    fn next(&mut self) -> Option<K> {
        let mut key_a = match self.a.next() {
            None => return None,
            Some(key) => key
        };

        let mut key_b = match self.b.next() {
            None => return None,
            Some(key) => key
        };

        loop {
            match key_a.cmp(&key_b) {
                Less => {
                    match self.a.next() {
                        None => return None,
                        Some(key) => { key_a = key; }
                    };
                },
                Equal => return Some(key_a),
                Greater => {
                    match self.b.next() {
                        None => return None,
                        Some(key) => { key_b = key; }
                    };
                }
            }
        }
    }
}

impl<K: Ord,
     V,
     SetIter: InnerJoinSet<K>,
     MapIter: InnerJoinMap<K, V>>
     Iterator<(K, V)> for InnerJoinMapSetIterator<MapIter, SetIter> {
    fn next(&mut self) -> Option<(K, V)> {
        let mut key_set = match self.set.next() {
            None => return None,
            Some(key) => key
        };

        let (mut key_map, mut data) = match self.map.next() {
            None => return None,
            Some((key, data)) => (key, data)
        };

        loop {
            match key_set.cmp(&key_map) {
                Less => {
                    match self.set.next() {
                        None => return None,
                        Some(key) => { key_set = key; }
                    };
                },
                Equal => return Some((key_set, data)),
                Greater => {
                    match self.map.next() {
                        None => return None,
                        Some((key, d)) => {
                            key_map = key;
                            data = d;
                        }
                    };
                }
            }
        }
    }
}

impl<'a, K: Ord> InnerJoinSet<&'a K> for btree_set::Items<'a, K> {}
impl<'a, K: Ord, V> InnerJoinMap<&'a K, &'a V> for btree_map::Entries<'a, K, V> {}
impl<'a, K: Ord> InnerJoinSet<&'a K> for tree_set::SetItems<'a, K> {}
impl<'a, K: Ord, V> InnerJoinMap<&'a K, &'a V> for tree_map::Entries<'a, K, V> {}
impl<'a> InnerJoinSet<uint> for trie_set::SetItems<'a> {}
impl<'a, V> InnerJoinMap<uint, &'a V> for trie_map::Entries<'a, V> {}
impl<'a, V> InnerJoinMap<uint, &'a V> for vec_map::Entries<'a, V> {}
impl<'a> InnerJoinSet<uint> for bitv_set::BitPositions<'a> {}

impl<K: Ord, VA, VB,
     A: InnerJoinMap<K, VA>,
     B: InnerJoinMap<K, VB>> InnerJoinMap<K, (VA, VB)> for InnerJoinMapIterator<A, B> {}
impl<K: Ord, V,
     A: InnerJoinSet<K>,
     B: InnerJoinMap<K, V>> InnerJoinMap<K, V> for InnerJoinMapSetIterator<B, A> {}
impl<K: Ord,
     A: InnerJoinSet<K>,
     B: InnerJoinSet<K>> InnerJoinSet<K> for InnerJoinSetIterator<A, B> {}

#[test]
fn join_two_sets() {
    use std::collections::BTreeSet;

    let powers_of_two: BTreeSet<int> = range(1, 10).map(|x| x * 2).collect();
    let powers_of_three: BTreeSet<int> = range(1, 10).map(|x| x * 3).collect();

    let expected = vec![6, 12, 18];

    let powers_of_two_and_three =
        powers_of_two.iter()
        .inner_join_set(powers_of_three.iter())
        .map(|&x| x)
        .collect();

    assert_eq!(expected, powers_of_two_and_three);
}

#[test]
fn join_three_sets() {
    use std::collections::BTreeSet;

    let powers_of_two: BTreeSet<int> = range(1, 100).map(|x| x * 2).collect();
    let powers_of_three: BTreeSet<int> = range(1, 100).map(|x| x * 3).collect();
    let powers_of_five: BTreeSet<int> = range(1, 100).map(|x| x * 5).collect();

    let expected = vec![30, 60, 90, 120, 150, 180];

    let powers_of_two_and_three =
        powers_of_two.iter()
        .inner_join_set(powers_of_three.iter())
        .inner_join_set(powers_of_five.iter())
        .map(|&x| x)
        .collect();

    assert_eq!(expected, powers_of_two_and_three);
}

#[test]
fn join_two_maps() {
    use std::collections::BTreeMap;

    let powers_of_two: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 2, x)).collect();
    let powers_of_three: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 3, x)).collect();

    let mut powers_of_two_and_three =
        powers_of_two.iter().inner_join_map(powers_of_three.iter())
        .map(|(&k, (&a, &b))| (k, a, b));

    assert_eq!(Some((6, 3, 2)), powers_of_two_and_three.next())
    assert_eq!(Some((12, 6, 4)), powers_of_two_and_three.next())
    assert_eq!(Some((18, 9, 6)), powers_of_two_and_three.next())
    assert_eq!(None, powers_of_two_and_three.next())
}

#[test]
fn join_two_maps_to_set() {
    use std::collections::{BTreeMap, BTreeSet};

    let powers_of_two: BTreeSet<int> = range(1, 10).map(|x| x * 2).collect();
    let powers_of_three: BTreeMap<int, int> = range(1i, 10).map(|x| (x * 3, x)).collect();

    let mut powers_of_two_and_three =
        powers_of_two.iter().inner_join_map(powers_of_three.iter())
        .map(|(&k, &a)| (k, a));

    assert_eq!(Some((6, 2)), powers_of_two_and_three.next())
    assert_eq!(Some((12, 4)), powers_of_two_and_three.next())
    assert_eq!(Some((18, 6)), powers_of_two_and_three.next())
    assert_eq!(None, powers_of_two_and_three.next())
}
<|endoftext|>


<commit_before>//! Function interfaces for VST 2.4 API.

#![doc(hidden)]

use std::{mem, slice};

use std::os::raw::{c_char, c_void};

use buffer::AudioBuffer;
use api::consts::*;
use api::{self, AEffect, ChannelProperties};
use editor::{Rect, KeyCode, Key, KnobMode};
use host::Host;
use event::Event;

/// Deprecated process function.
pub fn process_deprecated(_effect: *mut AEffect, _inputs_raw: *mut *mut f32, _outputs_raw: *mut *mut f32, _samples: i32) { }

/// VST2.4 replacing function.
pub fn process_replacing(effect: *mut AEffect, inputs_raw: *mut *mut f32, outputs_raw: *mut *mut f32, samples: i32) {
    // Handle to the vst
    let mut plugin = unsafe { (*effect).get_plugin() };

    let buffer = unsafe {
        AudioBuffer::from_raw(inputs_raw,
                              outputs_raw,
                              plugin.get_info().inputs as usize,
                              plugin.get_info().outputs as usize,
                              samples as usize)
    };

    plugin.process(buffer);
}

/// VST2.4 replacing function with `f64` values.
pub fn process_replacing_f64(effect: *mut AEffect, inputs_raw: *mut *mut f64, outputs_raw: *mut *mut f64, samples: i32) {
    let mut plugin = unsafe { (*effect).get_plugin() };

    if plugin.get_info().f64_precision {
        let buffer = unsafe {
            AudioBuffer::from_raw(inputs_raw,
                                  outputs_raw,
                                  plugin.get_info().inputs as usize,
                                  plugin.get_info().outputs as usize,
                                  samples as usize)
        };

        plugin.process_f64(buffer);
    }
}

/// VST2.4 set parameter function.
pub fn set_parameter(effect: *mut AEffect, index: i32, value: f32) {
    unsafe { (*effect).get_plugin() }.set_parameter(index, value);
}

/// VST2.4 get parameter function.
pub fn get_parameter(effect: *mut AEffect, index: i32) -> f32 {
    unsafe { (*effect).get_plugin() }.get_parameter(index)
}

// Copy a string into the `ptr` buffer
fn copy_string(dst: *mut c_void, src: &str, max: usize) {
    unsafe {
        use std::cmp::min;
        use libc::{c_void, memset, memcpy};

        let dst = dst as *mut c_void;
        memset(dst, 0, max);
        memcpy(dst, src.as_ptr() as *const c_void, min(max, src.len()));
    }
}

/// VST2.4 dispatch function. This function handles dispatching all opcodes to the vst plugin.
pub fn dispatch(effect: *mut AEffect, opcode: i32, index: i32, value: isize, ptr: *mut c_void, opt: f32) -> isize {
    use plugin::{CanDo, OpCode};

    // Convert passed in opcode to enum
    let opcode = OpCode::from(opcode);
    // Plugin handle
    let mut plugin = unsafe { (*effect).get_plugin() };

    match opcode {
        OpCode::Initialize => plugin.init(),
        OpCode::Shutdown => unsafe {
            (*effect).drop_plugin();
            drop(mem::transmute::<*mut AEffect, Box<AEffect>>(effect));
        },

        OpCode::ChangePreset => plugin.change_preset(value as i32),
        OpCode::GetCurrentPresetNum => return plugin.get_preset_num() as isize,
        OpCode::SetCurrentPresetName => plugin.set_preset_name(read_string(ptr)),
        OpCode::GetCurrentPresetName => {
            let num = plugin.get_preset_num();
            copy_string(ptr, &plugin.get_preset_name(num), MAX_PRESET_NAME_LEN);
        }

        OpCode::GetParameterLabel => copy_string(ptr, &plugin.get_parameter_label(index), MAX_PARAM_STR_LEN),
        OpCode::GetParameterDisplay => copy_string(ptr, &plugin.get_parameter_text(index), MAX_PARAM_STR_LEN),
        OpCode::GetParameterName => copy_string(ptr, &plugin.get_parameter_name(index), MAX_PARAM_STR_LEN),

        OpCode::SetSampleRate => plugin.set_sample_rate(opt),
        OpCode::SetBlockSize => plugin.set_block_size(value as i64),
        OpCode::StateChanged => {
            if value == 1 {
                plugin.resume();
            } else {
                plugin.suspend();
            }
        }

        OpCode::EditorGetRect => {
            if let Some(editor) = plugin.get_editor() {
                let size = editor.size();
                let pos = editor.position();

                unsafe {
                    // Given a Rect** structure
                    // TODO: Investigate whether we are given a valid Rect** pointer already
                    *(ptr as *mut *mut c_void) =
                        mem::transmute(Box::new(Rect {
                            left: pos.0 as i16, // x coord of position
                            top: pos.1 as i16, // y coord of position
                            right: (pos.0 + size.0) as i16, // x coord of pos + x coord of size
                            bottom: (pos.1 + size.1) as i16 // y coord of pos + y coord of size
                        }));
                }
            }
        }
        OpCode::EditorOpen => {
            if let Some(editor) = plugin.get_editor() {
                editor.open(ptr); //ptr is raw window handle, eg HWND* on windows
            }
        }
        OpCode::EditorClose => {
            if let Some(editor) = plugin.get_editor() {
                editor.close();
            }
        }

        OpCode::EditorIdle => {
            if let Some(editor) = plugin.get_editor() {
                editor.idle();
            }
        }

        OpCode::GetData => {
            let chunks = if index == 0 {
                plugin.get_bank_data()
            } else {
                plugin.get_preset_data()
            };

            let len = chunks.len() as isize;

            // u8 array to **void ptr
            // TODO: Release the allocated memory for the chunk in resume / suspend event
            unsafe {
                *(ptr as *mut *mut c_void) =
                    chunks.into_boxed_slice().as_ptr() as *mut c_void;
            }

            return len;
        }
        OpCode::SetData => {
            let chunks = unsafe { slice::from_raw_parts(ptr as *mut u8, value as usize) };
            if index == 0 {
                plugin.load_bank_data(chunks);
            } else {
                plugin.load_preset_data(chunks);
            }
        }

        OpCode::ProcessEvents => {
            let events: *const api::Events = ptr as *const api::Events;

            let events: Vec<Event> = unsafe {
                // Create a slice of type &mut [*mut Event]
                slice::from_raw_parts(&(*events).events[0], (*events).num_events as usize)
                // Deref and clone each event to get a slice
                .iter().map(|item| Event::from(**item)).collect()
            };

            plugin.process_events(events);
        }
        OpCode::CanBeAutomated => return plugin.can_be_automated(index) as isize,
        OpCode::StringToParameter => return plugin.string_to_parameter(index, read_string(ptr)) as isize,

        OpCode::GetPresetName => copy_string(ptr, &plugin.get_preset_name(index), MAX_PRESET_NAME_LEN),

        OpCode::GetInputInfo => {
            if index >= 0 && index < plugin.get_info().inputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_input_info(index).into();
                }
            }
        }
        OpCode::GetOutputInfo => {
            if index >= 0 && index < plugin.get_info().outputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_output_info(index).into();
                }
            }
        }
        OpCode::GetCategory => {
            return plugin.get_info().category.into();
        }

        OpCode::GetVendorName => copy_string(ptr, &plugin.get_info().vendor, MAX_VENDOR_STR_LEN),
        OpCode::GetProductName => copy_string(ptr, &plugin.get_info().name, MAX_PRODUCT_STR_LEN),
        OpCode::GetVendorVersion => return plugin.get_info().version as isize,
        OpCode::VendorSpecific => return plugin.vendor_specific(index, value, ptr, opt),
        OpCode::CanDo => {
            let can_do: CanDo = match read_string(ptr).parse() {
                Ok(c) => c,
                Err(e) => { warn!("{}", e); return 0; }
            };
            return plugin.can_do(can_do).into();
        }
        OpCode::GetTailSize => if plugin.get_tail_size() == 0 { return 1; } else { return plugin.get_tail_size() },

        //OpCode::GetParamInfo => { /*TODO*/ }

        OpCode::GetApiVersion => return 2400,

        OpCode::EditorKeyDown => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_down(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8
                });
            }
        }
        OpCode::EditorKeyUp => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_up(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8
                });
            }
        }
        OpCode::EditorSetKnobMode => {
            if let Some(editor) = plugin.get_editor() {
                editor.set_knob_mode(KnobMode::from(value));
            }
        }

        _ => {
            warn!("Unimplemented opcode ({:?})", opcode);
            trace!("Arguments; index: {}, value: {}, ptr: {:?}, opt: {}", index, value, ptr, opt);
        }
    }

    0
}

pub fn host_dispatch(host: &mut Host,
                     effect: *mut AEffect,
                     opcode: i32,
                     index: i32,
                     value: isize,
                     ptr: *mut c_void,
                     opt: f32) -> isize {
    use host::OpCode;

    match OpCode::from(opcode) {
        OpCode::Version => return 2400,
        OpCode::Automate => host.automate(index, opt),

        OpCode::Idle => host.idle(),

        // ...

        OpCode::CanDo => {
            info!("Plugin is asking if host can: {}.", read_string(ptr));
        }

        OpCode::GetVendorVersion => return host.get_info().0,
        OpCode::GetVendorString => copy_string(ptr, &host.get_info().1, MAX_VENDOR_STR_LEN),
        OpCode::GetProductString => copy_string(ptr, &host.get_info().2, MAX_PRODUCT_STR_LEN),
        OpCode::ProcessEvents => {
            let events: *const api::Events = ptr as *const api::Events;

            let events: Vec<Event> = unsafe {
                // Create a slice of type &mut [*mut Event]
                slice::from_raw_parts(&(*events).events[0], (*events).num_events as usize)
                // Deref and clone each event to get a slice
                .iter().map(|item| Event::from(**item)).collect()
            };

            host.process_events(events);
        }

        unimplemented => {
            trace!("VST: Got unimplemented host opcode ({:?})", unimplemented);
            trace!("Arguments; effect: {:?}, index: {}, value: {}, ptr: {:?}, opt: {}",
                    effect, index, value, ptr, opt);
        }
    }
    0
}

// Read a string from the `ptr` buffer
fn read_string(ptr: *mut c_void) -> String {
    use std::ffi::CStr;

    String::from_utf8_lossy(
        unsafe { CStr::from_ptr(ptr as *mut c_char).to_bytes() }
    ).into_owned()
}

/// Translate `Vec<Event>` into `&api::Events` and use via a callback.
///
/// Both plugins and hosts can receive VST events, this simply translates the rust structure into
/// the equivalent API structure and takes care of cleanup.
pub fn process_events<F>(events: Vec<Event>, callback: F)
    where F: FnOnce(*mut c_void)
{
    use api::flags::REALTIME_EVENT;

    let len = events.len();

    // The `api::Events` structure uses a variable length array which is difficult to represent in
    // rust. We begin by creating a vector with the appropriate byte size by calculating the header
    // and the variable length body seperately.
    let header_size = mem::size_of::<api::Events>() - (mem::size_of::<*mut api::Event>() * 2);
    let body_size = mem::size_of::<*mut api::Event>() * len;

    let mut send = vec![0u8; header_size + body_size];

    let send_events: &mut [*mut api::Event] = unsafe {
        // The header is updated by casting the array to the `api::Events` type and specifying the
        // required fields. We create a slice from the position of the first event and the length
        // of the array.
        let ptr = send.as_mut_ptr() as *mut api::Events;
        (*ptr).num_events = len as i32;

        // A slice view of the body
        slice::from_raw_parts_mut(&mut (*ptr).events[0], len)
    };

    // Each event is zipped with the target body array slot. Most of what's happening here is just
    // copying data but the key thing to notice is that each event is boxed and cast to
    // (*mut api::Event). This way we can let the callback handle the event, and then later create
    // the box again from the raw pointer so that it can be properly dropped.
    for (event, out) in events.iter().zip(send_events.iter_mut()) {
        *out = match *event {
            Event::Midi { data, delta_frames, live,
                          note_length, note_offset,
                          detune, note_off_velocity } => {
                Box::into_raw(Box::new(api::MidiEvent {
                    event_type: api::EventType::Midi,
                    byte_size: mem::size_of::<api::MidiEvent>() as i32,
                    delta_frames: delta_frames,
                    flags: if live { REALTIME_EVENT.bits() } else { 0 },
                    note_length: note_length.unwrap_or(0),
                    note_offset: note_offset.unwrap_or(0),
                    midi_data: data,
                    _midi_reserved: 0,
                    detune: detune,
                    note_off_velocity: note_off_velocity,
                    _reserved1: 0,
                    _reserved2: 0
                })) as *mut api::Event
            }
            Event::SysEx { payload, delta_frames } => {
                Box::into_raw(Box::new(api::SysExEvent {
                    event_type: api::EventType::SysEx,
                    byte_size: mem::size_of::<api::SysExEvent>() as i32,
                    delta_frames: delta_frames,
                    _flags: 0,
                    data_size: payload.len() as i32,
                    _reserved1: 0,
                    system_data: payload.as_ptr() as *const u8 as *mut u8,
                    _reserved2: 0,
                })) as *mut api::Event
            }
            Event::Deprecated(e) => Box::into_raw(Box::new(e))
        };
    }

    // Allow the callback to use the pointer
    callback(send.as_mut_ptr() as *mut c_void);

    // Clean up the created events
    unsafe {
        for &mut event in send_events {
            match (*event).event_type {
                api::EventType::Midi => {
                    drop(Box::from_raw(event as *mut api::MidiEvent));
                }
                api::EventType::SysEx => {
                    drop(Box::from_raw(event as *mut api::SysExEvent));
                }
                _ => {
                    drop(Box::from_raw(event));
                }
            }
        }
    }
}
<commit_msg>Add proper docs to function<commit_after>//! Function interfaces for VST 2.4 API.

#![doc(hidden)]

use std::{mem, slice};

use std::os::raw::{c_char, c_void};

use buffer::AudioBuffer;
use api::consts::*;
use api::{self, AEffect, ChannelProperties};
use editor::{Rect, KeyCode, Key, KnobMode};
use host::Host;
use event::Event;

/// Deprecated process function.
pub fn process_deprecated(_effect: *mut AEffect, _inputs_raw: *mut *mut f32, _outputs_raw: *mut *mut f32, _samples: i32) { }

/// VST2.4 replacing function.
pub fn process_replacing(effect: *mut AEffect, inputs_raw: *mut *mut f32, outputs_raw: *mut *mut f32, samples: i32) {
    // Handle to the vst
    let mut plugin = unsafe { (*effect).get_plugin() };

    let buffer = unsafe {
        AudioBuffer::from_raw(inputs_raw,
                              outputs_raw,
                              plugin.get_info().inputs as usize,
                              plugin.get_info().outputs as usize,
                              samples as usize)
    };

    plugin.process(buffer);
}

/// VST2.4 replacing function with `f64` values.
pub fn process_replacing_f64(effect: *mut AEffect, inputs_raw: *mut *mut f64, outputs_raw: *mut *mut f64, samples: i32) {
    let mut plugin = unsafe { (*effect).get_plugin() };

    if plugin.get_info().f64_precision {
        let buffer = unsafe {
            AudioBuffer::from_raw(inputs_raw,
                                  outputs_raw,
                                  plugin.get_info().inputs as usize,
                                  plugin.get_info().outputs as usize,
                                  samples as usize)
        };

        plugin.process_f64(buffer);
    }
}

/// VST2.4 set parameter function.
pub fn set_parameter(effect: *mut AEffect, index: i32, value: f32) {
    unsafe { (*effect).get_plugin() }.set_parameter(index, value);
}

/// VST2.4 get parameter function.
pub fn get_parameter(effect: *mut AEffect, index: i32) -> f32 {
    unsafe { (*effect).get_plugin() }.get_parameter(index)
}

/// Copy a string into a destination buffer.
///
/// String will be cut at `max` characters.
fn copy_string(dst: *mut c_void, src: &str, max: usize) {
    unsafe {
        use std::cmp::min;
        use libc::{c_void, memset, memcpy};

        let dst = dst as *mut c_void;
        memset(dst, 0, max);
        memcpy(dst, src.as_ptr() as *const c_void, min(max, src.len()));
    }
}

/// VST2.4 dispatch function. This function handles dispatching all opcodes to the vst plugin.
pub fn dispatch(effect: *mut AEffect, opcode: i32, index: i32, value: isize, ptr: *mut c_void, opt: f32) -> isize {
    use plugin::{CanDo, OpCode};

    // Convert passed in opcode to enum
    let opcode = OpCode::from(opcode);
    // Plugin handle
    let mut plugin = unsafe { (*effect).get_plugin() };

    match opcode {
        OpCode::Initialize => plugin.init(),
        OpCode::Shutdown => unsafe {
            (*effect).drop_plugin();
            drop(mem::transmute::<*mut AEffect, Box<AEffect>>(effect));
        },

        OpCode::ChangePreset => plugin.change_preset(value as i32),
        OpCode::GetCurrentPresetNum => return plugin.get_preset_num() as isize,
        OpCode::SetCurrentPresetName => plugin.set_preset_name(read_string(ptr)),
        OpCode::GetCurrentPresetName => {
            let num = plugin.get_preset_num();
            copy_string(ptr, &plugin.get_preset_name(num), MAX_PRESET_NAME_LEN);
        }

        OpCode::GetParameterLabel => copy_string(ptr, &plugin.get_parameter_label(index), MAX_PARAM_STR_LEN),
        OpCode::GetParameterDisplay => copy_string(ptr, &plugin.get_parameter_text(index), MAX_PARAM_STR_LEN),
        OpCode::GetParameterName => copy_string(ptr, &plugin.get_parameter_name(index), MAX_PARAM_STR_LEN),

        OpCode::SetSampleRate => plugin.set_sample_rate(opt),
        OpCode::SetBlockSize => plugin.set_block_size(value as i64),
        OpCode::StateChanged => {
            if value == 1 {
                plugin.resume();
            } else {
                plugin.suspend();
            }
        }

        OpCode::EditorGetRect => {
            if let Some(editor) = plugin.get_editor() {
                let size = editor.size();
                let pos = editor.position();

                unsafe {
                    // Given a Rect** structure
                    // TODO: Investigate whether we are given a valid Rect** pointer already
                    *(ptr as *mut *mut c_void) =
                        mem::transmute(Box::new(Rect {
                            left: pos.0 as i16, // x coord of position
                            top: pos.1 as i16, // y coord of position
                            right: (pos.0 + size.0) as i16, // x coord of pos + x coord of size
                            bottom: (pos.1 + size.1) as i16 // y coord of pos + y coord of size
                        }));
                }
            }
        }
        OpCode::EditorOpen => {
            if let Some(editor) = plugin.get_editor() {
                editor.open(ptr); //ptr is raw window handle, eg HWND* on windows
            }
        }
        OpCode::EditorClose => {
            if let Some(editor) = plugin.get_editor() {
                editor.close();
            }
        }

        OpCode::EditorIdle => {
            if let Some(editor) = plugin.get_editor() {
                editor.idle();
            }
        }

        OpCode::GetData => {
            let chunks = if index == 0 {
                plugin.get_bank_data()
            } else {
                plugin.get_preset_data()
            };

            let len = chunks.len() as isize;

            // u8 array to **void ptr
            // TODO: Release the allocated memory for the chunk in resume / suspend event
            unsafe {
                *(ptr as *mut *mut c_void) =
                    chunks.into_boxed_slice().as_ptr() as *mut c_void;
            }

            return len;
        }
        OpCode::SetData => {
            let chunks = unsafe { slice::from_raw_parts(ptr as *mut u8, value as usize) };
            if index == 0 {
                plugin.load_bank_data(chunks);
            } else {
                plugin.load_preset_data(chunks);
            }
        }

        OpCode::ProcessEvents => {
            let events: *const api::Events = ptr as *const api::Events;

            let events: Vec<Event> = unsafe {
                // Create a slice of type &mut [*mut Event]
                slice::from_raw_parts(&(*events).events[0], (*events).num_events as usize)
                // Deref and clone each event to get a slice
                .iter().map(|item| Event::from(**item)).collect()
            };

            plugin.process_events(events);
        }
        OpCode::CanBeAutomated => return plugin.can_be_automated(index) as isize,
        OpCode::StringToParameter => return plugin.string_to_parameter(index, read_string(ptr)) as isize,

        OpCode::GetPresetName => copy_string(ptr, &plugin.get_preset_name(index), MAX_PRESET_NAME_LEN),

        OpCode::GetInputInfo => {
            if index >= 0 && index < plugin.get_info().inputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_input_info(index).into();
                }
            }
        }
        OpCode::GetOutputInfo => {
            if index >= 0 && index < plugin.get_info().outputs {
                unsafe {
                    let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
                    *ptr = plugin.get_output_info(index).into();
                }
            }
        }
        OpCode::GetCategory => {
            return plugin.get_info().category.into();
        }

        OpCode::GetVendorName => copy_string(ptr, &plugin.get_info().vendor, MAX_VENDOR_STR_LEN),
        OpCode::GetProductName => copy_string(ptr, &plugin.get_info().name, MAX_PRODUCT_STR_LEN),
        OpCode::GetVendorVersion => return plugin.get_info().version as isize,
        OpCode::VendorSpecific => return plugin.vendor_specific(index, value, ptr, opt),
        OpCode::CanDo => {
            let can_do: CanDo = match read_string(ptr).parse() {
                Ok(c) => c,
                Err(e) => { warn!("{}", e); return 0; }
            };
            return plugin.can_do(can_do).into();
        }
        OpCode::GetTailSize => if plugin.get_tail_size() == 0 { return 1; } else { return plugin.get_tail_size() },

        //OpCode::GetParamInfo => { /*TODO*/ }

        OpCode::GetApiVersion => return 2400,

        OpCode::EditorKeyDown => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_down(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8
                });
            }
        }
        OpCode::EditorKeyUp => {
            if let Some(editor) = plugin.get_editor() {
                editor.key_up(KeyCode {
                    character: index as u8 as char,
                    key: Key::from(value),
                    modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8
                });
            }
        }
        OpCode::EditorSetKnobMode => {
            if let Some(editor) = plugin.get_editor() {
                editor.set_knob_mode(KnobMode::from(value));
            }
        }

        _ => {
            warn!("Unimplemented opcode ({:?})", opcode);
            trace!("Arguments; index: {}, value: {}, ptr: {:?}, opt: {}", index, value, ptr, opt);
        }
    }

    0
}

pub fn host_dispatch(host: &mut Host,
                     effect: *mut AEffect,
                     opcode: i32,
                     index: i32,
                     value: isize,
                     ptr: *mut c_void,
                     opt: f32) -> isize {
    use host::OpCode;

    match OpCode::from(opcode) {
        OpCode::Version => return 2400,
        OpCode::Automate => host.automate(index, opt),

        OpCode::Idle => host.idle(),

        // ...

        OpCode::CanDo => {
            info!("Plugin is asking if host can: {}.", read_string(ptr));
        }

        OpCode::GetVendorVersion => return host.get_info().0,
        OpCode::GetVendorString => copy_string(ptr, &host.get_info().1, MAX_VENDOR_STR_LEN),
        OpCode::GetProductString => copy_string(ptr, &host.get_info().2, MAX_PRODUCT_STR_LEN),
        OpCode::ProcessEvents => {
            let events: *const api::Events = ptr as *const api::Events;

            let events: Vec<Event> = unsafe {
                // Create a slice of type &mut [*mut Event]
                slice::from_raw_parts(&(*events).events[0], (*events).num_events as usize)
                // Deref and clone each event to get a slice
                .iter().map(|item| Event::from(**item)).collect()
            };

            host.process_events(events);
        }

        unimplemented => {
            trace!("VST: Got unimplemented host opcode ({:?})", unimplemented);
            trace!("Arguments; effect: {:?}, index: {}, value: {}, ptr: {:?}, opt: {}",
                    effect, index, value, ptr, opt);
        }
    }
    0
}

// Read a string from the `ptr` buffer
fn read_string(ptr: *mut c_void) -> String {
    use std::ffi::CStr;

    String::from_utf8_lossy(
        unsafe { CStr::from_ptr(ptr as *mut c_char).to_bytes() }
    ).into_owned()
}

/// Translate `Vec<Event>` into `&api::Events` and use via a callback.
///
/// Both plugins and hosts can receive VST events, this simply translates the rust structure into
/// the equivalent API structure and takes care of cleanup.
pub fn process_events<F>(events: Vec<Event>, callback: F)
    where F: FnOnce(*mut c_void)
{
    use api::flags::REALTIME_EVENT;

    let len = events.len();

    // The `api::Events` structure uses a variable length array which is difficult to represent in
    // rust. We begin by creating a vector with the appropriate byte size by calculating the header
    // and the variable length body seperately.
    let header_size = mem::size_of::<api::Events>() - (mem::size_of::<*mut api::Event>() * 2);
    let body_size = mem::size_of::<*mut api::Event>() * len;

    let mut send = vec![0u8; header_size + body_size];

    let send_events: &mut [*mut api::Event] = unsafe {
        // The header is updated by casting the array to the `api::Events` type and specifying the
        // required fields. We create a slice from the position of the first event and the length
        // of the array.
        let ptr = send.as_mut_ptr() as *mut api::Events;
        (*ptr).num_events = len as i32;

        // A slice view of the body
        slice::from_raw_parts_mut(&mut (*ptr).events[0], len)
    };

    // Each event is zipped with the target body array slot. Most of what's happening here is just
    // copying data but the key thing to notice is that each event is boxed and cast to
    // (*mut api::Event). This way we can let the callback handle the event, and then later create
    // the box again from the raw pointer so that it can be properly dropped.
    for (event, out) in events.iter().zip(send_events.iter_mut()) {
        *out = match *event {
            Event::Midi { data, delta_frames, live,
                          note_length, note_offset,
                          detune, note_off_velocity } => {
                Box::into_raw(Box::new(api::MidiEvent {
                    event_type: api::EventType::Midi,
                    byte_size: mem::size_of::<api::MidiEvent>() as i32,
                    delta_frames: delta_frames,
                    flags: if live { REALTIME_EVENT.bits() } else { 0 },
                    note_length: note_length.unwrap_or(0),
                    note_offset: note_offset.unwrap_or(0),
                    midi_data: data,
                    _midi_reserved: 0,
                    detune: detune,
                    note_off_velocity: note_off_velocity,
                    _reserved1: 0,
                    _reserved2: 0
                })) as *mut api::Event
            }
            Event::SysEx { payload, delta_frames } => {
                Box::into_raw(Box::new(api::SysExEvent {
                    event_type: api::EventType::SysEx,
                    byte_size: mem::size_of::<api::SysExEvent>() as i32,
                    delta_frames: delta_frames,
                    _flags: 0,
                    data_size: payload.len() as i32,
                    _reserved1: 0,
                    system_data: payload.as_ptr() as *const u8 as *mut u8,
                    _reserved2: 0,
                })) as *mut api::Event
            }
            Event::Deprecated(e) => Box::into_raw(Box::new(e))
        };
    }

    // Allow the callback to use the pointer
    callback(send.as_mut_ptr() as *mut c_void);

    // Clean up the created events
    unsafe {
        for &mut event in send_events {
            match (*event).event_type {
                api::EventType::Midi => {
                    drop(Box::from_raw(event as *mut api::MidiEvent));
                }
                api::EventType::SysEx => {
                    drop(Box::from_raw(event as *mut api::SysExEvent));
                }
                _ => {
                    drop(Box::from_raw(event));
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add some tests for SecretService<commit_after><|endoftext|>