<commit_before>use autograd::function::*;
use tensor::Tensor;
use ::*;

pub struct VariableImpl<T> {
    data: Option<Tensor<T>>,
    grad_fn: OptRcMut<Function<T>>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

pub struct Variable<T> {
    value: RcMut<VariableImpl<T>>,
}

impl<T> Clone for Variable<T> {
    fn clone(&self) -> Self {
        Variable { value: self.value.clone() }
    }
}

pub struct SavedVariable<T> {
    data: Box<Tensor<T>>,
    grad_fn: OptRcMut<Function<T>>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

impl<T> Variable<T> {
    pub fn apply(&mut self, callback: fn(&mut Tensor<T>)) {
        let mut v = self.value.borrow_mut();
        if let Some(ref mut t) = v.data {
            callback(&mut *t);
        }
    }
}

impl<T> Default for Variable<T> {
    fn default() -> Self {
        let v = VariableImpl {
            data: None,
            grad_fn: None,
            grad: None,
        };
        Variable { value: RcMutNew(v) }
    }
}
<commit_msg>add VarList<T> type alias<commit_after>use autograd::function::*;
use tensor::Tensor;
use ::*;

pub type VarList<T> = Vec<Variable<T>>;

pub struct VariableImpl<T> {
    data: Option<Tensor<T>>,
    grad_fn: OptRcMut<Function<T>>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

pub struct Variable<T> {
    value: RcMut<VariableImpl<T>>,
}

impl<T> Clone for Variable<T> {
    fn clone(&self) -> Self {
        Variable { value: self.value.clone() }
    }
}

pub struct SavedVariable<T> {
    data: Box<Tensor<T>>,
    grad_fn: OptRcMut<Function<T>>,
    grad: OptRcMut<Variable<T>>,
	// version_counter etc ...
}

impl<T> Variable<T> {
    pub fn apply(&mut self, callback: fn(&mut Tensor<T>)) {
        let mut v = self.value.borrow_mut();
        if let Some(ref mut t) = v.data {
            callback(&mut *t);
        }
    }
}

impl<T> Default for Variable<T> {
    fn default() -> Self {
        let v = VariableImpl {
            data: None,
            grad_fn: None,
            grad: None,
        };
        Variable { value: RcMutNew(v) }
    }
}
<|endoftext|>


<commit_before>use bitstream::byteread::*;

pub trait BitReadEndian {
    fn peek_val(&mut self, n:usize) -> u64;
    fn merge_val(msp:u64, lsp:u64, msb:usize, lsb:usize) -> u64;
    fn skip_rem(&mut self, n:usize) -> ();
    fn fill32(&self) -> u64;
    fn fill64(&self) -> u64;
}

pub trait BitReadInternal : BitReadEndian {
    #[inline]
    fn left(&self) -> usize;
    fn refill32(&mut self) -> ();
    fn refill64(&mut self) -> ();

    fn get_val(&mut self, n:usize) -> u64 {
        let ret = self.peek_val(n);

        self.skip_rem(n);

        return ret;
    }

}

pub trait BitRead<'a>: BitReadInternal+Copy {
    fn new(&'a[u8]) -> Self;
    fn consumed(&self) -> usize;
    fn available(&self) -> usize;
    fn can_refill(&self) -> bool;

    fn skip_bits(&mut self, size : usize) -> ();

    #[inline]
    fn get_bit(&mut self) -> bool {
        if self.left() <= 0 {
            self.refill64();
        }

        self.get_val(1) != 0
    }

    #[inline]
    fn get_bits_64(&mut self, mut n:usize) -> u64 {
        let mut left = 0;
        let mut ret = 0;

        if n == 0 {
            return 0;
        }

        if self.left() < n {
            n   -= self.left();
            left = self.left();
            ret  = self.get_val(left);
            self.refill64();
        }

        Self::merge_val(self.get_val(n), ret, left, n)
    }

    #[inline]
    fn get_bits_32(&mut self, n:usize) -> u32 {
        if n == 0 {
            return 0;
        }

        if self.left() <= n {
            self.refill32();
        }

        return self.get_val(n) as u32;
    }

    #[inline]
    fn peek_bits_32(&mut self, n:usize) -> u32 {
        let mut tmp = *self;

        tmp.get_bits_32(n)
    }

    #[inline]
    fn peek_bits_64(&self, n:usize) -> u64 {
        let mut tmp = *self;

        tmp.get_bits_64(n)
    }

    #[inline]
    fn align_bits(&mut self) -> () {
        let left = self.left() & 63;

        self.skip_bits(left);
    }
}

macro_rules! endian_reader {
    {$name: ident} => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<'a> {
            buffer : &'a[u8], /// read buffer, 8-bytes padded
            index : usize,
            cache : u64,
            left : usize,
        }
        impl <'a> BitReadInternal for $name<'a> {
            #[inline]
            fn left(&self) -> usize {
                self.left
            }
            #[inline]
            fn refill32(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }
                let val = self.fill32();

                self.cache  = Self::merge_val(val, self.cache,
                                              self.left, 32 - self.left);
                self.index += 4;
                self.left  += 32;
            }
            #[inline]
            fn refill64(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }

                self.cache  = self.fill64();
                self.index += 8;
                self.left   = 64;
            }
        }

        impl <'a> BitRead<'a> for $name<'a> {
            fn new(buffer: &'a[u8]) -> $name<'a> {
                let mut reader = $name {
                    buffer: buffer,
                    index: 0,
                    cache: 0,
                    left: 0
                };

                reader.refill64();
                return reader;
            }
            #[inline]
            fn consumed(&self) -> usize {
                self.index * 8 - self.left
            }

            #[inline]
            fn available(&self) -> usize {
                (self.buffer.len() - self.index) * 8 + self.left
            }

            #[inline]
            fn can_refill(&self) -> bool {
                self.index < self.buffer.len() - 8
            }

            #[inline]
            fn skip_bits(&mut self, mut n:usize) -> () {
                if n == 0 {
                    return;
                }
                if self.left <= n {
                    n -= self.left;
                    self.skip_rem(n);
                    if n > 64 {
                        let skip = n / 8;

                        n -= skip * 8;
                        self.index += skip;
                    }
                    self.refill64();
                }

                self.skip_rem(n);
            }

        }
    }
}

endian_reader!{ BitReadLE }

impl <'a> BitReadEndian for BitReadLE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        let v = self.cache & ((1u64 << n) - 1);

        return v;
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache >> n;
        self.left -= n;
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, msb:usize, _:usize) -> u64 {
        msp << msb | lsp
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32l(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64l(&self.buffer[self.index..])
    }
}

endian_reader!{ BitReadBE }

impl <'a> BitReadEndian for BitReadBE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        self.cache >> (64 - n)
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache << n;
        self.left -= n;
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, _:usize, lsb:usize) -> u64 {
        msp | lsp << lsb
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32b(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64b(&self.buffer[self.index..])
    }
}

#[cfg(test)]
mod test {
    pub const CHECKBOARD0101: [u8; 128] = [0b01010101; 128];
    pub const CHECKBOARD0011: [u8; 128] = [0b00110011; 128];

    mod le {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bit());
            assert!(!reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let mut reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 3);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }
    }
    mod be {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(!reader.get_bit());
            assert!(reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let b = &CHECKBOARD0101;
            let reader = BitReadBE::new(b);

            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }
    }
}
<commit_msg>bitread: Fix align_bits<commit_after>use bitstream::byteread::*;

