<commit_before>#![doc="Defines generic traits for numbers on which
SciRust library works.
"]

// std imports
use std::num::{Int, SignedInt, Float};

// complex numbers
pub use external::complex::{Complex32, Complex64};

// local imports
use entry::{Entry, Zero, One};

/// Defines basic requirements for a matrix of numbers
pub trait Number : Entry
    + Clone
    + Copy
    + Add<Self,Self>
    + Sub<Self, Self>
    + Mul<Self, Self>
    + Div<Self, Self>
    + PartialEq
    + One
    + Zero{

    #[inline]
    fn is_float(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        false
    }

    #[inline]
    fn is_complex(&self) -> bool {
        false
    }

    fn is_signed(&self) -> bool;
}

pub trait Signed: Number + Neg<Self> {
    fn abs_val(&self) -> Self;
    fn signum(&self) -> Self;
    fn is_positive(&self) -> bool;
    fn is_negative(&self) -> bool;
}

/******************************************************
 *      i8 implementation
 ******************************************************/

/// Indicate that i8 fits all requirements for being a matrix element.
impl Number for i8 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

}

impl Signed for i8 {

    #[inline]
    fn abs_val(&self) -> i8{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i8{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i16 implementation
 ******************************************************/

/// Indicate that i16 fits all requirements for being a matrix element.
impl Number for i16 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i16 {

    #[inline]
    fn abs_val(&self) -> i16{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i16{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i32 implementation
 ******************************************************/

/// Indicate that i32 fits all requirements for being a matrix element.
impl Number for i32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i32 {

    #[inline]
    fn abs_val(&self) -> i32{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i32{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i64 implementation
 ******************************************************/

/// Indicate that i64 fits all requirements for being a matrix element.
impl Number for i64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i64 {

    #[inline]
    fn abs_val(&self) -> i64{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i64{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      int implementation
 ******************************************************/

/// Indicate that int fits all requirements for being a matrix element.
impl Number for int {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for int {

    #[inline]
    fn abs_val(&self) -> int{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> int{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      u8 implementation
 ******************************************************/

/// Indicate that u8 fits all requirements for being a matrix element.
impl Number for u8 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u16 implementation
 ******************************************************/

/// Indicate that u16 fits all requirements for being a matrix element.
impl Number for u16 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u32 implementation
 ******************************************************/

/// Indicate that u32 fits all requirements for being a matrix element.
impl Number for u32 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u64 implementation
 ******************************************************/

/// Indicate that u64 fits all requirements for being a matrix element.
impl Number for u64 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      uint implementation
 ******************************************************/

/// Indicate that uint fits all requirements for being a matrix element.
impl Number for uint {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      f32 implementation
 ******************************************************/

/// Indicate that f32 fits all requirements for being a matrix element.
impl Number for f32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

impl Signed for f32 {

    #[inline]
    fn abs_val(&self) -> f32{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> f32{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      f64 implementation
 ******************************************************/

/// Indicate that f64 fits all requirements for being a matrix element.
impl Number for f64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

impl Signed for f64 {

    #[inline]
    fn abs_val(&self) -> f64{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> f64{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      Complex32 implementation
 ******************************************************/

/// Indicate that Complex32 fits all requirements for being a matrix element.
impl Number for Complex32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

/******************************************************
 *      Complex64 implementation
 ******************************************************/

/// Indicate that Complex64 fits all requirements for being a matrix element.
impl Number for Complex64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

//TODO: figure out how to make this work.
pub fn describe<T: Number>(z : T){
     println!("Signed: {}", z.is_signed());
}

/******************************************************
 *
 *   Number range
 *
 *******************************************************/

/// An iterator over the range [start, stop)
#[deriving(Clone)]
pub struct NumRange<A> {
    state: A,
    stop: A,
    one: A
}

/// Returns an iterator over the given range [start, stop) (that is, starting
/// at start (inclusive), and ending at stop (exclusive)).
#[inline]
pub fn num_range<A: Number + PartialOrd + One>(start: A, stop: A) -> NumRange<A> {
    NumRange{state: start, stop: stop, one: One::one()}
}

impl<A: Number + PartialOrd + One + ToPrimitive> Iterator<A> for NumRange<A> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.state < self.stop {
            let result = self.state.clone();
            self.state = self.state + self.one;
            Some(result)
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        // This first checks if the elements are representable as i64. If they aren't, try u64 (to
        // handle cases like range(huge, huger)). We don't use uint/int because the difference of
        // the i64/u64 might lie within their range.
        let bound = match self.state.to_i64() {
            Some(a) => {
                let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
                match sz {
                    Some(Some(bound)) => bound.to_uint(),
                    _ => None,
                }
            },
            None => match self.state.to_u64() {
                Some(a) => {
                    let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
                    match sz {
                        Some(Some(bound)) => bound.to_uint(),
                        _ => None
                    }
                },
                None => None
            }
        };

        match bound {
            Some(b) => (b, Some(b)),
            // Standard fallback for unbounded/unrepresentable bounds
            None => (0, None)
        }
    }
}

/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/

#[cfg(test)]
mod tests {

    use super::*;
    use entry::Zero;

    #[test]
    fn  test_introspection_i64(){
       let z : i64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(!z.is_complex());
        assert!(z.is_int());
    }

    #[test]
    fn  test_introspection_f64(){
       let z : f64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(z.is_float());
        assert!(!z.is_complex());
        assert!(!z.is_int());
    }

    #[test]
    fn  test_introspection_c64(){
       let z : Complex64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(z.is_complex());
        assert!(!z.is_int());
    }

}<commit_msg>power<commit_after>#![doc="Defines generic traits for numbers on which
SciRust library works.
"]

// std imports
use std::num::{Int, SignedInt, Float};

// complex numbers
pub use external::complex::{Complex32, Complex64};

// local imports
use entry::{Entry, Zero, One};

/// Defines basic requirements for a matrix of numbers
pub trait Number : Entry
    + Clone
    + Copy
    + Add<Self,Self>
    + Sub<Self, Self>
    + Mul<Self, Self>
    + Div<Self, Self>
    + PartialEq
    + One
    + Zero{

    #[inline]
    fn is_float(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        false
    }

    #[inline]
    fn is_complex(&self) -> bool {
        false
    }

    fn is_signed(&self) -> bool;

    fn power(&self, n : uint)-> Self{
        if n == 0 {
            return One::one();
        }
        let mut result = *self;
        for _ in range(0, n - 1){
            result = result.mul(self);
        }
        result
    }
}

pub trait Signed: Number + Neg<Self> {
    fn abs_val(&self) -> Self;
    fn signum(&self) -> Self;
    fn is_positive(&self) -> bool;
    fn is_negative(&self) -> bool;
}

/******************************************************
 *      i8 implementation
 ******************************************************/

/// Indicate that i8 fits all requirements for being a matrix element.
impl Number for i8 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

}

impl Signed for i8 {

    #[inline]
    fn abs_val(&self) -> i8{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i8{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i16 implementation
 ******************************************************/

/// Indicate that i16 fits all requirements for being a matrix element.
impl Number for i16 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i16 {

    #[inline]
    fn abs_val(&self) -> i16{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i16{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i32 implementation
 ******************************************************/

/// Indicate that i32 fits all requirements for being a matrix element.
impl Number for i32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i32 {

    #[inline]
    fn abs_val(&self) -> i32{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i32{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      i64 implementation
 ******************************************************/

/// Indicate that i64 fits all requirements for being a matrix element.
impl Number for i64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for i64 {

    #[inline]
    fn abs_val(&self) -> i64{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> i64{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      int implementation
 ******************************************************/

/// Indicate that int fits all requirements for being a matrix element.
impl Number for int {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

impl Signed for int {

    #[inline]
    fn abs_val(&self) -> int{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> int{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      u8 implementation
 ******************************************************/

/// Indicate that u8 fits all requirements for being a matrix element.
impl Number for u8 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u16 implementation
 ******************************************************/

/// Indicate that u16 fits all requirements for being a matrix element.
impl Number for u16 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u32 implementation
 ******************************************************/

/// Indicate that u32 fits all requirements for being a matrix element.
impl Number for u32 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      u64 implementation
 ******************************************************/

/// Indicate that u64 fits all requirements for being a matrix element.
impl Number for u64 {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      uint implementation
 ******************************************************/

/// Indicate that uint fits all requirements for being a matrix element.
impl Number for uint {

    #[inline]
    fn is_signed(&self) -> bool {
        false
    }

    #[inline]
    fn is_int(&self) -> bool {
        true
    }

}

/******************************************************
 *      f32 implementation
 ******************************************************/

/// Indicate that f32 fits all requirements for being a matrix element.
impl Number for f32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

impl Signed for f32 {

    #[inline]
    fn abs_val(&self) -> f32{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> f32{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      f64 implementation
 ******************************************************/

/// Indicate that f64 fits all requirements for being a matrix element.
impl Number for f64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_float(&self) -> bool {
        true
    }

}

impl Signed for f64 {

    #[inline]
    fn abs_val(&self) -> f64{
        self.abs()
    }

    #[inline]
    fn signum(&self) -> f64{
        self.signum()
    }

    #[inline]
    fn is_positive(&self) -> bool{
        self.is_positive()
    }

    #[inline]
    fn is_negative(&self) -> bool{
        self.is_negative()
    }
}

/******************************************************
 *      Complex32 implementation
 ******************************************************/

/// Indicate that Complex32 fits all requirements for being a matrix element.
impl Number for Complex32 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

/******************************************************
 *      Complex64 implementation
 ******************************************************/

/// Indicate that Complex64 fits all requirements for being a matrix element.
impl Number for Complex64 {

    #[inline]
    fn is_signed(&self) -> bool {
        true
    }

    #[inline]
    fn is_complex(&self) -> bool {
        true
    }

}

//TODO: figure out how to make this work.
pub fn describe<T: Number>(z : T){
     println!("Signed: {}", z.is_signed());
}

/******************************************************
 *
 *   Number range
 *
 *******************************************************/

/// An iterator over the range [start, stop)
#[deriving(Clone)]
pub struct NumRange<A> {
    state: A,
    stop: A,
    one: A
}

/// Returns an iterator over the given range [start, stop) (that is, starting
/// at start (inclusive), and ending at stop (exclusive)).
#[inline]
pub fn num_range<A: Number + PartialOrd + One>(start: A, stop: A) -> NumRange<A> {
    NumRange{state: start, stop: stop, one: One::one()}
}

impl<A: Number + PartialOrd + One + ToPrimitive> Iterator<A> for NumRange<A> {
    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.state < self.stop {
            let result = self.state.clone();
            self.state = self.state + self.one;
            Some(result)
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        // This first checks if the elements are representable as i64. If they aren't, try u64 (to
        // handle cases like range(huge, huger)). We don't use uint/int because the difference of
        // the i64/u64 might lie within their range.
        let bound = match self.state.to_i64() {
            Some(a) => {
                let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
                match sz {
                    Some(Some(bound)) => bound.to_uint(),
                    _ => None,
                }
            },
            None => match self.state.to_u64() {
                Some(a) => {
                    let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
                    match sz {
                        Some(Some(bound)) => bound.to_uint(),
                        _ => None
                    }
                },
                None => None
            }
        };

        match bound {
            Some(b) => (b, Some(b)),
            // Standard fallback for unbounded/unrepresentable bounds
            None => (0, None)
        }
    }
}

/******************************************************
 *
 *   Unit tests follow.
 *
 *******************************************************/

#[cfg(test)]
mod tests {

    use super::*;
    use entry::Zero;

    #[test]
    fn  test_introspection_i64(){
       let z : i64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(!z.is_complex());
        assert!(z.is_int());
    }

    #[test]
    fn  test_introspection_f64(){
       let z : f64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(z.is_float());
        assert!(!z.is_complex());
        assert!(!z.is_int());
    }

    #[test]
    fn  test_introspection_c64(){
       let z : Complex64 = Zero::zero();
        describe(z);
        assert!(z.is_signed());
        assert!(!z.is_float());
        assert!(z.is_complex());
        assert!(!z.is_int());
    }

}<|endoftext|>


<commit_before>extern crate env_logger;
extern crate tsutils;

#[macro_use]
extern crate log;

fn main() {
    env_logger::init().unwrap();

    let input = std::io::stdin();
    let output = std::io::stdout();
    drop_av(input, output).unwrap();
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    PsiParseError(tsutils::psi::ParseError),
    Custom(std::borrow::Cow<'static, str>),
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<&'static str> for Error {
    fn from(e: &'static str) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<String> for Error {
    fn from(e: String) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<tsutils::psi::ParseError> for Error {
    fn from(e: tsutils::psi::ParseError) -> Self {
        Error::PsiParseError(e)
    }
}

fn drop_av<R, W>(reader: R, mut writer: W) -> Result<(), Error>
    where R: std::io::Read,
          W: std::io::Write
{
    let mut pat = None;
    let mut payloads: std::collections::HashMap<u16, Vec<u8>> = std::collections::HashMap::new();
    let mut av_pids = std::collections::HashSet::new();
    let mut nonav_pids = std::collections::HashSet::new();

    for buf in tsutils::packet::ts_packets(reader) {
        let buf = try!(buf);
        let packet = tsutils::TsPacket::new(&buf);
        if !packet.check_sync_byte() {
            return Err(Error::from("sync_byte failed"));
        }
        if packet.transport_error_indicator {
            return Err(Error::from("transport_error_indicator is set"));
        }

        if packet.payload_unit_start_indicator {
            if let Some(payload) = payloads.get(&packet.pid) {
                match packet.pid {
                    0x0000 => {
                        pat = Some(try!(tsutils::ProgramAssociationTable::parse(payload)));
                    }
                    _ => {
                        if let Some(ref pat) = pat {
                            if let Some(&program_number) = pat.program_map.get(&packet.pid) {
                                let pmt = try!(tsutils::ProgramMapTable::parse(payload));
                                if pmt.program_number != program_number {
                                    return Err(Error::from(format!("Inconsistent \
                                                                    program_number for PID={}: \
                                                                    PAT says {} but PMT says {}",
                                                                   packet.pid,
                                                                   program_number,
                                                                   pmt.program_number)));
                                }
                                for es in pmt.es_info {
                                    if !av_pids.contains(&es.elementary_pid) &&
                                       !nonav_pids.contains(&es.elementary_pid) {
                                        match es.stream_type {
                                            0x0f => {
                                                // Audio
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            0x02 | 0x1b => {
                                                // Video
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            _ => {
                                                debug!("non-AV stream_type={:x} pid={:x}",
                                                       es.stream_type,
                                                       es.elementary_pid);
                                                nonav_pids.insert(es.elementary_pid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if let Some(data_bytes) = packet.data_bytes {
                payloads.insert(packet.pid, data_bytes.to_vec());
            } else {
                return Err(Error::from("payload_unit_start_indicator is set, but no \
                                                 data_bytes"));
            }
        } else {
            if let Some(data_bytes) = packet.data_bytes {
                match payloads.entry(packet.pid) {
                    std::collections::hash_map::Entry::Occupied(mut entry) => {
                        entry.get_mut().extend_from_slice(data_bytes);
                    }
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(data_bytes.to_vec());
                    }
                }
            }
        }

        if !av_pids.contains(&packet.pid) {
            try!(writer.write(&buf));
        }
    }
    Ok(())
}
<commit_msg>tsutils-drop-av infile outfile<commit_after>extern crate env_logger;
extern crate tsutils;

#[macro_use]
extern crate log;

fn main() {
    env_logger::init().unwrap();

    let mut args = std::env::args().skip(1);
    if let Some(input_path) = args.next() {
        if let Some(output_path) = args.next() {
            let input = std::fs::File::open(input_path).unwrap();
            let output = std::fs::File::create(output_path).unwrap();
            drop_av(input, output).unwrap();
            return;
        }
    }
    std::process::exit(1);
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    PsiParseError(tsutils::psi::ParseError),
    Custom(std::borrow::Cow<'static, str>),
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<&'static str> for Error {
    fn from(e: &'static str) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<String> for Error {
    fn from(e: String) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<tsutils::psi::ParseError> for Error {
    fn from(e: tsutils::psi::ParseError) -> Self {
        Error::PsiParseError(e)
    }
}

fn drop_av<R, W>(reader: R, mut writer: W) -> Result<(), Error>
    where R: std::io::Read,
          W: std::io::Write
{
    let mut pat = None;
    let mut payloads: std::collections::HashMap<u16, Vec<u8>> = std::collections::HashMap::new();
    let mut av_pids = std::collections::HashSet::new();
    let mut nonav_pids = std::collections::HashSet::new();

    for buf in tsutils::packet::ts_packets(reader) {
        let buf = try!(buf);
        let packet = tsutils::TsPacket::new(&buf);
        if !packet.check_sync_byte() {
            return Err(Error::from("sync_byte failed"));
        }
        if packet.transport_error_indicator {
            return Err(Error::from("transport_error_indicator is set"));
        }

        if packet.payload_unit_start_indicator {
            if let Some(payload) = payloads.get(&packet.pid) {
                match packet.pid {
                    0x0000 => {
                        pat = Some(try!(tsutils::ProgramAssociationTable::parse(payload)));
                    }
                    _ => {
                        if let Some(ref pat) = pat {
                            if let Some(&program_number) = pat.program_map.get(&packet.pid) {
                                let pmt = try!(tsutils::ProgramMapTable::parse(payload));
                                if pmt.program_number != program_number {
                                    return Err(Error::from(format!("Inconsistent \
                                                                    program_number for PID={}: \
                                                                    PAT says {} but PMT says {}",
                                                                   packet.pid,
                                                                   program_number,
                                                                   pmt.program_number)));
                                }
                                for es in pmt.es_info {
                                    if !av_pids.contains(&es.elementary_pid) &&
                                       !nonav_pids.contains(&es.elementary_pid) {
                                        match es.stream_type {
                                            0x0f => {
                                                // Audio
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            0x02 | 0x1b => {
                                                // Video
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            _ => {
                                                debug!("non-AV stream_type={:x} pid={:x}",
                                                       es.stream_type,
                                                       es.elementary_pid);
                                                nonav_pids.insert(es.elementary_pid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if let Some(data_bytes) = packet.data_bytes {
                payloads.insert(packet.pid, data_bytes.to_vec());
            } else {
                return Err(Error::from("payload_unit_start_indicator is set, but no \
                                                 data_bytes"));
            }
        } else {
            if let Some(data_bytes) = packet.data_bytes {
                match payloads.entry(packet.pid) {
                    std::collections::hash_map::Entry::Occupied(mut entry) => {
                        entry.get_mut().extend_from_slice(data_bytes);
                    }
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(data_bytes.to_vec());
                    }
                }
            }
        }

        if !av_pids.contains(&packet.pid) {
            try!(writer.write(&buf));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! Operator norm

use ndarray::*;

use crate::convert::*;
use crate::error::*;
use crate::layout::*;
use crate::tridiagonal::TriDiagonal;
use crate::types::*;

pub use crate::lapack::NormType;

/// Operator norm using `*lange` LAPACK routines
///
/// [Wikipedia article on operator norm](https://en.wikipedia.org/wiki/Operator_norm)
pub trait OperationNorm {
    /// the value of norm
    type Output: Scalar;

    fn opnorm(&self, t: NormType) -> Result<Self::Output>;

    /// the one norm of a matrix (maximum column sum)
    fn opnorm_one(&self) -> Result<Self::Output> {
        self.opnorm(NormType::One)
    }

    /// the infinity norm of a matrix (maximum row sum)
    fn opnorm_inf(&self) -> Result<Self::Output> {
        self.opnorm(NormType::Infinity)
    }

    /// the Frobenius norm of a matrix (square root of sum of squares)
    fn opnorm_fro(&self) -> Result<Self::Output> {
        self.opnorm(NormType::Frobenius)
    }
}

impl OperationNorm for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type Output = A::Real;

    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
        let l = self.layout()?;
        let a = self.as_allocated()?;
        Ok(unsafe { A::opnorm(t, l, a) })
    }
}

impl OperationNorm for TriDiagonal
where
    A: Scalar + Lapack,
{
    type Output = A::Real;

    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
        let arr = match t {
            NormType::One => {
                let zl: Array1 = Array::zeros(1);
                let zu: Array1 = Array::zeros(1);
                let dl = stack![Axis(0), self.dl.to_owned(), zl];
                let du = stack![Axis(0), zu, self.du.to_owned()];
                let arr = stack![
                    Axis(0),
                    into_row(du),
                    into_row(self.d.to_owned()),
                    into_row(dl)
                ];
                arr
            }
            NormType::Infinity => {
                let zl: Array1 = Array::zeros(1);
                let zu: Array1 = Array::zeros(1);
                let dl = stack![Axis(0), zl, self.dl.to_owned()];
                let du = stack![Axis(0), self.du.to_owned(), zu];
                let arr = stack![
                    Axis(1),
                    into_col(dl),
                    into_col(self.d.to_owned()),
                    into_col(du)
                ];
                arr
            }
            NormType::Frobenius => {
                let arr = stack![
                    Axis(1),
                    into_row(self.dl.to_owned()),
                    into_row(self.d.to_owned()),
                    into_row(self.du.to_owned())
                ];
                arr
            }
        };

        let l = arr.layout()?;
        let a = arr.as_allocated()?;
        Ok(unsafe { A::opnorm(t, l, a) })
    }
}
<commit_msg>add comments on opnorm<commit_after>//! Operator norm

use ndarray::*;

use crate::convert::*;
use crate::error::*;
use crate::layout::*;
use crate::tridiagonal::TriDiagonal;
use crate::types::*;

pub use crate::lapack::NormType;

/// Operator norm using `*lange` LAPACK routines
///
/// [Wikipedia article on operator norm](https://en.wikipedia.org/wiki/Operator_norm)
pub trait OperationNorm {
    /// the value of norm
    type Output: Scalar;

    fn opnorm(&self, t: NormType) -> Result<Self::Output>;

    /// the one norm of a matrix (maximum column sum)
    fn opnorm_one(&self) -> Result<Self::Output> {
        self.opnorm(NormType::One)
    }

    /// the infinity norm of a matrix (maximum row sum)
    fn opnorm_inf(&self) -> Result<Self::Output> {
        self.opnorm(NormType::Infinity)
    }

    /// the Frobenius norm of a matrix (square root of sum of squares)
    fn opnorm_fro(&self) -> Result<Self::Output> {
        self.opnorm(NormType::Frobenius)
    }
}

impl OperationNorm for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type Output = A::Real;

    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
        let l = self.layout()?;
        let a = self.as_allocated()?;
        Ok(unsafe { A::opnorm(t, l, a) })
    }
}

impl OperationNorm for TriDiagonal
where
    A: Scalar + Lapack,
{
    type Output = A::Real;

    fn opnorm(&self, t: NormType) -> Result<Self::Output> {
        // `self` is a tridiagonal matrix like,
        // [d0, u1,  0,   ...,       0,
        //  l1, d1, u2,            ...,
        //   0, l2, d2,
        //  ...           ...,  u{n-1},
        //   0,  ...,  l{n-1},  d{n-1},]
        let arr = match t {
            // opnorm_one() calculates muximum column sum.
            // Therefore, This part align the columns and make a (3 x n) matrix like,
            // [ 0, u1, u2, ..., u{n-1},
            //  d0, d1, d2, ..., d{n-1},
            //  l1, l2, l3, ...,      0,]
            NormType::One => {
                let zl: Array1 = Array::zeros(1);
                let zu: Array1 = Array::zeros(1);
                let dl = stack![Axis(0), self.dl.to_owned(), zl];
                let du = stack![Axis(0), zu, self.du.to_owned()];
                let arr = stack![
                    Axis(0),
                    into_row(du),
                    into_row(self.d.to_owned()),
                    into_row(dl)
                ];
                arr
            }
            // opnorm_inf() calculates muximum row sum.
            // Therefore, This part align the rows and make a (n x 3) matrix like,
            // [     0,     d0,     u1,
            //      l1,     d1,     u2,
            //      l2,     d2,     u3,
            //     ...,    ...,    ...,
            //  l{n-1}, d{n-1},      0,]
            NormType::Infinity => {
                let zl: Array1 = Array::zeros(1);
                let zu: Array1 = Array::zeros(1);
                let dl = stack![Axis(0), zl, self.dl.to_owned()];
                let du = stack![Axis(0), self.du.to_owned(), zu];
                let arr = stack![
                    Axis(1),
                    into_col(dl),
                    into_col(self.d.to_owned()),
                    into_col(du)
                ];
                arr
            }
            // opnorm_fro() calculates square root of sum of squares.
            // Because it is independent of the shape of matrix,
            // this part make a (1 x (3n-2)) matrix like,
            // [l1, ..., l{n-1}, d0, ..., d{n-1}, u1, ..., u{n-1}]
            NormType::Frobenius => {
                let arr = stack![
                    Axis(1),
                    into_row(self.dl.to_owned()),
                    into_row(self.d.to_owned()),
                    into_row(self.du.to_owned())
                ];
                arr
            }
        };

        let l = arr.layout()?;
        let a = arr.as_allocated()?;
        Ok(unsafe { A::opnorm(t, l, a) })
    }
}
<|endoftext|>


<commit_before>use nom::{self, IResult};
use std::str;
use proto::{Address, Attribute, Envelope, MailboxDatum};
use proto::{RequestId, Response, ResponseCode, Status};

fn crlf(c: u8) -> bool {
    c == b'\r' || c == b'\n'
}

fn list_wildcards(c: u8) -> bool {
    c == b'%' || c == b'*'
}

fn quoted_specials(c: u8) -> bool {
    c == b'"' || c == b'\\'
}

fn resp_specials(c: u8) -> bool {
    c == b']'
}

fn atom_specials(c: u8) -> bool {
    c == b'(' || c == b')' || c == b'{' || c == b' ' || c < 32 ||
    list_wildcards(c) || quoted_specials(c) || resp_specials(c)
}

fn atom_char(c: u8) -> bool {
    !atom_specials(c)
}

fn astring_char(c: u8) -> bool {
    atom_char(c) || resp_specials(c)
}

fn tag_char(c: u8) -> bool {
    c != b'+' && astring_char(c)
}

named!(quoted_data<&[u8], &str, u32>, map!(
    //escaped!(take_till_s!(quoted_specials), '\\', one_of!("\"\\")),
    take_till_s!(quoted_specials),
    |s| str::from_utf8(s).unwrap()
));

named!(quoted<&str>, do_parse!(
    tag_s!("\"") >>
    data: quoted_data >>
    tag_s!("\"") >>
    (data)
));

named!(status_ok<Status>, map!(tag_no_case!("OK"),
    |s| Status::Ok
));
named!(status_no<Status>, map!(tag_no_case!("NO"),
    |s| Status::No
));
named!(status_bad<Status>, map!(tag_no_case!("BAD"),
    |s| Status::Bad
));
named!(status_preauth<Status>, map!(tag_no_case!("PREAUTH"),
    |s| Status::PreAuth
));
named!(status_bye<Status>, map!(tag_no_case!("BYE"),
    |s| Status::Bye
));

named!(status<Status>, alt!(
    status_ok |
    status_no |
    status_bad |
    status_preauth |
    status_bye
));

named!(number<u32>, map!(nom::digit,
    |s| str::parse(str::from_utf8(s).unwrap()).unwrap()
));

named!(number_64<u64>, map!(nom::digit,
    |s| str::parse(str::from_utf8(s).unwrap()).unwrap()
));

named!(text<&str>, map!(take_till_s!(crlf),
    |s| str::from_utf8(s).unwrap()
));

named!(atom<&str>, map!(take_while1_s!(atom_char),
    |s| str::from_utf8(s).unwrap()
));

fn flag_extension(i: &[u8]) -> IResult<&[u8], &str> {
    if i.len() < 1 || i[0] != b'\\' {
        return IResult::Error(nom::ErrorKind::Custom(0));
    }
    let mut last = 0;
    for (idx, c) in i[1..].iter().enumerate() {
        last = idx;
        if !atom_char(*c) {
            break;
        }
    }
    IResult::Done(&i[last + 1..], str::from_utf8(&i[..last + 1]).unwrap())
}

named!(flag<&str>, alt!(flag_extension | atom));

named!(flag_list<Vec<&str>>, do_parse!(
    tag_s!("(") >>
    elements: opt!(do_parse!(
        flag0: flag >>
        flags: many0!(do_parse!(
            tag_s!(" ") >>
            flag: flag >>
            (flag)
        )) >> ({
            let mut res = vec![flag0];
            res.extend(flags);
            res
        })
    )) >>
    tag_s!(")") >> ({
       if elements.is_some() {
           elements.unwrap()
       } else {
           Vec::new()
       }
    })
));

named!(flag_perm<&str>, alt!(
    map!(tag_s!("\\*"), |s| str::from_utf8(s).unwrap()) |
    flag
));

named!(resp_text_code_permanent_flags<ResponseCode>, do_parse!(
    tag_s!("PERMANENTFLAGS (") >>
    elements: dbg_dmp!(opt!(do_parse!(
        flag0: flag_perm >>
        flags: many0!(do_parse!(
            tag_s!(" ") >>
            flag: flag_perm >>
            (flag)
        )) >> ({
            let mut res = vec![flag0];
            res.extend(flags);
            res
        })
    ))) >>
    tag_s!(")") >> ({
        ResponseCode::PermanentFlags(if elements.is_some() {
            elements.unwrap()
        } else {
            Vec::new()
        })
    })
));

named!(resp_text_code_highest_mod_seq<ResponseCode>, dbg_dmp!(do_parse!(
    tag_s!("HIGHESTMODSEQ ") >>
    num: number_64 >>
    (ResponseCode::HighestModSeq(num))
)));

named!(resp_text_code_read_only<ResponseCode>, do_parse!(
    tag_s!("READ-ONLY") >>
    (ResponseCode::ReadOnly)
));

named!(resp_text_code_read_write<ResponseCode>, do_parse!(
    tag_s!("READ-WRITE") >>
    (ResponseCode::ReadWrite)
));

named!(resp_text_code_try_create<ResponseCode>, do_parse!(
    tag_s!("TRYCREATE") >>
    (ResponseCode::TryCreate)
));

named!(resp_text_code_uid_validity<ResponseCode>, do_parse!(
    tag_s!("UIDVALIDITY ") >>
    num: number >>
    (ResponseCode::UidValidity(num))
));

named!(resp_text_code_uid_next<ResponseCode>, do_parse!(
    tag_s!("UIDNEXT ") >>
    num: number >>
    (ResponseCode::UidNext(num))
));

named!(resp_text_code<ResponseCode>, do_parse!(
    tag_s!("[") >>
    coded: alt!(
        resp_text_code_permanent_flags |
        resp_text_code_uid_validity |
        resp_text_code_uid_next |
        resp_text_code_read_only |
        resp_text_code_read_write |
        resp_text_code_try_create |
        resp_text_code_highest_mod_seq
    ) >>
    // Per the spec, the closing tag should be "] ".
    // See `resp_text` for more on why this is done differently.
    tag_s!("]") >>
    (coded)
));

named!(capability<&str>, do_parse!(
    tag_s!(" ") >>
    atom: take_till1_s!(atom_specials) >>
    (str::from_utf8(atom).unwrap())
));

named!(capability_data<Response>, do_parse!(
    tag_s!("CAPABILITY") >>
    capabilities: many1!(capability) >>
    (Response::Capabilities(capabilities))
));

named!(mailbox_data_flags<Response>, do_parse!(
    tag_s!("FLAGS ") >>
    flags: flag_list >>
    (Response::MailboxData(MailboxDatum::Flags(flags)))
));

named!(mailbox_data_exists<Response>, do_parse!(
    num: number >>
    tag_s!(" EXISTS") >>
    (Response::MailboxData(MailboxDatum::Exists(num)))
));

named!(mailbox_data_recent<Response>, do_parse!(
    num: number >>
    tag_s!(" RECENT") >>
    (Response::MailboxData(MailboxDatum::Recent(num)))
));

named!(mailbox_data<Response>, alt!(
    mailbox_data_flags |
    mailbox_data_exists |
    mailbox_data_recent
));

named!(nstring<Option<&str>>, map!(
    alt!(
        map!(tag_s!("NIL"), |s| str::from_utf8(s).unwrap()) |
        quoted
    ),
    |s| if s == "NIL" { None } else { Some(s) }
));

named!(address<Address>, do_parse!(
    tag_s!("(") >>
    name: nstring >>
    tag_s!(" ") >>
    adl: nstring >>
    tag_s!(" ") >>
    mailbox: nstring >>
    tag_s!(" ") >>
    host: nstring >>
    tag_s!(")") >>
    (Address { name, adl, mailbox, host })
));

named!(opt_addresses<Option<Vec<Address>>>, alt!(
    map!(tag_s!("NIL"), |s| None) |
    do_parse!(
        tag_s!("(") >>
        addrs: many1!(address) >>
        tag_s!(")") >>
        (Some(addrs))
    )
));

named!(msg_att_envelope<Attribute>, do_parse!(
    tag_s!("ENVELOPE (") >>
    date: nstring >>
    tag_s!(" ") >>
    subject: nstring >>
    tag_s!(" ") >>
    from: opt_addresses >>
    tag_s!(" ") >>
    sender: opt_addresses >>
    tag_s!(" ") >>
    reply_to: opt_addresses >>
    tag_s!(" ") >>
    to: opt_addresses >>
    tag_s!(" ") >>
    cc: opt_addresses >>
    tag_s!(" ") >>
    bcc: opt_addresses >>
    tag_s!(" ") >>
    in_reply_to: nstring >>
    tag_s!(" ") >>
    message_id: nstring >>
    tag_s!(")") >> ({
        Attribute::Envelope(Envelope {
            date, subject, from, sender, reply_to, to, cc, bcc, in_reply_to, message_id
        })
    })
));

named!(msg_att_internal_date<Attribute>, do_parse!(
    tag_s!("INTERNALDATE ") >>
    date: nstring >>
    (Attribute::InternalDate(date.unwrap()))
));

named!(msg_att_flags<Attribute>, do_parse!(
    tag_s!("FLAGS ") >>
    flags: flag_list >>
    (Attribute::Flags(flags))
));

named!(msg_att_rfc822_size<Attribute>, do_parse!(
    tag_s!("RFC822.SIZE ") >>
    num: number >>
    (Attribute::Rfc822Size(num))
));

named!(msg_att<Attribute>, alt!(
    msg_att_envelope |
    msg_att_internal_date |
    msg_att_flags |
    msg_att_rfc822_size
));

named!(msg_att_list<Vec<Attribute>>, do_parse!(
    tag_s!("(") >>
    elements: do_parse!(
        attr0: msg_att >>
        attrs: many0!(do_parse!(
            tag_s!(" ") >>
            attr: msg_att >>
            (attr)
        )) >> ({
            let mut res = vec![attr0];
            res.extend(attrs);
            res
        })
    ) >>
    tag_s!(")") >>
    (elements)
));

named!(message_data_fetch<Response>, do_parse!(
    num: number >>
    tag_s!(" FETCH ") >>
    attrs: msg_att_list >>
    (Response::Fetch(num, attrs))
));

named!(message_data_expunge<Response>, do_parse!(
    num: number >>
    tag_s!(" EXPUNGE") >>
    (Response::Expunge(num))
));

named!(tag<RequestId>, map!(take_while1_s!(tag_char),
    |s| RequestId(str::from_utf8(s).unwrap().to_string())
));

// This is not quite according to spec, which mandates the following:
//     ["[" resp-text-code "]" SP] text
// However, examples in RFC 4551 (Conditional STORE) counteract this by giving
// examples of `resp-text` that do not include the trailing space and text.
named!(resp_text<(Option<ResponseCode>, Option<&str>)>, do_parse!(
    code: opt!(resp_text_code) >>
    text: text >>
    ((code, if text.len() > 0 { Some(&text[1..]) } else { None }))
));

named!(response_tagged<Response>, do_parse!(
    tag: tag >>
    tag_s!(" ") >>
    status: status >>
    tag_s!(" ") >>
    text: resp_text >>
    (Response::Done(tag, status, text.0, text.1))
));

named!(resp_cond<Response>, do_parse!(
    status: status >>
    tag_s!(" ") >>
    text: resp_text >>
    (Response::Data(status, text.0, text.1))
));

named!(response_data<Response>, do_parse!(
    tag_s!("* ") >>
    contents: alt!(
        resp_cond |
        mailbox_data |
        message_data_expunge |
        message_data_fetch |
        capability_data
    ) >>
    (contents)
));

named!(response<Response>, alt!(
    response_data |
    response_tagged
));

pub fn parse(msg: &str) -> Response {
    match response(msg.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete: {:?}", msg),
    }
}
<commit_msg>Fix bug in parsing post-code response text<commit_after>use nom::{self, IResult};
use std::str;
use proto::{Address, Attribute, Envelope, MailboxDatum};
use proto::{RequestId, Response, ResponseCode, Status};

fn crlf(c: u8) -> bool {
    c == b'\r' || c == b'\n'
}

fn list_wildcards(c: u8) -> bool {
    c == b'%' || c == b'*'
}

fn quoted_specials(c: u8) -> bool {
    c == b'"' || c == b'\\'
}

fn resp_specials(c: u8) -> bool {
    c == b']'
}

fn atom_specials(c: u8) -> bool {
    c == b'(' || c == b')' || c == b'{' || c == b' ' || c < 32 ||
    list_wildcards(c) || quoted_specials(c) || resp_specials(c)
}

fn atom_char(c: u8) -> bool {
    !atom_specials(c)
}

fn astring_char(c: u8) -> bool {
    atom_char(c) || resp_specials(c)
}

fn tag_char(c: u8) -> bool {
    c != b'+' && astring_char(c)
}

named!(quoted_data<&[u8], &str, u32>, map!(
    //escaped!(take_till_s!(quoted_specials), '\\', one_of!("\"\\")),
    take_till_s!(quoted_specials),
    |s| str::from_utf8(s).unwrap()
));

named!(quoted<&str>, do_parse!(
    tag_s!("\"") >>
    data: quoted_data >>
    tag_s!("\"") >>
    (data)
));

named!(status_ok<Status>, map!(tag_no_case!("OK"),
    |s| Status::Ok
));
named!(status_no<Status>, map!(tag_no_case!("NO"),
    |s| Status::No
));
named!(status_bad<Status>, map!(tag_no_case!("BAD"),
    |s| Status::Bad
));
named!(status_preauth<Status>, map!(tag_no_case!("PREAUTH"),
    |s| Status::PreAuth
));
named!(status_bye<Status>, map!(tag_no_case!("BYE"),
    |s| Status::Bye
));

named!(status<Status>, alt!(
    status_ok |
    status_no |
    status_bad |
    status_preauth |
    status_bye
));

named!(number<u32>, map!(nom::digit,
    |s| str::parse(str::from_utf8(s).unwrap()).unwrap()
));

named!(number_64<u64>, map!(nom::digit,
    |s| str::parse(str::from_utf8(s).unwrap()).unwrap()
));

named!(text<&str>, map!(take_till_s!(crlf),
    |s| str::from_utf8(s).unwrap()
));

named!(atom<&str>, map!(take_while1_s!(atom_char),
    |s| str::from_utf8(s).unwrap()
));

fn flag_extension(i: &[u8]) -> IResult<&[u8], &str> {
    if i.len() < 1 || i[0] != b'\\' {
        return IResult::Error(nom::ErrorKind::Custom(0));
    }
    let mut last = 0;
    for (idx, c) in i[1..].iter().enumerate() {
        last = idx;
        if !atom_char(*c) {
            break;
        }
    }
    IResult::Done(&i[last + 1..], str::from_utf8(&i[..last + 1]).unwrap())
}

named!(flag<&str>, alt!(flag_extension | atom));

named!(flag_list<Vec<&str>>, do_parse!(
    tag_s!("(") >>
    elements: opt!(do_parse!(
        flag0: flag >>
        flags: many0!(do_parse!(
            tag_s!(" ") >>
            flag: flag >>
            (flag)
        )) >> ({
            let mut res = vec![flag0];
            res.extend(flags);
            res
        })
    )) >>
    tag_s!(")") >> ({
       if elements.is_some() {
           elements.unwrap()
       } else {
           Vec::new()
       }
    })
));

named!(flag_perm<&str>, alt!(
    map!(tag_s!("\\*"), |s| str::from_utf8(s).unwrap()) |
    flag
));

named!(resp_text_code_permanent_flags<ResponseCode>, do_parse!(
    tag_s!("PERMANENTFLAGS (") >>
    elements: dbg_dmp!(opt!(do_parse!(
        flag0: flag_perm >>
        flags: many0!(do_parse!(
            tag_s!(" ") >>
            flag: flag_perm >>
            (flag)
        )) >> ({
            let mut res = vec![flag0];
            res.extend(flags);
            res
        })
    ))) >>
    tag_s!(")") >> ({
        ResponseCode::PermanentFlags(if elements.is_some() {
            elements.unwrap()
        } else {
            Vec::new()
        })
    })
));

named!(resp_text_code_highest_mod_seq<ResponseCode>, dbg_dmp!(do_parse!(
    tag_s!("HIGHESTMODSEQ ") >>
    num: number_64 >>
    (ResponseCode::HighestModSeq(num))
)));

named!(resp_text_code_read_only<ResponseCode>, do_parse!(
    tag_s!("READ-ONLY") >>
    (ResponseCode::ReadOnly)
));

named!(resp_text_code_read_write<ResponseCode>, do_parse!(
    tag_s!("READ-WRITE") >>
    (ResponseCode::ReadWrite)
));

named!(resp_text_code_try_create<ResponseCode>, do_parse!(
    tag_s!("TRYCREATE") >>
    (ResponseCode::TryCreate)
));

named!(resp_text_code_uid_validity<ResponseCode>, do_parse!(
    tag_s!("UIDVALIDITY ") >>
    num: number >>
    (ResponseCode::UidValidity(num))
));

named!(resp_text_code_uid_next<ResponseCode>, do_parse!(
    tag_s!("UIDNEXT ") >>
    num: number >>
    (ResponseCode::UidNext(num))
));

named!(resp_text_code<ResponseCode>, do_parse!(
    tag_s!("[") >>
    coded: alt!(
        resp_text_code_permanent_flags |
        resp_text_code_uid_validity |
        resp_text_code_uid_next |
        resp_text_code_read_only |
        resp_text_code_read_write |
        resp_text_code_try_create |
        resp_text_code_highest_mod_seq
    ) >>
    // Per the spec, the closing tag should be "] ".
    // See `resp_text` for more on why this is done differently.
    tag_s!("]") >>
    (coded)
));

named!(capability<&str>, do_parse!(
    tag_s!(" ") >>
    atom: take_till1_s!(atom_specials) >>
    (str::from_utf8(atom).unwrap())
));

named!(capability_data<Response>, do_parse!(
    tag_s!("CAPABILITY") >>
    capabilities: many1!(capability) >>
    (Response::Capabilities(capabilities))
));

named!(mailbox_data_flags<Response>, do_parse!(
    tag_s!("FLAGS ") >>
    flags: flag_list >>
    (Response::MailboxData(MailboxDatum::Flags(flags)))
));

named!(mailbox_data_exists<Response>, do_parse!(
    num: number >>
    tag_s!(" EXISTS") >>
    (Response::MailboxData(MailboxDatum::Exists(num)))
));

named!(mailbox_data_recent<Response>, do_parse!(
    num: number >>
    tag_s!(" RECENT") >>
    (Response::MailboxData(MailboxDatum::Recent(num)))
));

named!(mailbox_data<Response>, alt!(
    mailbox_data_flags |
    mailbox_data_exists |
    mailbox_data_recent
));

named!(nstring<Option<&str>>, map!(
    alt!(
        map!(tag_s!("NIL"), |s| str::from_utf8(s).unwrap()) |
        quoted
    ),
    |s| if s == "NIL" { None } else { Some(s) }
));

named!(address<Address>, do_parse!(
    tag_s!("(") >>
    name: nstring >>
    tag_s!(" ") >>
    adl: nstring >>
    tag_s!(" ") >>
    mailbox: nstring >>
    tag_s!(" ") >>
    host: nstring >>
    tag_s!(")") >>
    (Address { name, adl, mailbox, host })
));

named!(opt_addresses<Option<Vec<Address>>>, alt!(
    map!(tag_s!("NIL"), |s| None) |
    do_parse!(
        tag_s!("(") >>
        addrs: many1!(address) >>
        tag_s!(")") >>
        (Some(addrs))
    )
));

named!(msg_att_envelope<Attribute>, do_parse!(
    tag_s!("ENVELOPE (") >>
    date: nstring >>
    tag_s!(" ") >>
    subject: nstring >>
    tag_s!(" ") >>
    from: opt_addresses >>
    tag_s!(" ") >>
    sender: opt_addresses >>
    tag_s!(" ") >>
    reply_to: opt_addresses >>
    tag_s!(" ") >>
    to: opt_addresses >>
    tag_s!(" ") >>
    cc: opt_addresses >>
    tag_s!(" ") >>
    bcc: opt_addresses >>
    tag_s!(" ") >>
    in_reply_to: nstring >>
    tag_s!(" ") >>
    message_id: nstring >>
    tag_s!(")") >> ({
        Attribute::Envelope(Envelope {
            date, subject, from, sender, reply_to, to, cc, bcc, in_reply_to, message_id
        })
    })
));

named!(msg_att_internal_date<Attribute>, do_parse!(
    tag_s!("INTERNALDATE ") >>
    date: nstring >>
    (Attribute::InternalDate(date.unwrap()))
));

named!(msg_att_flags<Attribute>, do_parse!(
    tag_s!("FLAGS ") >>
    flags: flag_list >>
    (Attribute::Flags(flags))
));

named!(msg_att_rfc822_size<Attribute>, do_parse!(
    tag_s!("RFC822.SIZE ") >>
    num: number >>
    (Attribute::Rfc822Size(num))
));

named!(msg_att<Attribute>, alt!(
    msg_att_envelope |
    msg_att_internal_date |
    msg_att_flags |
    msg_att_rfc822_size
));

named!(msg_att_list<Vec<Attribute>>, do_parse!(
    tag_s!("(") >>
    elements: do_parse!(
        attr0: msg_att >>
        attrs: many0!(do_parse!(
            tag_s!(" ") >>
            attr: msg_att >>
            (attr)
        )) >> ({
            let mut res = vec![attr0];
            res.extend(attrs);
            res
        })
    ) >>
    tag_s!(")") >>
    (elements)
));

named!(message_data_fetch<Response>, do_parse!(
    num: number >>
    tag_s!(" FETCH ") >>
    attrs: msg_att_list >>
    (Response::Fetch(num, attrs))
));

named!(message_data_expunge<Response>, do_parse!(
    num: number >>
    tag_s!(" EXPUNGE") >>
    (Response::Expunge(num))
));

named!(tag<RequestId>, map!(take_while1_s!(tag_char),
    |s| RequestId(str::from_utf8(s).unwrap().to_string())
));

// This is not quite according to spec, which mandates the following:
//     ["[" resp-text-code "]" SP] text
// However, examples in RFC 4551 (Conditional STORE) counteract this by giving
// examples of `resp-text` that do not include the trailing space and text.
named!(resp_text<(Option<ResponseCode>, Option<&str>)>, do_parse!(
    code: opt!(resp_text_code) >>
    text: text >>
    ({
        let res = if text.len() < 1 {
            None
        } else if code.is_some() {
            Some(&text[1..])
        } else {
            Some(text)
        };
        (code, res)
    })
));

named!(response_tagged<Response>, do_parse!(
    tag: tag >>
    tag_s!(" ") >>
    status: status >>
    tag_s!(" ") >>
    text: resp_text >>
    (Response::Done(tag, status, text.0, text.1))
));

named!(resp_cond<Response>, do_parse!(
    status: status >>
    tag_s!(" ") >>
    text: resp_text >>
    (Response::Data(status, text.0, text.1))
));

named!(response_data<Response>, do_parse!(
    tag_s!("* ") >>
    contents: alt!(
        resp_cond |
        mailbox_data |
        message_data_expunge |
        message_data_fetch |
        capability_data
    ) >>
    (contents)
));

named!(response<Response>, alt!(
    response_data |
    response_tagged
));

pub fn parse(msg: &str) -> Response {
    match response(msg.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete: {:?}", msg),
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::File;
use std::iter::Peekable;
use std::str::Chars;

use super::sql::*;

//pub enum Keyword {
//    Select,
//    From,
//    Where
//}

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
    Identifier(String),
    Keyword(String),
    Operator(String),
    Number(String),
    Comma,
    Whitespace,
    Eq,
    Neq,
    Lt,
    Gt,
    LtEq,
    GtEq,
    Plus,
    Minus,
    Mult,
    Div,
    LParen,
    RParen,

    //Operator(String)
}

#[derive(Debug,Clone)]
pub enum ParserError {
    TokenizerError(String)
}

struct Tokenizer {
    query: String,
}

impl Tokenizer {

    pub fn tokenize(&mut self) -> Result<Vec<Token>, ParserError> {

        let mut peekable = self.query.chars().peekable();

        let mut tokens : Vec<Token> = vec![];

        while let Some(token) = self.next_token(&mut peekable)? {
            tokens.push(token);
        }

        Ok(tokens.into_iter().filter(|t| match t {
            &Token::Whitespace => false,
            _ => true
        }).collect())
    }

    fn next_token(&self, chars: &mut Peekable<Chars>) -> Result<Option<Token>, ParserError> {
        match chars.peek() {
            Some(&ch) => match ch {
                // whitespace
                ' ' | '\t' | '\n' => {
                    chars.next(); // consume
                    Ok(Some(Token::Whitespace))
                },
                // identifier or keyword
                'a' ... 'z' | 'A' ... 'Z' | '_' | '@' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    Ok(Some(Token::Identifier(s)))
                },
                // numbers
                '0' ... '9' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    Ok(Some(Token::Number(s)))
                },
                // operators
                '+' => { chars.next(); Ok(Some(Token::Plus)) },
                '-' => { chars.next(); Ok(Some(Token::Minus)) },
                '*' => { chars.next(); Ok(Some(Token::Mult)) },
                '/' => { chars.next(); Ok(Some(Token::Div)) },
                '=' => { chars.next(); Ok(Some(Token::Eq)) },
                '<' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::LtEq))
                            },
                            '>' => {
                                chars.next();
                                Ok(Some(Token::Neq))
                            },
                            _ => Ok(Some(Token::Lt))
                        },
                        None => Ok(Some(Token::Lt))
                    }
                },
                '>' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::GtEq))
                            },
                            _ => Ok(Some(Token::Gt))
                        },
                        None => Ok(Some(Token::Gt))
                    }
                },
                _ => Err(ParserError::TokenizerError(
                    String::from(format!("unhandled char '{}' in tokenizer", ch))))
            },
            None => Ok(None)
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn tokenize_select_1()  {
        let sql = String::from("SELECT 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(2, tokens.len());
        assert_eq!(Token::Identifier(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Number(String::from("1")), tokens[1]);
    }

    #[test]
    fn tokenize_simple_select()  {
        let sql = String::from("SELECT * FROM customer WHERE id = 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(8, tokens.len());
        assert_eq!(Token::Identifier(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Mult, tokens[1]);
        assert_eq!(Token::Identifier(String::from("FROM")), tokens[2]);
        assert_eq!(Token::Identifier(String::from("customer")), tokens[3]);
        assert_eq!(Token::Identifier(String::from("WHERE")), tokens[4]);
        assert_eq!(Token::Identifier(String::from("id")), tokens[5]);
        assert_eq!(Token::Eq, tokens[6]);
        assert_eq!(Token::Number(String::from("1")), tokens[7]);
    }
}

<commit_msg>keyword support<commit_after>use std::error::Error;
use std::fs::File;
use std::iter::Peekable;
use std::str::Chars;

use super::sql::*;

//pub enum Keyword {
//    Select,
//    From,
//    Where
//}

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
    Identifier(String),
    Keyword(String),
    Operator(String),
    Number(String),
    Comma,
    Whitespace,
    Eq,
    Neq,
    Lt,
    Gt,
    LtEq,
    GtEq,
    Plus,
    Minus,
    Mult,
    Div,
    LParen,
    RParen,

    //Operator(String)
}

#[derive(Debug,Clone)]
pub enum ParserError {
    TokenizerError(String)
}

struct Tokenizer {
    query: String,
}

impl Tokenizer {

    pub fn tokenize(&mut self) -> Result<Vec<Token>, ParserError> {

        let mut peekable = self.query.chars().peekable();

        let mut tokens : Vec<Token> = vec![];

        while let Some(token) = self.next_token(&mut peekable)? {
            tokens.push(token);
        }

        Ok(tokens.into_iter().filter(|t| match t {
            &Token::Whitespace => false,
            _ => true
        }).collect())
    }

    fn next_token(&self, chars: &mut Peekable<Chars>) -> Result<Option<Token>, ParserError> {
        match chars.peek() {
            Some(&ch) => match ch {
                // whitespace
                ' ' | '\t' | '\n' => {
                    chars.next(); // consume
                    Ok(Some(Token::Whitespace))
                },
                // identifier or keyword
                'a' ... 'z' | 'A' ... 'Z' | '_' | '@' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            'a' ... 'z' | 'A' ... 'Z' | '_' | '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    match s.to_uppercase().as_ref() {
                        "SELECT" | "FROM" | "WHERE" | "LIMIT" | "ORDER" | "GROUP" | "BY" |
                        "UNION" | "ALL"| "UPDATE" | "DELETE" | "IN" | "NOT" | "NULL" |
                        "SET" => Ok(Some(Token::Keyword(s))),
                        _ => Ok(Some(Token::Identifier(s))),
                    }
                },
                // numbers
                '0' ... '9' => {
                    let mut s = String::new();
                    while let Some(&ch) = chars.peek() {
                        match ch {
                            '0' ... '9' => {
                                chars.next(); // consume
                                s.push(ch);
                            },
                            _ => break
                        }
                    }
                    Ok(Some(Token::Number(s)))
                },
                // operators
                '+' => { chars.next(); Ok(Some(Token::Plus)) },
                '-' => { chars.next(); Ok(Some(Token::Minus)) },
                '*' => { chars.next(); Ok(Some(Token::Mult)) },
                '/' => { chars.next(); Ok(Some(Token::Div)) },
                '=' => { chars.next(); Ok(Some(Token::Eq)) },
                '<' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::LtEq))
                            },
                            '>' => {
                                chars.next();
                                Ok(Some(Token::Neq))
                            },
                            _ => Ok(Some(Token::Lt))
                        },
                        None => Ok(Some(Token::Lt))
                    }
                },
                '>' => {
                    chars.next(); // consume
                    match chars.peek() {
                        Some(&ch) => match ch {
                            '=' => {
                                chars.next();
                                Ok(Some(Token::GtEq))
                            },
                            _ => Ok(Some(Token::Gt))
                        },
                        None => Ok(Some(Token::Gt))
                    }
                },
                _ => Err(ParserError::TokenizerError(
                    String::from(format!("unhandled char '{}' in tokenizer", ch))))
            },
            None => Ok(None)
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn tokenize_select_1()  {
        let sql = String::from("SELECT 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(2, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Number(String::from("1")), tokens[1]);
    }

    #[test]
    fn tokenize_simple_select()  {
        let sql = String::from("SELECT * FROM customer WHERE id = 1");
        let mut tokenizer = Tokenizer { query: sql };
        let tokens = tokenizer.tokenize().unwrap();
        println!("tokens = {:?}", tokens);
        assert_eq!(8, tokens.len());
        assert_eq!(Token::Keyword(String::from("SELECT")), tokens[0]);
        assert_eq!(Token::Mult, tokens[1]);
        assert_eq!(Token::Keyword(String::from("FROM")), tokens[2]);
        assert_eq!(Token::Identifier(String::from("customer")), tokens[3]);
        assert_eq!(Token::Keyword(String::from("WHERE")), tokens[4]);
        assert_eq!(Token::Identifier(String::from("id")), tokens[5]);
        assert_eq!(Token::Eq, tokens[6]);
        assert_eq!(Token::Number(String::from("1")), tokens[7]);
    }
}

<|endoftext|>


<commit_before>use std::ops::Range;
use time;

use collision::Aabb3;
use noise;
use noise::{Brownian3, Seed};

use world::Block;

pub fn generate_blocks(boundaries: &Aabb3<i32>) -> Vec<Block> {
  let start_s = time::precise_time_s();

  let seed = Seed::new(1);
  let noise = Brownian3::new(noise::perlin3, 4).wavelength(16.0);

  let x_range = Range {
    start: boundaries.min.x,
    end: boundaries.max.x + 1,
  };
  let y_range = Range {
    start: boundaries.min.y,
    end: boundaries.max.y + 1,
  };
  let z_range = Range {
    start: boundaries.min.z,
    end: boundaries.max.z + 1,
  };
  let y_scale = 1.0 / (y_range.end as f64 - 1.0 - y_range.start as f64);
  let y_min = y_range.start as f64;

  let mut blocks = Vec::new();
  for y in y_range {
    // Normalize into [0, 1].
    let normalized_y = (y as f64 - y_min) * y_scale;
    for x in x_range.clone() {
      for z in z_range.clone() {
        let p = [x as f64, y as f64, z as f64];
        let val = noise.apply(&seed, &p);

        // Probablility to have a block added linearly increases from 0.0 at y_max to 1.0 at y_min.
        if 0.5 * (val + 1.0) >= normalized_y {
          blocks.push(Block::new(x, y, z));
        }
      }
    }
  }

  let spent_ms = (time::precise_time_s() - start_s) * 1000.0;
  log!("*** Generated a chunk of perlin: {:.3}ms, {} blocks", spent_ms, blocks.len());

  blocks
}
<commit_msg>Perlin now works in f32, not in f64.<commit_after>use std::ops::Range;
use time;

use collision::Aabb3;
use noise;
use noise::{Brownian3, Seed};

use world::Block;

pub fn generate_blocks(boundaries: &Aabb3<i32>) -> Vec<Block> {
  let start_s = time::precise_time_s();

  let seed = Seed::new(1);
  let noise = Brownian3::new(noise::perlin3, 4).wavelength(16.0);

  let x_range = Range {
    start: boundaries.min.x,
    end: boundaries.max.x + 1,
  };
  let y_range = Range {
    start: boundaries.min.y,
    end: boundaries.max.y + 1,
  };
  let z_range = Range {
    start: boundaries.min.z,
    end: boundaries.max.z + 1,
  };
  let y_scale = 1.0 / (y_range.end as f32 - 1.0 - y_range.start as f32);
  let y_min = y_range.start as f32;

  let mut blocks = Vec::new();
  for y in y_range {
    // Normalize into [0, 1].
    let normalized_y = (y as f32 - y_min) * y_scale;
    for x in x_range.clone() {
      for z in z_range.clone() {
        let p = [x as f32, y as f32, z as f32];
        let val = noise.apply(&seed, &p);

        // Probablility to have a block added linearly increases from 0.0 at y_max to 1.0 at y_min.
        if 0.5 * (val + 1.0) >= normalized_y {
          blocks.push(Block::new(x, y, z));
        }
      }
    }
  }

  let spent_ms = (time::precise_time_s() - start_s) * 1000.0;
  log!("*** Generated a chunk of perlin: {:.3}ms, {} blocks", spent_ms, blocks.len());

  blocks
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate jmap;
extern crate time;

#[macro_use]
extern crate log;

mod logger;
mod db;
mod util;
mod record;

use std::default::Default;
use std::io::{Read, Write, ErrorKind};

use std::fs::File;

use hyper::server::{Request, Response};
use hyper::method::Method::{Post, Get};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;
use hyper::header;

use rustc_serialize::json::{Json,ToJson};

use jmap::parse::FromJson;
use jmap::method::{RequestBatch, ResponseBatch, ResponseMethod};
use jmap::method::RequestMethod::*;
use jmap::method::ResponseMethod::*;

use util::RequestContext;
use record::RecordHandler;
use db::Db;

struct StatusBody {
    code: StatusCode,
    body: Option<Vec<u8>>
}
impl StatusBody {
    fn new(code: StatusCode, body: Option<Vec<u8>>) -> StatusBody {
        StatusBody { code: code, body: body }
    }
}

macro_rules! make_crud_method_dispatcher {
    ($method: expr, $rmethods: expr, $r: expr,
     $($ty: ty { $get: ident => $rget: ident, $set: ident => $rset: ident, $getup: ident => $rgetup: ident }),*) => {
        $rmethods = match $method {
            $(
                $get(args, id)
                    => vec!($r.get_records(&args).map(|a| $rget(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $set(args, id)
                    => vec!($r.set_records(&args).map(|a| $rset(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $getup(args, id) => $r.get_record_updates(&args).map(|a| {
                    match a {
                        (a, Some(b)) => vec!($rgetup(a, id.clone()), $rget(b, id.clone())),
                        (a, _)       => vec!($rgetup(a, id.clone())),
                    }
                }).unwrap_or_else(|e| vec!(ResponseError(e, id.clone()))),
            )*
            RequestError(args, id) => vec!(ResponseError(args, id)),
        };
    }
}

fn jmap_handler(mut req: Request) -> StatusBody {

    match Json::from_reader(&mut req) {
        Ok(j) => match RequestBatch::from_json(&j) {
            Ok(b) => {
                let mut rbatch: ResponseBatch = ResponseBatch::default();

                let r = RequestContext {
                    userid: 1, // XXX get userid from auth
                    db: Db::open().unwrap(),
                };

                for method in b.0.into_iter() {
                    let rmethods: Vec<ResponseMethod>;
                    make_crud_method_dispatcher!(method, rmethods, r,
                        Calendar {
                            GetCalendars       => Calendars,
                            SetCalendars       => CalendarsSet,
                            GetCalendarUpdates => CalendarUpdates
                        },
                        CalendarEvent {
                            GetCalendarEvents       => CalendarEvents,
                            SetCalendarEvents       => CalendarEventsSet,
                            GetCalendarEventUpdates => CalendarEventUpdates
                        },
                        Contact {
                            GetContacts       => Contacts,
                            SetContacts       => ContactsSet,
                            GetContactUpdates => ContactUpdates
                        },
                        ContactGroup {
                            GetContactGroups       => ContactGroups,
                            SetContactGroups       => ContactGroupsSet,
                            GetContactGroupUpdates => ContactGroupUpdates
                        },
                        Mailbox {
                            GetMailboxes      => Mailboxes,
                            SetMailboxes      => MailboxesSet,
                            GetMailboxUpdates => MailboxUpdates
                        }
                    );

                    rbatch.0.extend(rmethods.into_iter());
                }

                StatusBody::new(StatusCode::Ok, Some(rbatch.to_json().to_string().into_bytes()))
            },
            Err(e) =>
                StatusBody::new(StatusCode::BadRequest, Some(e.to_string().into_bytes())),
        },
        Err(e) => StatusBody::new(StatusCode::BadRequest, Some(e.to_string().into_bytes())),
    }
}

fn file_handler(path: &String) -> StatusBody {
    match File::open(String::from("client") + if path == "/" { "/index.html" } else { path }) {
        Err(ref e) => match e.kind() {
            ErrorKind::NotFound => StatusBody::new(StatusCode::NotFound, None),
            // XXX others
            _ => StatusBody::new(StatusCode::InternalServerError, Some(format!("{}", e).into_bytes())),
        },
        Ok(ref mut f) => {
            let mut s = String::new();
            match f.read_to_string(&mut s) {
                Err(ref e) =>
                    StatusBody::new(StatusCode::InternalServerError, Some(format!("{}", e).into_bytes())),
                _ =>
                    StatusBody::new(StatusCode::Ok, Some(s.into_bytes())),
            }
        },
    }
}

fn finish_response(mut res: Response, out: StatusBody) {
    *res.status_mut() = out.code;

    match res.start()
        .and_then(|mut res|
                  match out.body {
                      Some(ref b) => {
                          try!(res.write_all(b));
                          Ok(res)
                      }
                      None => {
                          Ok(res)
                      }
                  })
        .and_then(|res| res.end()) {
            Err(e) => error!("response error: {}", e),
            _      => (),
        };
}

fn http_handler(req: Request, mut res: Response) {
    res.headers_mut().set(header::Server("salada/0.0.5".to_string()));

    let method = req.method.clone();
    let uri = req.uri.clone();

    match (method, uri) {
        (Post, AbsolutePath(ref path)) if path == "/jmap" =>
            finish_response(res, jmap_handler(req)),

        (Get, AbsolutePath(ref path)) =>
            finish_response(res, file_handler(path)),

        _ => finish_response(res, StatusBody::new(StatusCode::MethodNotAllowed, None)),
    };
}

fn main() {
    logger::init().unwrap();

    info!("Listening on http://127.0.0.1:3000/jmap");
    hyper::Server::http("127.0.0.1:3000").unwrap().handle(http_handler).unwrap();
}
<commit_msg>Handle HEAD request for static files<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate jmap;
extern crate time;

#[macro_use]
extern crate log;

mod logger;
mod db;
mod util;
mod record;

use std::default::Default;
use std::io::{Read, Write, ErrorKind};

use std::fs::File;

use hyper::server::{Request, Response};
use hyper::method::Method::{Post, Get, Head};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;
use hyper::header;

use rustc_serialize::json::{Json,ToJson};

use jmap::parse::FromJson;
use jmap::method::{RequestBatch, ResponseBatch, ResponseMethod};
use jmap::method::RequestMethod::*;
use jmap::method::ResponseMethod::*;

use util::RequestContext;
use record::RecordHandler;
use db::Db;

struct StatusBody {
    code: StatusCode,
    body: Option<Vec<u8>>
}
impl StatusBody {
    fn new(code: StatusCode, body: Option<Vec<u8>>) -> StatusBody {
        StatusBody { code: code, body: body }
    }
}

macro_rules! make_crud_method_dispatcher {
    ($method: expr, $rmethods: expr, $r: expr,
     $($ty: ty { $get: ident => $rget: ident, $set: ident => $rset: ident, $getup: ident => $rgetup: ident }),*) => {
        $rmethods = match $method {
            $(
                $get(args, id)
                    => vec!($r.get_records(&args).map(|a| $rget(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $set(args, id)
                    => vec!($r.set_records(&args).map(|a| $rset(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $getup(args, id) => $r.get_record_updates(&args).map(|a| {
                    match a {
                        (a, Some(b)) => vec!($rgetup(a, id.clone()), $rget(b, id.clone())),
                        (a, _)       => vec!($rgetup(a, id.clone())),
                    }
                }).unwrap_or_else(|e| vec!(ResponseError(e, id.clone()))),
            )*
            RequestError(args, id) => vec!(ResponseError(args, id)),
        };
    }
}

fn jmap_handler(mut req: Request) -> StatusBody {

    match Json::from_reader(&mut req) {
        Ok(j) => match RequestBatch::from_json(&j) {
            Ok(b) => {
                let mut rbatch: ResponseBatch = ResponseBatch::default();

                let r = RequestContext {
                    userid: 1, // XXX get userid from auth
                    db: Db::open().unwrap(),
                };

                for method in b.0.into_iter() {
                    let rmethods: Vec<ResponseMethod>;
                    make_crud_method_dispatcher!(method, rmethods, r,
                        Calendar {
                            GetCalendars       => Calendars,
                            SetCalendars       => CalendarsSet,
                            GetCalendarUpdates => CalendarUpdates
                        },
                        CalendarEvent {
                            GetCalendarEvents       => CalendarEvents,
                            SetCalendarEvents       => CalendarEventsSet,
                            GetCalendarEventUpdates => CalendarEventUpdates
                        },
                        Contact {
                            GetContacts       => Contacts,
                            SetContacts       => ContactsSet,
                            GetContactUpdates => ContactUpdates
                        },
                        ContactGroup {
                            GetContactGroups       => ContactGroups,
                            SetContactGroups       => ContactGroupsSet,
                            GetContactGroupUpdates => ContactGroupUpdates
                        },
                        Mailbox {
                            GetMailboxes      => Mailboxes,
                            SetMailboxes      => MailboxesSet,
                            GetMailboxUpdates => MailboxUpdates
                        }
                    );

                    rbatch.0.extend(rmethods.into_iter());
                }

                StatusBody::new(StatusCode::Ok, Some(rbatch.to_json().to_string().into_bytes()))
            },
            Err(e) =>
                StatusBody::new(StatusCode::BadRequest, Some(e.to_string().into_bytes())),
        },
        Err(e) => StatusBody::new(StatusCode::BadRequest, Some(e.to_string().into_bytes())),
    }
}

fn file_handler(path: &String, include_body: bool) -> StatusBody {
    match File::open(String::from("client") + if path == "/" { "/index.html" } else { path }) {
        Err(ref e) => match e.kind() {
            ErrorKind::NotFound => StatusBody::new(StatusCode::NotFound, None),
            // XXX others
            _ => StatusBody::new(StatusCode::InternalServerError, Some(format!("{}", e).into_bytes())),
        },
        Ok(ref mut f) => {
            match include_body {
                false => StatusBody::new(StatusCode::Ok, None),
                true  => {
                    let mut s = String::new();
                    match f.read_to_string(&mut s) {
                        Err(ref e) =>
                            StatusBody::new(StatusCode::InternalServerError, Some(format!("{}", e).into_bytes())),
                        _ =>
                            StatusBody::new(StatusCode::Ok, Some(s.into_bytes())),
                    }
                },
            }
        },
    }
}

fn finish_response(mut res: Response, out: StatusBody) {
    *res.status_mut() = out.code;

    match res.start()
        .and_then(|mut res|
                  match out.body {
                      Some(ref b) => {
                          try!(res.write_all(b));
                          Ok(res)
                      }
                      None => {
                          Ok(res)
                      }
                  })
        .and_then(|res| res.end()) {
            Err(e) => error!("response error: {}", e),
            _      => (),
        };
}

fn http_handler(req: Request, mut res: Response) {
    res.headers_mut().set(header::Server("salada/0.0.5".to_string()));

    let method = req.method.clone();
    let uri = req.uri.clone();

    match (method, uri) {
        (Post, AbsolutePath(ref path)) if path == "/jmap" =>
            finish_response(res, jmap_handler(req)),

        (Get, AbsolutePath(ref path)) =>
            finish_response(res, file_handler(path, true)),

        (Head, AbsolutePath(ref path)) =>
            finish_response(res, file_handler(path, false)),

        _ => finish_response(res, StatusBody::new(StatusCode::MethodNotAllowed, None)),
    };
}

fn main() {
    logger::init().unwrap();

    info!("Listening on http://127.0.0.1:3000/jmap");
    hyper::Server::http("127.0.0.1:3000").unwrap().handle(http_handler).unwrap();
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate string_telephone;
extern crate collections;

use collections::str::{Slice, Owned};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use piston::{EventIterator, EventSettings, WindowSettings, NoWindow};
use string_telephone::{Server, ConnectionConfig, UserPacket};
use std::fmt;

struct Player {
    controller: SocketAddr,
    x: i32,
    y: i32,

    keyUp: bool,
    keyDown: bool,
    keyLeft: bool,
    keyRight: bool
}

impl Player {
    pub fn new (controller: SocketAddr, x: i32, y: i32) -> Player {
        Player {
            controller: controller,
            x: x,
            y: y,
            keyUp: false,
            keyDown: false,
            keyLeft: false,
            keyRight: false
        }
    }

    pub fn move(&mut self) {
        if self.keyUp && self.y > 0 {
            self.y -= 1;
        } else if self.keyDown && self.y < 600 {
            self.y += 1;
        }

        if self.keyLeft && self.x > 0 {
            self.x -= 1;
        } else if self.keyRight && self.x < 800{
            self.x += 1;
        }
    }
}

impl fmt::Show for Player {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {} {}", self.controller, self.x, self.y)
    }
}

fn deserializer(message: &Vec<u8>) -> String {
    match String::from_utf8_lossy(message.as_slice()) {
        Slice(slice) => slice.to_string(),
        Owned(item) => item
    }
}

fn serializer(packet: &String) -> Vec<u8> {
    packet.clone().into_bytes()
}

fn main() {
    let mut window = NoWindow::new(WindowSettings {
        title: "SuperMegaTag".to_string(),
        size: [0u32, 0u32],
        samples: 0,
        fullscreen: false,
        exit_on_esc: true,
    });

    let game_iter_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    let settings = ConnectionConfig {
        protocol_id: 88869,
        timeout_period: 10,
        packet_deserializer: deserializer,
        packet_serializer: serializer
    };

    let mut server = match Server::new(SocketAddr {ip: Ipv4Addr(0, 0, 0, 0), port: 8869}, settings) {
        Ok(server) => {
            println!("Listening on {}", server.addr);
            server
        },
        Err(e) => fail!("Failed to start listening - {}", e)
    };

    let mut players:Vec<Player> = vec![
        Player::new(SocketAddr {ip: Ipv4Addr(0, 0, 0, 0), port: 8869}, 400, 300)
    ];

    for e in EventIterator::new(&mut window, &game_iter_settings) {
        match e {
            piston::Update(update_args) => {
                loop {
                    match server.poll() {
                        Some((UserPacket(packet), _)) => {
                            //Do something
                        },
                        Some(_) => (),
                        None => break
                    }
                };

                //Update the game world
                for player in players.iter_mut() {
                    player.move()
                }
                println!("{}", players);
                let culled = server.cull();
                if culled.len() > 0 {
                    println!("{}", culled);
                }
            },
            _ => ()
        }
    }
}
<commit_msg>Starting to match on incoming commands<commit_after>extern crate piston;
extern crate string_telephone;
extern crate collections;

use collections::str::{Slice, Owned};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use piston::{EventIterator, EventSettings, WindowSettings, NoWindow};
use string_telephone::{Server, ConnectionConfig, UserPacket, Command, PacketDisconnect, PacketConnect};
use std::fmt;

struct Player {
    controller: SocketAddr,
    x: i32,
    y: i32,

    keyUp: bool,
    keyDown: bool,
    keyLeft: bool,
    keyRight: bool
}

impl Player {
    pub fn new (controller: SocketAddr, x: i32, y: i32) -> Player {
        Player {
            controller: controller,
            x: x,
            y: y,
            keyUp: false,
            keyDown: false,
            keyLeft: false,
            keyRight: false
        }
    }

    pub fn move(&mut self) {
        if self.keyUp && self.y > 0 {
            self.y -= 1;
        } else if self.keyDown && self.y < 600 {
            self.y += 1;
        }

        if self.keyLeft && self.x > 0 {
            self.x -= 1;
        } else if self.keyRight && self.x < 800{
            self.x += 1;
        }
    }
}

impl fmt::Show for Player {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {} {}", self.controller, self.x, self.y)
    }
}

fn deserializer(message: &Vec<u8>) -> String {
    match String::from_utf8_lossy(message.as_slice()) {
        Slice(slice) => slice.to_string(),
        Owned(item) => item
    }
}

fn serializer(packet: &String) -> Vec<u8> {
    packet.clone().into_bytes()
}

fn main() {
    let mut window = NoWindow::new(WindowSettings {
        title: "SuperMegaTag".to_string(),
        size: [0u32, 0u32],
        samples: 0,
        fullscreen: false,
        exit_on_esc: true,
    });

    let game_iter_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    let settings = ConnectionConfig {
        protocol_id: 88869,
        timeout_period: 10,
        packet_deserializer: deserializer,
        packet_serializer: serializer
    };

    let mut server = match Server::new(SocketAddr {ip: Ipv4Addr(0, 0, 0, 0), port: 8869}, settings) {
        Ok(server) => {
            println!("Listening on {}", server.addr);
            server
        },
        Err(e) => fail!("Failed to start listening - {}", e)
    };

    let mut players:Vec<Player> = vec![
        Player::new(SocketAddr {ip: Ipv4Addr(0, 0, 0, 0), port: 8869}, 400, 300)
    ];

    for e in EventIterator::new(&mut window, &game_iter_settings) {
        match e {
            piston::Update(update_args) => {
                loop {
                    match server.poll() {
                        Some((Command(PacketConnect), addr_from)) => {
                            //New player!
                        },
                        Some((Command(PacketDisconnect), addr_from)) => {
                            //Ohnoes
                        },
                        Some((UserPacket(packet), _)) => {
                            //Do something
                        },
                        Some(_) => (),
                        None => break
                    }
                };

                //Update the game world
                for player in players.iter_mut() {
                    player.move()
                }
                println!("{}", players);
                let culled = server.cull();
                if culled.len() > 0 {
                    println!("{}", culled);
                }
            },
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>use libc;

use std::ptr::null_mut;

const STACK_SPACE : u64 = 1024 * 1024;

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ( $($offset:expr, $kind:ty),* ) => {{
        $(
            let dest_ptr: *mut $kind;

            // We can't use constant segment offsets here due to some odd
            // asm! behavior, so just use indirect (it's slower, oh well).
            asm!("mov %fs:($1), $0"
                 : "=r"(dest_ptr)
                 : "r" ($offset)
                 :: "volatile");

            dest_ptr
          )*
        }
    };
}

macro_rules! set_thread_mem {
    ( $($offset:expr, $expression:expr),* ) => {{
        $(
            asm!("movl $1, %fs:($0)" :
                 : "r"($offset), "i"($expression)
                 :: "volatile");
          )*
        }
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub struct ThreadBlarg {
    stack: *mut libc::c_void,
}

impl Drop for ThreadBlarg {
    fn drop(&mut self) {
        unsafe { libc::free(self.stack); }
    }
}

impl ThreadBlarg {
    pub fn new() -> ThreadBlarg {
        let stack_space = unsafe {
            let m = libc::malloc(STACK_SPACE);

            if m.is_null() { panic!("couldn't alloc stack space"); }

            m
        };

        ThreadBlarg { stack: stack_space }
    }
}
<commit_msg>mmap stack segment<commit_after>use libc;

use std::ptr::null_mut;

/// 16k is enough for anybody.
const STACK_SIZE: u64 = 16384;

/// Return a pointer to the TLS value at the given offset.
macro_rules! get_thread_mem {
    ( $($offset:expr, $kind:ty),* ) => {{
        $(
            let dest_ptr: *mut $kind;

            // We can't use constant segment offsets here due to some odd
            // asm! behavior, so just use indirect (it's slower, oh well).
            asm!("mov %fs:($1), $0"
                 : "=r"(dest_ptr)
                 : "r" ($offset)
                 :: "volatile");

            dest_ptr
          )*
        }
    };
}

macro_rules! set_thread_mem {
    ( $($offset:expr, $expression:expr),* ) => {{
        $(
            asm!("movl $1, %fs:($0)" :
                 : "r"($offset), "i"($expression)
                 :: "volatile");
          )*
        }
    };
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct ControlBlockHead {
    tcb: *mut libc::c_void,
    dtv: *mut libc::c_void,
    thread_self: *mut Thread,

    /// We don't actually care about the rest.
    padding: [*mut libc::c_void; 21],
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct Thread {
    header: ControlBlockHead,

    /// This thread's id
    pub tid: libc::pid_t,

    /// This thread's parent pid
    pub pid: libc::pid_t,

    pub magic: usize
}

unsafe fn get_thread_tcb() {
}

pub unsafe fn get_current_thread() -> () {
    let thd_ptr: *mut Thread = get_thread_mem!(0, Thread);
    if thd_ptr.is_null() { panic!("TLS thread return NULL"); }

    let thd = &*thd_ptr;

    println!("magic = {}", thd.magic);
}

pub unsafe fn allocate_stack() -> *mut libc::c_void {
    let prot = libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE;
    let flags = libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_STACK;

    let stack = libc::mmap(null_mut(), STACK_SIZE, prot, flags, -1, 0);

    if stack == libc::MAP_FAILED || stack.is_null() {
        panic!("couldn't mmap space for stack");
    }

    stack
}
<|endoftext|>