pub trait BitReadEndian {
    fn peek_val(&mut self, n:usize) -> u64;
    fn merge_val(msp:u64, lsp:u64, msb:usize, lsb:usize) -> u64;
    fn skip_rem(&mut self, n:usize) -> ();
    fn fill32(&self) -> u64;
    fn fill64(&self) -> u64;
}

pub trait BitReadInternal : BitReadEndian {
    #[inline]
    fn left(&self) -> usize;
    fn refill32(&mut self) -> ();
    fn refill64(&mut self) -> ();

    fn get_val(&mut self, n:usize) -> u64 {
        let ret = self.peek_val(n);

        self.skip_rem(n);

        return ret;
    }

}

pub trait BitRead<'a>: BitReadInternal+Copy {
    fn new(&'a[u8]) -> Self;
    fn consumed(&self) -> usize;
    fn available(&self) -> usize;
    fn can_refill(&self) -> bool;

    fn skip_bits(&mut self, size : usize) -> ();

    #[inline]
    fn get_bit(&mut self) -> bool {
        if self.left() <= 0 {
            self.refill64();
        }

        self.get_val(1) != 0
    }

    #[inline]
    fn get_bits_64(&mut self, mut n:usize) -> u64 {
        let mut left = 0;
        let mut ret = 0;

        if n == 0 {
            return 0;
        }

        if self.left() < n {
            n   -= self.left();
            left = self.left();
            ret  = self.get_val(left);
            self.refill64();
        }

        Self::merge_val(self.get_val(n), ret, left, n)
    }

    #[inline]
    fn get_bits_32(&mut self, n:usize) -> u32 {
        if n == 0 {
            return 0;
        }

        if self.left() <= n {
            self.refill32();
        }

        return self.get_val(n) as u32;
    }

    #[inline]
    fn peek_bits_32(&mut self, n:usize) -> u32 {
        let mut tmp = *self;

        tmp.get_bits_32(n)
    }

    #[inline]
    fn peek_bits_64(&self, n:usize) -> u64 {
        let mut tmp = *self;

        tmp.get_bits_64(n)
    }

    #[inline]
    fn align_bits(&mut self) -> () {
        let left = self.left() & 7;

        self.skip_bits(left);
    }
}

macro_rules! endian_reader {
    {$name: ident} => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<'a> {
            buffer : &'a[u8], /// read buffer, 8-bytes padded
            index : usize,
            cache : u64,
            left : usize,
        }
        impl <'a> BitReadInternal for $name<'a> {
            #[inline]
            fn left(&self) -> usize {
                self.left
            }
            #[inline]
            fn refill32(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }
                let val = self.fill32();

                self.cache  = Self::merge_val(val, self.cache,
                                              self.left, 32 - self.left);
                self.index += 4;
                self.left  += 32;
            }
            #[inline]
            fn refill64(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }

                self.cache  = self.fill64();
                self.index += 8;
                self.left   = 64;
            }
        }

        impl <'a> BitRead<'a> for $name<'a> {
            fn new(buffer: &'a[u8]) -> $name<'a> {
                let mut reader = $name {
                    buffer: buffer,
                    index: 0,
                    cache: 0,
                    left: 0
                };

                reader.refill64();
                return reader;
            }
            #[inline]
            fn consumed(&self) -> usize {
                self.index * 8 - self.left
            }

            #[inline]
            fn available(&self) -> usize {
                (self.buffer.len() - self.index) * 8 + self.left
            }

            #[inline]
            fn can_refill(&self) -> bool {
                self.index < self.buffer.len() - 8
            }

            #[inline]
            fn skip_bits(&mut self, mut n:usize) -> () {
                if n == 0 {
                    return;
                }
                if self.left <= n {
                    n -= self.left;
                    self.skip_rem(n);
                    if n > 64 {
                        let skip = n / 8;

                        n -= skip * 8;
                        self.index += skip;
                    }
                    self.refill64();
                }

                self.skip_rem(n);
            }

        }
    }
}

endian_reader!{ BitReadLE }

impl <'a> BitReadEndian for BitReadLE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        let v = self.cache & ((1u64 << n) - 1);

        return v;
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache >> n;
        self.left -= n;
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, msb:usize, _:usize) -> u64 {
        msp << msb | lsp
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32l(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64l(&self.buffer[self.index..])
    }
}

endian_reader!{ BitReadBE }

impl <'a> BitReadEndian for BitReadBE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        self.cache >> (64 - n)
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache << n;
        self.left -= n;
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, _:usize, lsb:usize) -> u64 {
        msp | lsp << lsb
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32b(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64b(&self.buffer[self.index..])
    }
}

#[cfg(test)]
mod test {
    pub const CHECKBOARD0101: [u8; 128] = [0b01010101; 128];
    pub const CHECKBOARD0011: [u8; 128] = [0b00110011; 128];

    mod le {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bit());
            assert!(!reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let mut reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 3);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }
    }
    mod be {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(!reader.get_bit());
            assert!(reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let b = &CHECKBOARD0101;
            let reader = BitReadBE::new(b);

            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }
    }
}
<|endoftext|>


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

use std::env;
use std::ffi::OsStr;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path();
    repo_dir.push(crate_name);

    let st = Command::new("git")
        .args(&[
            OsStr::new("clone"),
            OsStr::new("--depth=1"),
            OsStr::new(&repo_url),
            OsStr::new(&repo_dir),
        ])
        .status()
        .expect("unable to run git");
    assert!(st.success());

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        // Encountering E0463 (can't find crate for `x`) did _not_ cause the build to fail in the
        // past. Even though it should have. That's why we explicitly panic here.
        // See PR #3552 and issue #3523 for more background.
        panic!("error: E0463");
    } else if stderr.contains("E0514") {
        panic!("incompatible crate versions");
    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
    }

    match output.status.code() {
        Some(0) => println!("Compilation successful"),
        Some(code) => eprintln!("Compilation failed. Exit code: {}", code),
        None => panic!("Process terminated by signal"),
    }
}
<commit_msg>Error in integration test, if required toolchain is not installed<commit_after>#![cfg(feature = "integration")]

use std::env;
use std::ffi::OsStr;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path();
    repo_dir.push(crate_name);

    let st = Command::new("git")
        .args(&[
            OsStr::new("clone"),
            OsStr::new("--depth=1"),
            OsStr::new(&repo_url),
            OsStr::new(&repo_dir),
        ])
        .status()
        .expect("unable to run git");
    assert!(st.success());

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        // Encountering E0463 (can't find crate for `x`) did _not_ cause the build to fail in the
        // past. Even though it should have. That's why we explicitly panic here.
        // See PR #3552 and issue #3523 for more background.
        panic!("error: E0463");
    } else if stderr.contains("E0514") {
        panic!("incompatible crate versions");
    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
    } else if stderr.contains("toolchain") && stderr.contains("is not installed") {
        panic!("missing required toolchain");
    }

    match output.status.code() {
        Some(0) => println!("Compilation successful"),
        Some(code) => eprintln!("Compilation failed. Exit code: {}", code),
        None => panic!("Process terminated by signal"),
    }
}
<|endoftext|>


<commit_before>// -*- rust -*-

import front.creader;
import front.parser;
import front.token;
import front.eval;
import front.ast;
import middle.trans;
import middle.resolve;
import middle.capture;
import middle.ty;
import middle.typeck;
import middle.typestate_check;
import util.common;

import std.map.mk_hashmap;
import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;
import std.io;
import std.Time;

import std.GetOpts;
import std.GetOpts.optopt;
import std.GetOpts.optmulti;
import std.GetOpts.optflag;
import std.GetOpts.opt_present;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.os.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @ast.crate {
    if (_str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (_str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown input file type: " + input);
    fail;
}

fn time[T](bool do_it, str what, fn()->T thunk) -> T {
    if (!do_it) { ret thunk(); }

    auto start = Time.get_time();
    auto rv = thunk();
    auto end = Time.get_time();

    // FIXME: Actually do timeval math.
    log_err #fmt("time: %s took %u s", what, (end.sec - start.sec) as uint);
    ret rv;
}

fn compile_input(session.session sess,
                        eval.env env,
                        str input, str output,
                        bool shared,
                        bool optimize,
                        bool verify,
                        bool save_temps,
                        trans.output_type ot,
                        bool time_passes,
                        bool run_typestate,
                        vec[str] library_search_paths) {
    auto def = tup(0, 0);
    auto p = parser.new_parser(sess, env, def, input, 0u);
    auto crate = time[@ast.crate](time_passes, "parsing",
        bind parse_input(sess, p, input));
    if (ot == trans.output_type_none) {ret;}

    crate = time[@ast.crate](time_passes, "external crate reading",
        bind creader.read_crates(sess, crate, library_search_paths));
    crate = time[@ast.crate](time_passes, "resolution",
        bind resolve.resolve_crate(sess, crate));
    time[()](time_passes, "capture checking",
        bind capture.check_for_captures(sess, crate));

    auto ty_cx = ty.mk_ctxt(sess);
    auto typeck_result =
        time[typeck.typecheck_result](time_passes, "typechecking",
        bind typeck.check_crate(ty_cx, crate));
    crate = typeck_result._0;
    auto type_cache = typeck_result._1;

    if (run_typestate) {
        crate = time[@ast.crate](time_passes, "typestate checking",
            bind typestate_check.check_crate(crate));
    }

    time[()](time_passes, "translation",
        bind trans.trans_crate(sess, crate, ty_cx, type_cache, output, shared,
                               optimize, verify, save_temps, ot));
}

fn pretty_print_input(session.session sess,
                             eval.env env,
                             str input) {
    auto def = tup(0, 0);
    auto p = front.parser.new_parser(sess, env, def, input, 0u);
    auto crate = front.parser.parse_crate_from_source_file(p);
    pretty.pprust.print_file(crate.node.module, input, std.io.stdout());
}

fn usage(session.session sess, str argv0) {
    io.stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) + "
options:

    -o <filename>      write output to <filename>
    --glue             generate glue.bc file
    --shared           compile a shared-library crate
    --pretty           pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --noverify         suppress LLVM verification step (slight speedup)
    --parse-only       parse only; do not compile, assemble, or link
    -O                 optimize
    -S                 compile only; do not assemble or link
    -c                 compile and assemble, but do not link
    --save-temps       write intermediate files in addition to normal output
    --time-passes      time the individual phases of the compiler
    --no-typestate     don't run the typestate pass (unsafe!)
    -h                 display this message\n\n");
}

fn get_os() -> session.os {
    auto s = std.os.target_os();
    if (_str.eq(s, "win32")) { ret session.os_win32; }
    if (_str.eq(s, "macos")) { ret session.os_macos; }
    if (_str.eq(s, "linux")) { ret session.os_linux; }
}

fn main(vec[str] args) {

    // FIXME: don't hard-wire this.
    auto target_cfg = rec(os = get_os(),
                          arch = session.arch_x86,
                          int_type = common.ty_i32,
                          uint_type = common.ty_u32,
                          float_type = common.ty_f64 );

    auto crate_cache = common.new_int_hash[session.crate_metadata]();
    auto target_crate_num = 0;
    let vec[@ast.meta_item] md = vec();
    auto sess = session.session(target_crate_num, target_cfg, crate_cache,
                                md, front.codemap.new_codemap());

    auto opts = vec(optflag("h"), optflag("glue"),
                    optflag("pretty"), optflag("ls"), optflag("parse-only"),
                    optflag("O"), optflag("shared"), optmulti("L"),
                    optflag("S"), optflag("c"), optopt("o"),
                    optflag("save-temps"), optflag("time-passes"),
                    optflag("no-typestate"), optflag("noverify"));
    auto binary = _vec.shift[str](args);
    auto match;
    alt (GetOpts.getopts(args, opts)) {
        case (GetOpts.failure(?f)) { sess.err(GetOpts.fail_str(f)); fail; }
        case (GetOpts.success(?m)) { match = m; }
    }
    if (opt_present(match, "h")) {
        usage(sess, binary);
        ret;
    }

    auto pretty = opt_present(match, "pretty");
    auto ls = opt_present(match, "ls");
    auto glue = opt_present(match, "glue");
    auto shared = opt_present(match, "shared");
    auto output_file = GetOpts.opt_maybe_str(match, "o");
    auto library_search_paths = GetOpts.opt_strs(match, "L");
    auto ot = trans.output_type_bitcode;
    if (opt_present(match, "parse-only")) {
        ot = trans.output_type_none;
    } else if (opt_present(match, "S")) {
        ot = trans.output_type_assembly;
    } else if (opt_present(match, "c")) {
        ot = trans.output_type_object;
    }
    auto verify = !opt_present(match, "noverify");
    auto save_temps = opt_present(match, "save-temps");
    // FIXME: Maybe we should support -O0, -O1, -Os, etc
    auto optimize = opt_present(match, "O");
    auto time_passes = opt_present(match, "time-passes");
    auto run_typestate = !opt_present(match, "no-typestate");
    auto n_inputs = _vec.len[str](match.free);

    if (glue) {
        if (n_inputs > 0u) {
            sess.err("No input files allowed with --glue.");
        }
        auto out = option.from_maybe[str]("glue.bc", output_file);
        middle.trans.make_common_glue(out, optimize, verify, save_temps, ot);
        ret;
    }

    if (n_inputs == 0u) {
        sess.err("No input filename given.");
    } else if (n_inputs > 1u) {
        sess.err("Multiple input filenames provided.");
    }

    auto ifile = match.free.(0);
    auto env = default_environment(sess, args.(0), ifile);
    if (pretty) {
        pretty_print_input(sess, env, ifile);
    } else if (ls) {
        front.creader.list_file_metadata(ifile, std.io.stdout());
    } else {
        alt (output_file) {
            case (none[str]) {
                let vec[str] parts = _str.split(ifile, '.' as u8);
                _vec.pop[str](parts);
                parts += vec(".bc");
                auto ofile = _str.concat(parts);
                compile_input(sess, env, ifile, ofile, shared,
                              optimize, verify, save_temps, ot,
                              time_passes, run_typestate,
                              library_search_paths);
            }
            case (some[str](?ofile)) {
                compile_input(sess, env, ifile, ofile, shared,
                              optimize, verify, save_temps, ot,
                              time_passes, run_typestate,
                              library_search_paths);
            }
        }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>rustc: Preserve dots in input path when using an implicit output path<commit_after>// -*- rust -*-

import front.creader;
import front.parser;
import front.token;
import front.eval;
import front.ast;
import middle.trans;
import middle.resolve;
import middle.capture;
import middle.ty;
import middle.typeck;
import middle.typestate_check;
import util.common;

import std.map.mk_hashmap;
import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;
import std.io;
import std.Time;

import std.GetOpts;
import std.GetOpts.optopt;
import std.GetOpts.optmulti;
import std.GetOpts.optflag;
import std.GetOpts.opt_present;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.os.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @ast.crate {
    if (_str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (_str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown input file type: " + input);
    fail;
}

fn time[T](bool do_it, str what, fn()->T thunk) -> T {
    if (!do_it) { ret thunk(); }

    auto start = Time.get_time();
    auto rv = thunk();
    auto end = Time.get_time();

    // FIXME: Actually do timeval math.
    log_err #fmt("time: %s took %u s", what, (end.sec - start.sec) as uint);
    ret rv;
}

fn compile_input(session.session sess,
                        eval.env env,
                        str input, str output,
                        bool shared,
                        bool optimize,
                        bool verify,
                        bool save_temps,
                        trans.output_type ot,
                        bool time_passes,
                        bool run_typestate,
                        vec[str] library_search_paths) {
    auto def = tup(0, 0);
    auto p = parser.new_parser(sess, env, def, input, 0u);
    auto crate = time[@ast.crate](time_passes, "parsing",
        bind parse_input(sess, p, input));
    if (ot == trans.output_type_none) {ret;}

    crate = time[@ast.crate](time_passes, "external crate reading",
        bind creader.read_crates(sess, crate, library_search_paths));
    crate = time[@ast.crate](time_passes, "resolution",
        bind resolve.resolve_crate(sess, crate));
    time[()](time_passes, "capture checking",
        bind capture.check_for_captures(sess, crate));

    auto ty_cx = ty.mk_ctxt(sess);
    auto typeck_result =
        time[typeck.typecheck_result](time_passes, "typechecking",
        bind typeck.check_crate(ty_cx, crate));
    crate = typeck_result._0;
    auto type_cache = typeck_result._1;

    if (run_typestate) {
        crate = time[@ast.crate](time_passes, "typestate checking",
            bind typestate_check.check_crate(crate));
    }

    time[()](time_passes, "translation",
        bind trans.trans_crate(sess, crate, ty_cx, type_cache, output, shared,
                               optimize, verify, save_temps, ot));
}

fn pretty_print_input(session.session sess,
                             eval.env env,
                             str input) {
    auto def = tup(0, 0);
    auto p = front.parser.new_parser(sess, env, def, input, 0u);
    auto crate = front.parser.parse_crate_from_source_file(p);
    pretty.pprust.print_file(crate.node.module, input, std.io.stdout());
}

fn usage(session.session sess, str argv0) {
    io.stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) + "
options:

    -o <filename>      write output to <filename>
    --glue             generate glue.bc file
    --shared           compile a shared-library crate
    --pretty           pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --noverify         suppress LLVM verification step (slight speedup)
    --parse-only       parse only; do not compile, assemble, or link
    -O                 optimize
    -S                 compile only; do not assemble or link
    -c                 compile and assemble, but do not link
    --save-temps       write intermediate files in addition to normal output
    --time-passes      time the individual phases of the compiler
    --no-typestate     don't run the typestate pass (unsafe!)
    -h                 display this message\n\n");
}

fn get_os() -> session.os {
    auto s = std.os.target_os();
    if (_str.eq(s, "win32")) { ret session.os_win32; }
    if (_str.eq(s, "macos")) { ret session.os_macos; }
    if (_str.eq(s, "linux")) { ret session.os_linux; }
}

fn main(vec[str] args) {

    // FIXME: don't hard-wire this.
    auto target_cfg = rec(os = get_os(),
                          arch = session.arch_x86,
                          int_type = common.ty_i32,
                          uint_type = common.ty_u32,
                          float_type = common.ty_f64 );

    auto crate_cache = common.new_int_hash[session.crate_metadata]();
    auto target_crate_num = 0;
    let vec[@ast.meta_item] md = vec();
    auto sess = session.session(target_crate_num, target_cfg, crate_cache,
                                md, front.codemap.new_codemap());

    auto opts = vec(optflag("h"), optflag("glue"),
                    optflag("pretty"), optflag("ls"), optflag("parse-only"),
                    optflag("O"), optflag("shared"), optmulti("L"),
                    optflag("S"), optflag("c"), optopt("o"),
                    optflag("save-temps"), optflag("time-passes"),
                    optflag("no-typestate"), optflag("noverify"));
    auto binary = _vec.shift[str](args);
    auto match;
    alt (GetOpts.getopts(args, opts)) {
        case (GetOpts.failure(?f)) { sess.err(GetOpts.fail_str(f)); fail; }
        case (GetOpts.success(?m)) { match = m; }
    }
    if (opt_present(match, "h")) {
        usage(sess, binary);
        ret;
    }

    auto pretty = opt_present(match, "pretty");
    auto ls = opt_present(match, "ls");
    auto glue = opt_present(match, "glue");
    auto shared = opt_present(match, "shared");
    auto output_file = GetOpts.opt_maybe_str(match, "o");
    auto library_search_paths = GetOpts.opt_strs(match, "L");
    auto ot = trans.output_type_bitcode;
    if (opt_present(match, "parse-only")) {
        ot = trans.output_type_none;
    } else if (opt_present(match, "S")) {
        ot = trans.output_type_assembly;
    } else if (opt_present(match, "c")) {
        ot = trans.output_type_object;
    }
    auto verify = !opt_present(match, "noverify");
    auto save_temps = opt_present(match, "save-temps");
    // FIXME: Maybe we should support -O0, -O1, -Os, etc
    auto optimize = opt_present(match, "O");
    auto time_passes = opt_present(match, "time-passes");
    auto run_typestate = !opt_present(match, "no-typestate");
    auto n_inputs = _vec.len[str](match.free);

    if (glue) {
        if (n_inputs > 0u) {
            sess.err("No input files allowed with --glue.");
        }
        auto out = option.from_maybe[str]("glue.bc", output_file);
        middle.trans.make_common_glue(out, optimize, verify, save_temps, ot);
        ret;
    }

    if (n_inputs == 0u) {
        sess.err("No input filename given.");
    } else if (n_inputs > 1u) {
        sess.err("Multiple input filenames provided.");
    }

    auto ifile = match.free.(0);
    auto env = default_environment(sess, args.(0), ifile);
    if (pretty) {
        pretty_print_input(sess, env, ifile);
    } else if (ls) {
        front.creader.list_file_metadata(ifile, std.io.stdout());
    } else {
        alt (output_file) {
            case (none[str]) {
                let vec[str] parts = _str.split(ifile, '.' as u8);
                _vec.pop[str](parts);
                parts += vec("bc");
                auto ofile = _str.connect(parts, ".");
                compile_input(sess, env, ifile, ofile, shared,
                              optimize, verify, save_temps, ot,
                              time_passes, run_typestate,
                              library_search_paths);
            }
            case (some[str](?ofile)) {
                compile_input(sess, env, ifile, ofile, shared,
                              optimize, verify, save_temps, ot,
                              time_passes, run_typestate,
                              library_search_paths);
            }
        }
    }
}

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


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write, ErrorKind, Result};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<commit_msg>Add test for posix_fadvise<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

#![feature(rustc_private)]

extern crate libc;

use std::fs::{File, remove_file};
use std::io::{Read, Write, ErrorKind, Result};
use std::os::unix::io::AsRawFd;
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test calling posix_fadvise on the file.
    unsafe {
        libc::posix_fadvise(
            file.as_raw_fd(),
            0,
            bytes.len() as i64,
            libc::POSIX_FADV_DONTNEED,
        );
    }

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, Arg, SubCommand, ErrorKind};

#[test]
fn subcommand() {
    let m = App::new("test")
        .subcommand(SubCommand::with_name("some")
            .arg(Arg::with_name("test")
                .short("t")
                .long("test")
                .takes_value(true)
                .help("testing testing")))
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec!["myprog", "some", "--test", "testing"]);

    assert_eq!(m.subcommand_name().unwrap(), "some");
    let sub_m = m.subcommand_matches("some").unwrap();
    assert!(sub_m.is_present("test"));
    assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}

#[test]
fn subcommand_none_given() {
    let m = App::new("test")
        .subcommand(SubCommand::with_name("some")
            .arg(Arg::with_name("test")
                .short("t")
                .long("test")
                .takes_value(true)
                .help("testing testing")))
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec![""]);

    assert!(m.subcommand_name().is_none());
}

#[test]
fn subcommand_multiple() {
    let m = App::new("test")
        .subcommands(vec![
            SubCommand::with_name("some")
                .arg(Arg::with_name("test")
                    .short("t")
                    .long("test")
                    .takes_value(true)
                    .help("testing testing")),
            SubCommand::with_name("add")
                .arg(Arg::with_name("roster").short("r"))
        ])
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec!["myprog", "some", "--test", "testing"]);

    assert!(m.subcommand_matches("some").is_some());
    assert!(m.subcommand_matches("add").is_none());
    assert_eq!(m.subcommand_name().unwrap(), "some");
    let sub_m = m.subcommand_matches("some").unwrap();
    assert!(sub_m.is_present("test"));
    assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}

#[test]
fn single_alias() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .alias("do-stuff"))
                .get_matches_from(vec!["myprog", "do-stuff"]);
    assert_eq!(m.subcommand_name(), Some("test"));
}

#[test]
fn multiple_aliases() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .aliases(&["do-stuff", "test-stuff"]))
                .get_matches_from(vec!["myprog", "test-stuff"]);
    assert_eq!(m.subcommand_name(), Some("test"));
}

#[test]
fn subcmd_did_you_mean_output() {
    test::check_err_output(test::complex_app(), "clap-test subcm",
"error: The subcommand 'subcm' wasn't recognized
\tDid you mean 'subcmd' ?

If you believe you received this message in error, try re-running with 'clap-test -- subcm'

USAGE:
    clap-test [FLAGS] [OPTIONS] [ARGS] [SUBCOMMAND]

For more information try --help", true);
}

#[test]
fn alias_help() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .alias("do-stuff"))
                .get_matches_from_safe(vec!["myprog", "help", "do-stuff"]);
    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}<commit_msg>tests: adds tests for visible aliases<commit_after>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, Arg, SubCommand, ErrorKind};

static VISIBLE_ALIAS_HELP: &'static str = "clap-test 2.6

USAGE:
    clap-test [FLAGS] [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    help      Prints this message or the help of the given subcommand(s)
    vim|vi    Some help";

#[test]
fn subcommand() {
    let m = App::new("test")
        .subcommand(SubCommand::with_name("some")
            .arg(Arg::with_name("test")
                .short("t")
                .long("test")
                .takes_value(true)
                .help("testing testing")))
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec!["myprog", "some", "--test", "testing"]);

    assert_eq!(m.subcommand_name().unwrap(), "some");
    let sub_m = m.subcommand_matches("some").unwrap();
    assert!(sub_m.is_present("test"));
    assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}

#[test]
fn subcommand_none_given() {
    let m = App::new("test")
        .subcommand(SubCommand::with_name("some")
            .arg(Arg::with_name("test")
                .short("t")
                .long("test")
                .takes_value(true)
                .help("testing testing")))
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec![""]);

    assert!(m.subcommand_name().is_none());
}

#[test]
fn subcommand_multiple() {
    let m = App::new("test")
        .subcommands(vec![
            SubCommand::with_name("some")
                .arg(Arg::with_name("test")
                    .short("t")
                    .long("test")
                    .takes_value(true)
                    .help("testing testing")),
            SubCommand::with_name("add")
                .arg(Arg::with_name("roster").short("r"))
        ])
        .arg(Arg::with_name("other").long("other"))
        .get_matches_from(vec!["myprog", "some", "--test", "testing"]);

    assert!(m.subcommand_matches("some").is_some());
    assert!(m.subcommand_matches("add").is_none());
    assert_eq!(m.subcommand_name().unwrap(), "some");
    let sub_m = m.subcommand_matches("some").unwrap();
    assert!(sub_m.is_present("test"));
    assert_eq!(sub_m.value_of("test").unwrap(), "testing");
}

#[test]
fn single_alias() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .alias("do-stuff"))
                .get_matches_from(vec!["myprog", "do-stuff"]);
    assert_eq!(m.subcommand_name(), Some("test"));
}

#[test]
fn multiple_aliases() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .aliases(&["do-stuff", "test-stuff"]))
                .get_matches_from(vec!["myprog", "test-stuff"]);
    assert_eq!(m.subcommand_name(), Some("test"));
}

#[test]
fn subcmd_did_you_mean_output() {
    test::check_err_output(test::complex_app(), "clap-test subcm",
"error: The subcommand 'subcm' wasn't recognized
\tDid you mean 'subcmd' ?

If you believe you received this message in error, try re-running with 'clap-test -- subcm'

USAGE:
    clap-test [FLAGS] [OPTIONS] [ARGS] [SUBCOMMAND]

For more information try --help", true);
}

#[test]
fn alias_help() {
    let m = App::new("myprog")
                .subcommand(SubCommand::with_name("test")
                    .alias("do-stuff"))
                .get_matches_from_safe(vec!["myprog", "help", "do-stuff"]);
    assert!(m.is_err());
    assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
}

#[test]
fn visible_aliases_help_output() {
    let app = App::new("clap-test")
        .version("2.6")
        .subcommand(SubCommand::with_name("vim")
            .about("Some help")
            .alias("invisible")
            .visible_alias("vi"));
    test::check_help(app, VISIBLE_ALIAS_HELP);
}
<|endoftext|>


<commit_before>use crate::utils::deserialize::deserialize_opt_duration;
use cosmogony::ZoneType;
use geojson::{GeoJson, Geometry};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::time::Duration;

use crate::adapters::primary::common::coord::Coord;
use crate::adapters::primary::common::filters::Filters;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street};

pub const DEFAULT_LIMIT_RESULT_ES: i64 = 10;

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderExplainQuery {
    pub doc_id: String,
    pub doc_type: String,

    #[serde(flatten)]
    pub query: ForwardGeocoderQuery,
}

/// This structure contains all the query parameters that
/// can be submitted for the autocomplete endpoint.
///
/// Only the `q` parameter is mandatory.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderQuery {
    pub q: String,
    pub lat: Option<f32>,
    pub lon: Option<f32>,
    pub shape_scope: Option<Vec<Type>>,
    #[serde(default, rename = "type")]
    pub types: Option<Vec<Type>>,
    #[serde(default, rename = "zone_type")]
    pub zone_types: Option<Vec<ZoneType>>,
    pub poi_types: Option<Vec<String>>,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration", default)]
    pub timeout: Option<Duration>,
    pub pt_dataset: Option<Vec<String>>,
    pub poi_dataset: Option<Vec<String>>,
    pub request_id: Option<String>,
}

fn default_result_limit() -> i64 {
    DEFAULT_LIMIT_RESULT_ES
}

impl From<(ForwardGeocoderQuery, Option<Geometry>)> for Filters {
    fn from(source: (ForwardGeocoderQuery, Option<Geometry>)) -> Self {
        let (
            ForwardGeocoderQuery {
                q: _,
                lat,
                lon,
                shape_scope,
                types: _,
                zone_types,
                poi_types,
                limit,
                timeout,
                pt_dataset: _,
                poi_dataset: _,
                request_id: _
            },
            geometry,
        ) = source;
        let zone_types = zone_types.map(|zts| {
            zts.iter()
                .map(|zt| serde_json::to_string(zt).unwrap())
                .collect()
        });
        Filters {
            // When option_zip_option becomes available: coord: input.lat.zip_with(input.lon, Coord::new),
            coord: match (lat, lon) {
                (Some(lat), Some(lon)) => Some(Coord::new(lat, lon)),
                _ => None,
            },
            shape: geometry.map(|geometry| {
                (
                    geometry,
                    shape_scope
                        .map(|shape_scope| {
                            shape_scope.iter().map(|t| t.as_str().to_string()).collect()
                        })
                        .unwrap_or_else(|| {
                            vec![
                                Type::House,
                                Type::Poi,
                                Type::StopArea,
                                Type::Street,
                                Type::Zone,
                            ]
                            .iter()
                            .map(|t| t.as_str().to_string())
                            .collect()
                        }),
                )
            }),
            zone_types,
            poi_types,
            limit,
            timeout,
        }
    }
}

/// This structure contains all the query parameters that
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ReverseGeocoderQuery {
    pub lat: f64,
    pub lon: f64,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration")]
    pub timeout: Option<Duration>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JsonParam {
    pub shape: GeoJson,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ExplainResponseBody {
    pub explanation: JsonValue,
}

impl From<JsonValue> for ExplainResponseBody {
    fn from(explanation: JsonValue) -> Self {
        ExplainResponseBody { explanation }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct BragiStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct MimirStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ElasticsearchStatus {
    pub version: String,
    pub health: String,
    pub url: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct StatusResponseBody {
    pub bragi: BragiStatus,
    pub mimir: MimirStatus,
    pub elasticsearch: ElasticsearchStatus,
}

/// This macro is used to define the forward_geocoder route.
/// It takes a client (ElasticsearchStorage) and query settings
/// It can be either a GET request, with query parameters,
/// or a POST request, with both query parameters and a GeoJson shape
/// in the body.
#[macro_export]
macro_rules! forward_geocoder {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_get()
            .or(routes::forward_geocoder_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder)
    };
}

pub use forward_geocoder;

#[macro_export]
macro_rules! forward_geocoder_explain {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_explain_get()
            .or(routes::forward_geocoder_explain_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder_explain)
    };
}
pub use forward_geocoder_explain;

#[macro_export]
macro_rules! reverse_geocoder {
    ($cl:expr, $st:expr) => {
        routes::reverse_geocoder()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::reverse_geocoder)
    };
}
pub use reverse_geocoder;

#[macro_export]
macro_rules! status {
    ($cl:expr, $es:expr) => {
        routes::status()
            .and(routes::with_client($cl))
            .and(routes::with_elasticsearch($es))
            .and_then(handlers::status)
    };
}
pub use status;

#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Type {
    #[serde(rename = "house")]
    House,
    #[serde(rename = "poi")]
    Poi,
    #[serde(rename = "public_transport:stop_area")]
    StopArea,
    #[serde(rename = "street")]
    Street,
    #[serde(rename = "zone")]
    Zone,
}

impl Type {
    pub fn as_str(&self) -> &'static str {
        match self {
            Type::House => "house",
            Type::Poi => "poi",
            Type::StopArea => "public_transport:stop_area",
            Type::Street => "street",
            Type::Zone => "zone",
        }
    }

    pub fn as_index_type(&self) -> &'static str {
        match self {
            Type::House => Addr::static_doc_type(),
            Type::Poi => Poi::static_doc_type(),
            Type::StopArea => Stop::static_doc_type(),
            Type::Street => Street::static_doc_type(),
            Type::Zone => Admin::static_doc_type(),
        }
    }
}
<commit_msg>fix fmt<commit_after>use crate::utils::deserialize::deserialize_opt_duration;
use cosmogony::ZoneType;
use geojson::{GeoJson, Geometry};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::time::Duration;

use crate::adapters::primary::common::coord::Coord;
use crate::adapters::primary::common::filters::Filters;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street};

pub const DEFAULT_LIMIT_RESULT_ES: i64 = 10;

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderExplainQuery {
    pub doc_id: String,
    pub doc_type: String,

    #[serde(flatten)]
    pub query: ForwardGeocoderQuery,
}

/// This structure contains all the query parameters that
/// can be submitted for the autocomplete endpoint.
///
/// Only the `q` parameter is mandatory.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderQuery {
    pub q: String,
    pub lat: Option<f32>,
    pub lon: Option<f32>,
    pub shape_scope: Option<Vec<Type>>,
    #[serde(default, rename = "type")]
    pub types: Option<Vec<Type>>,
    #[serde(default, rename = "zone_type")]
    pub zone_types: Option<Vec<ZoneType>>,
    pub poi_types: Option<Vec<String>>,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration", default)]
    pub timeout: Option<Duration>,
    pub pt_dataset: Option<Vec<String>>,
    pub poi_dataset: Option<Vec<String>>,
    pub request_id: Option<String>,
}

fn default_result_limit() -> i64 {
    DEFAULT_LIMIT_RESULT_ES
}

impl From<(ForwardGeocoderQuery, Option<Geometry>)> for Filters {
    fn from(source: (ForwardGeocoderQuery, Option<Geometry>)) -> Self {
        let (
            ForwardGeocoderQuery {
                q: _,
                lat,
                lon,
                shape_scope,
                types: _,
                zone_types,
                poi_types,
                limit,
                timeout,
                pt_dataset: _,
                poi_dataset: _,
                request_id: _,
            },
            geometry,
        ) = source;
        let zone_types = zone_types.map(|zts| {
            zts.iter()
                .map(|zt| serde_json::to_string(zt).unwrap())
                .collect()
        });
        Filters {
            // When option_zip_option becomes available: coord: input.lat.zip_with(input.lon, Coord::new),
            coord: match (lat, lon) {
                (Some(lat), Some(lon)) => Some(Coord::new(lat, lon)),
                _ => None,
            },
            shape: geometry.map(|geometry| {
                (
                    geometry,
                    shape_scope
                        .map(|shape_scope| {
                            shape_scope.iter().map(|t| t.as_str().to_string()).collect()
                        })
                        .unwrap_or_else(|| {
                            vec![
                                Type::House,
                                Type::Poi,
                                Type::StopArea,
                                Type::Street,
                                Type::Zone,
                            ]
                            .iter()
                            .map(|t| t.as_str().to_string())
                            .collect()
                        }),
                )
            }),
            zone_types,
            poi_types,
            limit,
            timeout,
        }
    }
}

/// This structure contains all the query parameters that
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ReverseGeocoderQuery {
    pub lat: f64,
    pub lon: f64,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration")]
    pub timeout: Option<Duration>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JsonParam {
    pub shape: GeoJson,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ExplainResponseBody {
    pub explanation: JsonValue,
}

impl From<JsonValue> for ExplainResponseBody {
    fn from(explanation: JsonValue) -> Self {
        ExplainResponseBody { explanation }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct BragiStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct MimirStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ElasticsearchStatus {
    pub version: String,
    pub health: String,
    pub url: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct StatusResponseBody {
    pub bragi: BragiStatus,
    pub mimir: MimirStatus,
    pub elasticsearch: ElasticsearchStatus,
}

/// This macro is used to define the forward_geocoder route.
/// It takes a client (ElasticsearchStorage) and query settings
/// It can be either a GET request, with query parameters,
/// or a POST request, with both query parameters and a GeoJson shape
/// in the body.
#[macro_export]
macro_rules! forward_geocoder {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_get()
            .or(routes::forward_geocoder_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder)
    };
}

pub use forward_geocoder;

#[macro_export]
macro_rules! forward_geocoder_explain {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_explain_get()
            .or(routes::forward_geocoder_explain_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder_explain)
    };
}
pub use forward_geocoder_explain;

#[macro_export]
macro_rules! reverse_geocoder {
    ($cl:expr, $st:expr) => {
        routes::reverse_geocoder()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::reverse_geocoder)
    };
}
pub use reverse_geocoder;

#[macro_export]
macro_rules! status {
    ($cl:expr, $es:expr) => {
        routes::status()
            .and(routes::with_client($cl))
            .and(routes::with_elasticsearch($es))
            .and_then(handlers::status)
    };
}
pub use status;

#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Type {
    #[serde(rename = "house")]
    House,
    #[serde(rename = "poi")]
    Poi,
    #[serde(rename = "public_transport:stop_area")]
    StopArea,
    #[serde(rename = "street")]
    Street,
    #[serde(rename = "zone")]
    Zone,
}

impl Type {
    pub fn as_str(&self) -> &'static str {
        match self {
            Type::House => "house",
            Type::Poi => "poi",
            Type::StopArea => "public_transport:stop_area",
            Type::Street => "street",
            Type::Zone => "zone",
        }
    }

    pub fn as_index_type(&self) -> &'static str {
        match self {
            Type::House => Addr::static_doc_type(),
            Type::Poi => Poi::static_doc_type(),
            Type::StopArea => Stop::static_doc_type(),
            Type::Street => Street::static_doc_type(),
            Type::Zone => Admin::static_doc_type(),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, deprecated)]
#![plugin(clippy)]

#![deny(inline_always, deprecated_semver)]

#[inline(always)] //~ERROR you have declared `#[inline(always)]` on `test_attr_lint`.
fn test_attr_lint() {
    assert!(true)
}

#[inline(always)]
fn false_positive_expr() {
    unreachable!()
}

#[inline(always)]
fn false_positive_stmt() {
    unreachable!();
}

#[inline(always)]
fn empty_and_false_positive_stmt() {
    ;
    unreachable!();
}

#[deprecated(since = "forever")] //~ERROR the since field must contain a semver-compliant version
pub const SOME_CONST : u8 = 42;

#[deprecated(since = "1")] //~ERROR the since field must contain a semver-compliant version
pub const ANOTHER_CONST : u8 = 23;

#[deprecated(since = "0.1.1")]
pub const YET_ANOTHER_CONST : u8 = 0;

fn main() {
    test_attr_lint();
    if false { false_positive_expr() }
    if false { false_positive_stmt() }
    if false { empty_and_false_positive_stmt() }
}
<commit_msg>Remove `#[feature(deprecated)]`<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![deny(inline_always, deprecated_semver)]

#[inline(always)] //~ERROR you have declared `#[inline(always)]` on `test_attr_lint`.
fn test_attr_lint() {
    assert!(true)
}

#[inline(always)]
fn false_positive_expr() {
    unreachable!()
}

#[inline(always)]
fn false_positive_stmt() {
    unreachable!();
}

#[inline(always)]
fn empty_and_false_positive_stmt() {
    ;
    unreachable!();
}

#[deprecated(since = "forever")] //~ERROR the since field must contain a semver-compliant version
pub const SOME_CONST : u8 = 42;

#[deprecated(since = "1")] //~ERROR the since field must contain a semver-compliant version
pub const ANOTHER_CONST : u8 = 23;

#[deprecated(since = "0.1.1")]
pub const YET_ANOTHER_CONST : u8 = 0;

fn main() {
    test_attr_lint();
    if false { false_positive_expr() }
    if false { false_positive_stmt() }
    if false { empty_and_false_positive_stmt() }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;
extern crate ws;

use std::env;
use std::thread;
use std::io::Read;
use std::path::Path;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

use uuid::Uuid;

use iron::prelude::*;
use iron::status;
use iron::modifiers::Header;
use iron::headers::{AccessControlAllowOrigin,SetCookie,Cookie,CookieJar};
use iron::middleware::{BeforeMiddleware};

use mount::Mount;
use staticfile::Static;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
    ip: std::net::SocketAddr,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}⁖{}", self.uuid, self.ip)
    }
}

fn respond(status: status::Status, msg: &str) -> Response {
    Response::with((status, msg, Header(AccessControlAllowOrigin::Any)))
}

fn respond_ok(msg: &str) -> Response {
    respond(status::Ok, msg)
}

struct ParseCookie { }

impl BeforeMiddleware for ParseCookie {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        // Parse some cookies
        if let Some(cookie_header) = req.headers.get::<iron::headers::Cookie>() {
            cookie_header.to_cookie_jar();
            for cookie in cookie_header.iter() {
            }
        }
        Ok(())
    }

    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<()> {
        // TODO??? Not really sure what this is.
        Ok(())
    }
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    let mut router = router::Router::new();

    {
        let connections = connections.clone();
        let game_connect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection {
                uuid: new_uuid,
                ip: req.remote_addr,
            };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("connect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            let resp = respond_ok(&format!("{}", new_uuid));
            Ok(resp.set(Header(SetCookie(vec![
                              String::from(format!("bzwf_anon_wstx={}", new_conn))
            ]))))
        };
        router.get("/connect", game_connect, "connect");
    }

    {
        let connections = connections.clone();
        let game_disconnect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            /* NOTE(jordan): Must "let _ = ..." Otherwise this gives compiler warning "unused
             * result which must be used"
             */
            /* FIXME(jordan): Is there error-handling we aren't doing here? Whoops... That return
             * value probably *means* something.
             */
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.remove(&req_uuid) {
                Some(dropped_conn) => {
                    println!("disconnect: user with uuid {}", dropped_conn.uuid);
                    println!("{} connected users", conn_map.len());
                    Ok(respond_ok("dropped"))
                },
                None => {
                    println!("error: disconnect: tried to drop unconnected user {}", req_uuid);
                    Ok(
                        respond(status::Conflict, "error: cannot drop a user who is not connected")
                    )
                },
            }
        };
        router.post("/disconnect", game_disconnect, "disconnect");
    }

    {
        let connections = connections.clone();
        let game_ping = move |req: &mut Request| -> IronResult<Response> {
            if let Ok(conn_map) = connections.lock() {
                let mut req_body = String::new();
                let _ = req.body.read_to_string(&mut req_body);
                let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

                match conn_map.get(&req_uuid) {
                    Some(conn) => {
                        println!("ping[{}]: user with uuid {} sent ping",
                                 time::precise_time_ns(),
                                 conn.uuid);
                        Ok(respond_ok("pong"))
                    },
                    None => {
                        println!("error: ping: nonexistent user {} tried to ping", req_uuid);
                        Ok(respond(status::NotFound, ""))
                    },
                }
            } else {
                panic!("error: ping: cannot obtain lock on connections map");
            }
        };

        let game_ping_ref = Arc::new(game_ping);
        for endpoint in vec!["/ping", "/keep-alive"] {
            let handle = game_ping_ref.clone();
            let desc   = format!("ping:{}", endpoint);
            router.post(endpoint, move |req: &mut Request| handle(req), desc);
        }
    }

    let mut assets_mount = Mount::new();
    assets_mount
        .mount("/", router)
        .mount("/client", Static::new(Path::new("../client")));

    struct WSServer {
        out: ws::Sender,
    }

    impl ws::Handler for WSServer {
        fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
            // TODO
            println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     msg);
            Ok(())
        }

        fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
            // TODO
            println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]");
            Ok(())
        }

        fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
            println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     code,
                     reason);
            // TODO
        }

        fn on_error(&mut self, err: ws::Error) {
            println!("ws:err[{}]: user with uuid {} got error {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     err);
            // TODO
        }
    }

    {
        let domain : String;

        match env::var("ADDR") {
            Ok(val) => domain = val,
            Err(_)  => {
                println!("Environment error! ADDR not found; using localhost for default.");
                domain = String::from("localhost")
            }
        }

        // FIXME(jordan): Printing that servers are running before they fail or succeed...
        let web_domain = domain.clone();
        let webserver_thread = thread::spawn(move || {
            let web_addr = format!("{}:3000", web_domain);
            println!("TCP Web server listening on {}", web_addr);
            println!("\tGo to: http://{}/client/html", web_addr);
            Iron::new(assets_mount).http(web_addr.clone()).unwrap()
        });

        let ws_domain = domain.clone();
        let websocket_thread = thread::spawn(move || {
            let ws_addr = format!("{}:3001", ws_domain);
            println!("WS WebSockets server listening on {}", ws_addr);
            ws::listen(ws_addr.clone(), |out| WSServer { out: out }).unwrap()
        });

        webserver_thread.join().unwrap();
        websocket_thread.join().unwrap();
    }
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<commit_msg>Remove nonexistent CookieJar nonsense<commit_after>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;
extern crate ws;

use std::env;
use std::thread;
use std::io::Read;
use std::path::Path;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

use uuid::Uuid;

use iron::prelude::*;
use iron::status;
use iron::modifiers::Header;
use iron::headers::{AccessControlAllowOrigin,SetCookie};
use iron::middleware::{BeforeMiddleware};

use mount::Mount;
use staticfile::Static;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
    ip: std::net::SocketAddr,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}⁖{}", self.uuid, self.ip)
    }
}

fn respond(status: status::Status, msg: &str) -> Response {
    Response::with((status, msg, Header(AccessControlAllowOrigin::Any)))
}

fn respond_ok(msg: &str) -> Response {
    respond(status::Ok, msg)
}

struct ParseCookie { }

impl BeforeMiddleware for ParseCookie {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        // Parse some cookies
        if let Some(cookie_header) = req.headers.get::<iron::headers::Cookie>() {
            // println!("coooookie: {:?}", cookie_header)
        }
        Ok(())
    }

    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<()> {
        // TODO??? Not really sure what this is.
        Ok(())
    }
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    let mut router = router::Router::new();

    {
        let connections = connections.clone();
        let game_connect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection {
                uuid: new_uuid,
                ip: req.remote_addr,
            };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("connect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            let resp = respond_ok(&format!("{}", new_uuid));
            Ok(resp.set(Header(SetCookie(vec![
                              String::from(format!("bzwf_anon_wstx={}", new_conn))
            ]))))
        };
        router.get("/connect", game_connect, "connect");
    }

    {
        let connections = connections.clone();
        let game_disconnect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            /* NOTE(jordan): Must "let _ = ..." Otherwise this gives compiler warning "unused
             * result which must be used"
             */
            /* FIXME(jordan): Is there error-handling we aren't doing here? Whoops... That return
             * value probably *means* something.
             */
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.remove(&req_uuid) {
                Some(dropped_conn) => {
                    println!("disconnect: user with uuid {}", dropped_conn.uuid);
                    println!("{} connected users", conn_map.len());
                    Ok(respond_ok("dropped"))
                },
                None => {
                    println!("error: disconnect: tried to drop unconnected user {}", req_uuid);
                    Ok(
                        respond(status::Conflict, "error: cannot drop a user who is not connected")
                    )
                },
            }
        };
        router.post("/disconnect", game_disconnect, "disconnect");
    }

    {
        let connections = connections.clone();
        let game_ping = move |req: &mut Request| -> IronResult<Response> {
            if let Ok(conn_map) = connections.lock() {
                let mut req_body = String::new();
                let _ = req.body.read_to_string(&mut req_body);
                let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

                match conn_map.get(&req_uuid) {
                    Some(conn) => {
                        println!("ping[{}]: user with uuid {} sent ping",
                                 time::precise_time_ns(),
                                 conn.uuid);
                        Ok(respond_ok("pong"))
                    },
                    None => {
                        println!("error: ping: nonexistent user {} tried to ping", req_uuid);
                        Ok(respond(status::NotFound, ""))
                    },
                }
            } else {
                panic!("error: ping: cannot obtain lock on connections map");
            }
        };

        let game_ping_ref = Arc::new(game_ping);
        for endpoint in vec!["/ping", "/keep-alive"] {
            let handle = game_ping_ref.clone();
            let desc   = format!("ping:{}", endpoint);
            router.post(endpoint, move |req: &mut Request| handle(req), desc);
        }
    }

    let mut assets_mount = Mount::new();
    assets_mount
        .mount("/", router)
        .mount("/client", Static::new(Path::new("../client")));

    struct WSServer {
        out: ws::Sender,
    }

    impl ws::Handler for WSServer {
        fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
            // TODO
            println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     msg);
            Ok(())
        }

        fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
            // TODO
            println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]");
            Ok(())
        }

        fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
            println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     code,
                     reason);
            // TODO
        }

        fn on_error(&mut self, err: ws::Error) {
            println!("ws:err[{}]: user with uuid {} got error {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     err);
            // TODO
        }
    }

    {
        let domain : String;

        match env::var("ADDR") {
            Ok(val) => domain = val,
            Err(_)  => {
                println!("Environment error! ADDR not found; using localhost for default.");
                domain = String::from("localhost")
            }
        }

        // FIXME(jordan): Printing that servers are running before they fail or succeed...
        let web_domain = domain.clone();
        let webserver_thread = thread::spawn(move || {
            let web_addr = format!("{}:3000", web_domain);
            println!("TCP Web server listening on {}", web_addr);
            println!("\tGo to: http://{}/client/html", web_addr);
            Iron::new(assets_mount).http(web_addr.clone()).unwrap()
        });

        let ws_domain = domain.clone();
        let websocket_thread = thread::spawn(move || {
            let ws_addr = format!("{}:3001", ws_domain);
            println!("WS WebSockets server listening on {}", ws_addr);
            ws::listen(ws_addr.clone(), |out| WSServer { out: out }).unwrap()
        });

        webserver_thread.join().unwrap();
        websocket_thread.join().unwrap();
    }
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<|endoftext|>