<commit_before>//! Implementation of `get_bytes` operation on `Buf`.
//!
//! See also [this PR](https://github.com/tokio-rs/bytes/pull/363).

use bytes::buf::ext::BufExt;
use bytes::buf::ext::Chain;
use bytes::buf::ext::Take;
use bytes::Buf;
use bytes::BufMut;
use bytes::Bytes;
use bytes::BytesMut;
use std::cmp;
use std::io::Cursor;

/// Get `Bytes` from `Buf`.
pub trait BufGetBytes: Buf {
    /// Consumes requested number of bytes from `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bytes::Buf;
    /// use httpbis::BufGetBytes;
    ///
    /// let bytes = (&b"hello world"[..]).get_bytes(5);
    /// assert_eq!(&bytes[..], &b"hello"[..]);
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if there is not enough remaining data in `self`.
    fn get_bytes(&mut self, mut cnt: usize) -> Bytes {
        if cnt == 0 {
            return Bytes::new();
        }

        assert!(self.remaining() >= cnt);

        // Could be as simple as self.take(count).to_bytes()
        // but compiler stack overflows on instantiation of test Buf impl for some types

        let mut ret = BytesMut::with_capacity(cnt);

        while cnt != 0 {
            let bytes = self.bytes();
            let step = cmp::min(bytes.len(), cnt);
            ret.put_slice(&bytes[..step]);
            self.advance(step);
            cnt -= step;
        }

        ret.freeze()
    }
}

impl BufGetBytes for Bytes {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        self.split_to(cnt)
    }
}

impl BufGetBytes for BytesMut {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        self.split_to(cnt).freeze()
    }
}

impl BufGetBytes for &[u8] {}

impl<A: AsRef<[u8]>> BufGetBytes for Cursor<A> {}

impl<A: BufGetBytes, B: BufGetBytes> BufGetBytes for Chain<A, B> {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        let a_rem = self.first_mut().remaining();
        if a_rem >= cnt {
            self.first_mut().get_bytes(cnt)
        } else if !self.first_mut().has_remaining() {
            self.last_mut().get_bytes(cnt)
        } else {
            assert!(cnt <= a_rem + self.last_mut().remaining());

            let mut ret = BytesMut::with_capacity(cnt);
            ret.put(self.first_mut());
            ret.put((self.last_mut()).take(cnt - a_rem));
            ret.freeze()
        }
    }
}

impl<A: BufGetBytes> BufGetBytes for Take<A> {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        assert!(cnt <= self.remaining());
        let ret = self.get_mut().get_bytes(cnt);
        self.set_limit(self.limit() - cnt);
        ret
    }
}

impl<A: BufGetBytes> BufGetBytes for &mut A {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        (&mut **self).get_bytes(cnt)
    }
}

#[cfg(test)]
mod test {
    use crate::bytes_ext::buf_get_bytes::BufGetBytes;
    use bytes::buf::BufExt;
    use bytes::Buf;
    use bytes::Bytes;
    use bytes::BytesMut;

    #[test]
    fn get_to_bytes() {
        let mut buf = &b"abcd"[..];
        assert_eq!(Bytes::copy_from_slice(b"abcd"), buf.to_bytes());
        assert_eq!(b"", buf);
    }

    #[test]
    fn get_get_bytes() {
        let mut buf = &b"abcd"[..];
        assert_eq!(Bytes::copy_from_slice(b"abc"), buf.get_bytes(3));
        assert_eq!(b"d", buf);
    }

    #[test]
    fn bytes_get_bytes() {
        let mut bytes = Bytes::from(b"abc".to_vec());

        let a = bytes.get_bytes(1);
        assert_eq!(b"a", a.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            a.as_ref().as_ptr() as usize + 1,
            bytes.as_ref().as_ptr() as usize
        );

        let bc = bytes.get_bytes(2);
        assert_eq!(b"bc", bc.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            bc.as_ref().as_ptr() as usize,
            a.as_ref().as_ptr() as usize + 1
        );

        assert_eq!(Bytes::new(), bytes);
    }

    #[test]
    fn bytes_mut_get_bytes() {
        let mut bytes = BytesMut::from(&b"abc"[..]);

        let a = bytes.get_bytes(1);
        assert_eq!(b"a", a.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            a.as_ref().as_ptr() as usize + 1,
            bytes.as_ref().as_ptr() as usize
        );

        let bc = bytes.get_bytes(2);
        assert_eq!(b"bc", bc.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            bc.as_ref().as_ptr() as usize,
            a.as_ref().as_ptr() as usize + 1
        );

        assert_eq!(BytesMut::new(), bytes);
    }

    #[test]
    fn chain_to_bytes() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        let mut cd = Bytes::copy_from_slice(b"cd");
        let mut chain = (&mut ab).chain(&mut cd);
        assert_eq!(Bytes::copy_from_slice(b"abcd"), chain.to_bytes());
        assert_eq!(Bytes::new(), ab);
        assert_eq!(Bytes::new(), cd);
    }

    #[test]
    fn chain_to_bytes_first_empty() {
        let mut cd = Bytes::copy_from_slice(b"cd");
        let cd_ptr = cd.as_ptr();
        let mut chain = Bytes::new().chain(&mut cd);
        let cd_to_bytes = chain.to_bytes();
        assert_eq!(b"cd", cd_to_bytes.as_ref());
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Chain`
        // assert_eq!(cd_ptr, cd_to_bytes.as_ptr());
        // assert_eq!(Bytes::new(), cd);
    }

    #[test]
    fn chain_to_bytes_second_empty() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        let ab_ptr = ab.as_ptr();
        let mut chain = (&mut ab).chain(Bytes::new());
        let ab_to_bytes = chain.to_bytes();
        assert_eq!(b"ab", ab_to_bytes.as_ref());
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Chain`
        // assert_eq!(ab_ptr, ab_to_bytes.as_ptr());
        // assert_eq!(Bytes::new(), ab);
    }

    #[test]
    fn chain_get_bytes() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        let mut cd = Bytes::copy_from_slice(b"cd");
        let ab_ptr = ab.as_ptr();
        let cd_ptr = cd.as_ptr();
        let mut chain = (&mut ab).chain(&mut cd);
        let a = chain.get_bytes(1);
        let bc = chain.get_bytes(2);
        let d = chain.get_bytes(1);

        assert_eq!(Bytes::copy_from_slice(b"a"), a);
        assert_eq!(Bytes::copy_from_slice(b"bc"), bc);
        assert_eq!(Bytes::copy_from_slice(b"d"), d);

        // assert `get_bytes` did not allocate
        assert_eq!(ab_ptr, a.as_ptr());
        // assert `get_bytes` did not allocate
        assert_eq!(cd_ptr.wrapping_offset(1), d.as_ptr());
    }

    #[test]
    fn take_to_bytes() {
        let mut abcd = Bytes::copy_from_slice(b"abcd");
        let abcd_ptr = abcd.as_ptr();
        let mut take = (&mut abcd).take(2);
        let ab = take.to_bytes();
        assert_eq!(Bytes::copy_from_slice(b"ab"), ab);
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Take`
        //assert_eq!(abcd_ptr, ab.as_ptr());
        //assert_eq!(Bytes::copy_from_slice(b"cd"), abcd);
    }

    #[test]
    fn take_get_bytes() {
        let mut abcd = Bytes::copy_from_slice(b"abcd");
        let abcd_ptr = abcd.as_ptr();
        let mut take = (&mut abcd).take(2);
        let a = take.get_bytes(1);
        assert_eq!(Bytes::copy_from_slice(b"a"), a);
        // assert `to_bytes` did not allocate
        assert_eq!(abcd_ptr, a.as_ptr());
        assert_eq!(Bytes::copy_from_slice(b"bcd"), abcd);
    }

    #[test]
    #[should_panic]
    fn take_get_bytes_panics() {
        let abcd = Bytes::copy_from_slice(b"abcd");
        abcd.take(2).get_bytes(3);
    }
}
<commit_msg>warnings<commit_after>//! Implementation of `get_bytes` operation on `Buf`.
//!
//! See also [this PR](https://github.com/tokio-rs/bytes/pull/363).

use bytes::buf::ext::BufExt;
use bytes::buf::ext::Chain;
use bytes::buf::ext::Take;
use bytes::Buf;
use bytes::BufMut;
use bytes::Bytes;
use bytes::BytesMut;
use std::cmp;
use std::io::Cursor;

/// Get `Bytes` from `Buf`.
pub trait BufGetBytes: Buf {
    /// Consumes requested number of bytes from `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use bytes::Buf;
    /// use httpbis::BufGetBytes;
    ///
    /// let bytes = (&b"hello world"[..]).get_bytes(5);
    /// assert_eq!(&bytes[..], &b"hello"[..]);
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if there is not enough remaining data in `self`.
    fn get_bytes(&mut self, mut cnt: usize) -> Bytes {
        if cnt == 0 {
            return Bytes::new();
        }

        assert!(self.remaining() >= cnt);

        // Could be as simple as self.take(count).to_bytes()
        // but compiler stack overflows on instantiation of test Buf impl for some types

        let mut ret = BytesMut::with_capacity(cnt);

        while cnt != 0 {
            let bytes = self.bytes();
            let step = cmp::min(bytes.len(), cnt);
            ret.put_slice(&bytes[..step]);
            self.advance(step);
            cnt -= step;
        }

        ret.freeze()
    }
}

impl BufGetBytes for Bytes {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        self.split_to(cnt)
    }
}

impl BufGetBytes for BytesMut {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        self.split_to(cnt).freeze()
    }
}

impl BufGetBytes for &[u8] {}

impl<A: AsRef<[u8]>> BufGetBytes for Cursor<A> {}

impl<A: BufGetBytes, B: BufGetBytes> BufGetBytes for Chain<A, B> {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        let a_rem = self.first_mut().remaining();
        if a_rem >= cnt {
            self.first_mut().get_bytes(cnt)
        } else if !self.first_mut().has_remaining() {
            self.last_mut().get_bytes(cnt)
        } else {
            assert!(cnt <= a_rem + self.last_mut().remaining());

            let mut ret = BytesMut::with_capacity(cnt);
            ret.put(self.first_mut());
            ret.put((self.last_mut()).take(cnt - a_rem));
            ret.freeze()
        }
    }
}

impl<A: BufGetBytes> BufGetBytes for Take<A> {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        assert!(cnt <= self.remaining());
        let ret = self.get_mut().get_bytes(cnt);
        self.set_limit(self.limit() - cnt);
        ret
    }
}

impl<A: BufGetBytes> BufGetBytes for &mut A {
    fn get_bytes(&mut self, cnt: usize) -> Bytes {
        (&mut **self).get_bytes(cnt)
    }
}

#[cfg(test)]
mod test {
    use crate::bytes_ext::buf_get_bytes::BufGetBytes;
    use bytes::buf::BufExt;
    use bytes::Buf;
    use bytes::Bytes;
    use bytes::BytesMut;

    #[test]
    fn get_to_bytes() {
        let mut buf = &b"abcd"[..];
        assert_eq!(Bytes::copy_from_slice(b"abcd"), buf.to_bytes());
        assert_eq!(b"", buf);
    }

    #[test]
    fn get_get_bytes() {
        let mut buf = &b"abcd"[..];
        assert_eq!(Bytes::copy_from_slice(b"abc"), buf.get_bytes(3));
        assert_eq!(b"d", buf);
    }

    #[test]
    fn bytes_get_bytes() {
        let mut bytes = Bytes::from(b"abc".to_vec());

        let a = bytes.get_bytes(1);
        assert_eq!(b"a", a.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            a.as_ref().as_ptr() as usize + 1,
            bytes.as_ref().as_ptr() as usize
        );

        let bc = bytes.get_bytes(2);
        assert_eq!(b"bc", bc.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            bc.as_ref().as_ptr() as usize,
            a.as_ref().as_ptr() as usize + 1
        );

        assert_eq!(Bytes::new(), bytes);
    }

    #[test]
    fn bytes_mut_get_bytes() {
        let mut bytes = BytesMut::from(&b"abc"[..]);

        let a = bytes.get_bytes(1);
        assert_eq!(b"a", a.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            a.as_ref().as_ptr() as usize + 1,
            bytes.as_ref().as_ptr() as usize
        );

        let bc = bytes.get_bytes(2);
        assert_eq!(b"bc", bc.as_ref());
        // assert returned bytes object is a subslice of original bytes object
        assert_eq!(
            bc.as_ref().as_ptr() as usize,
            a.as_ref().as_ptr() as usize + 1
        );

        assert_eq!(BytesMut::new(), bytes);
    }

    #[test]
    fn chain_to_bytes() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        let mut cd = Bytes::copy_from_slice(b"cd");
        let mut chain = (&mut ab).chain(&mut cd);
        assert_eq!(Bytes::copy_from_slice(b"abcd"), chain.to_bytes());
        assert_eq!(Bytes::new(), ab);
        assert_eq!(Bytes::new(), cd);
    }

    #[test]
    fn chain_to_bytes_first_empty() {
        let mut cd = Bytes::copy_from_slice(b"cd");
        //let cd_ptr = cd.as_ptr();
        let mut chain = Bytes::new().chain(&mut cd);
        let cd_to_bytes = chain.to_bytes();
        assert_eq!(b"cd", cd_to_bytes.as_ref());
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Chain`
        // assert_eq!(cd_ptr, cd_to_bytes.as_ptr());
        // assert_eq!(Bytes::new(), cd);
    }

    #[test]
    fn chain_to_bytes_second_empty() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        //let ab_ptr = ab.as_ptr();
        let mut chain = (&mut ab).chain(Bytes::new());
        let ab_to_bytes = chain.to_bytes();
        assert_eq!(b"ab", ab_to_bytes.as_ref());
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Chain`
        // assert_eq!(ab_ptr, ab_to_bytes.as_ptr());
        // assert_eq!(Bytes::new(), ab);
    }

    #[test]
    fn chain_get_bytes() {
        let mut ab = Bytes::copy_from_slice(b"ab");
        let mut cd = Bytes::copy_from_slice(b"cd");
        let ab_ptr = ab.as_ptr();
        let cd_ptr = cd.as_ptr();
        let mut chain = (&mut ab).chain(&mut cd);
        let a = chain.get_bytes(1);
        let bc = chain.get_bytes(2);
        let d = chain.get_bytes(1);

        assert_eq!(Bytes::copy_from_slice(b"a"), a);
        assert_eq!(Bytes::copy_from_slice(b"bc"), bc);
        assert_eq!(Bytes::copy_from_slice(b"d"), d);

        // assert `get_bytes` did not allocate
        assert_eq!(ab_ptr, a.as_ptr());
        // assert `get_bytes` did not allocate
        assert_eq!(cd_ptr.wrapping_offset(1), d.as_ptr());
    }

    #[test]
    fn take_to_bytes() {
        let mut abcd = Bytes::copy_from_slice(b"abcd");
        //let abcd_ptr = abcd.as_ptr();
        let mut take = (&mut abcd).take(2);
        let ab = take.to_bytes();
        assert_eq!(Bytes::copy_from_slice(b"ab"), ab);
        // assert `to_bytes` did not allocate
        // this is not possible without reimplementing `to_bytes` in `Take`
        //assert_eq!(abcd_ptr, ab.as_ptr());
        //assert_eq!(Bytes::copy_from_slice(b"cd"), abcd);
    }

    #[test]
    fn take_get_bytes() {
        let mut abcd = Bytes::copy_from_slice(b"abcd");
        let abcd_ptr = abcd.as_ptr();
        let mut take = (&mut abcd).take(2);
        let a = take.get_bytes(1);
        assert_eq!(Bytes::copy_from_slice(b"a"), a);
        // assert `to_bytes` did not allocate
        assert_eq!(abcd_ptr, a.as_ptr());
        assert_eq!(Bytes::copy_from_slice(b"bcd"), abcd);
    }

    #[test]
    #[should_panic]
    fn take_get_bytes_panics() {
        let abcd = Bytes::copy_from_slice(b"abcd");
        abcd.take(2).get_bytes(3);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_imports)]

extern crate fitsio_sys as sys;
extern crate libc;

use std::ptr;
use std::ffi;

mod stringutils;

/// Error type
#[derive(Debug, PartialEq, Eq)]
pub struct FitsError {
    status: i32,
    message: String,
}

pub type Result<T> = std::result::Result<T, FitsError>;

/// Hdu description type
///
/// Any way of describing a HDU - number or string which either
/// changes the hdu by absolute number, or by name.
pub trait DescribesHdu {
    fn change_hdu(&self, fptr: &FitsFile) -> Result<()>;
}

impl DescribesHdu for usize {
    fn change_hdu(&self, f: &FitsFile) -> Result<()> {
        let mut _hdu_type = 0;
        let mut status = 0;
        unsafe {
            sys::ffmahd(f.fptr, (*self + 1) as i32, &mut _hdu_type, &mut status);
        }
        match status {
            0 => Ok(()),
            _ => Err(FitsError {
                status: status,
                message: stringutils::status_to_string(status).unwrap(),
            }),
        }
    }
}

impl<'a> DescribesHdu for &'a str {
    fn change_hdu(&self, f: &FitsFile) -> Result<()> {
        let mut _hdu_type = 0;
        let mut status = 0;
        let c_hdu_name = ffi::CString::new(*self).unwrap();

        unsafe {
            sys::ffmnhd(f.fptr,
                   sys::HduType::ANY_HDU as libc::c_int,
                   c_hdu_name.into_raw(),
                   0,
                   &mut status);
        }

        match status {
            0 => Ok(()),
            _ => Err(FitsError {
                status: status,
                message: stringutils::status_to_string(status).unwrap(),
            }),
        }
    }
}

pub struct FitsFile {
    fptr: *mut sys::fitsfile,
    pub filename: String,
}

pub struct FitsHdu<'a> {
    fits_file: &'a FitsFile,
    hdunum: usize,
}

impl FitsFile {
    pub fn open(filename: &str) -> Result<Self> {
        let mut fptr = ptr::null_mut();
        let mut status = 0;
        let c_filename = ffi::CString::new(filename).unwrap();

        unsafe {
            sys::ffopen(&mut fptr as *mut *mut sys::fitsfile,
                   c_filename.as_ptr(),
                   sys::FileOpenMode::READONLY as libc::c_int,
                   &mut status);
        }

        match status {
            0 => {
                Ok(FitsFile {
                    fptr: fptr,
                    filename: filename.to_string(),
                })
            }
            status => {
                Err(FitsError {
                    status: status,
                    message: stringutils::status_to_string(status).unwrap(),
                })
            }
        }

    }

    pub fn create(path: &str) -> Result<Self> {
        let mut fptr = ptr::null_mut();
        let mut status = 0;
        let c_filename = ffi::CString::new(path).unwrap();

        unsafe {
            sys::ffinit(&mut fptr as *mut *mut sys::fitsfile,
                        c_filename.as_ptr(),
                        &mut status);
        }

        match status {
            0 => {
                Ok(FitsFile {
                    fptr: fptr,
                    filename: path.to_string(),
                })
            }
            status => {
                Err(FitsError {
                    status: status,
                    message: stringutils::status_to_string(status).unwrap(),
                })
            }
        }
    }

    pub fn hdu<T: DescribesHdu>(&self, hdu_description: T) -> Result<FitsHdu> {
        try!(hdu_description.change_hdu(self));
        let hdu_number = self.hdu_number();

        Ok(FitsHdu {
            fits_file: self,
            hdunum: hdu_number,
        })
    }

    fn hdu_number(&self) -> usize {
        let mut hdu_num = 0;
        unsafe {
            sys::ffghdn(self.fptr, &mut hdu_num);
        }
        (hdu_num - 1) as usize
    }
}

impl Drop for FitsFile {
    fn drop(&mut self) {
        let mut status = 0;
        unsafe {
            sys::ffclos(self.fptr, &mut status);
        }
    }
}

#[cfg(test)]
mod test {
    extern crate tempdir;
    use super::FitsFile;

    #[test]
    fn opening_an_existing_file() {
        match FitsFile::open("../testdata/full_example.fits") {
            Ok(_) => {}
            Err(e) => panic!("{:?}", e),
        }
    }

    #[test]
    fn creating_a_new_file() {
        let tdir = tempdir::TempDir::new("fitsio-").unwrap();
        let tdir_path = tdir.path();
        let filename = tdir_path.join("test.fits");
        assert!(!filename.exists());

        match FitsFile::create(filename.to_str().unwrap()) {
            Ok(_) => assert!(filename.exists()),
            Err(e) => panic!("Error: {:?}", e),
        }
    }

    #[test]
    fn fetching_a_hdu() {
        let f = FitsFile::open("../testdata/full_example.fits").unwrap();
        for i in 0..2 {
            assert_eq!(f.hdu(i).unwrap().hdunum, i);
        }
        match f.hdu(2) {
            Err(e) => assert_eq!(e.status, 107),
            _ => panic!("Error checking for failure"),
        }

        let tbl_hdu = f.hdu("TESTEXT").unwrap();
        assert_eq!(tbl_hdu.hdunum, 1);
    }
}
<commit_msg>Implement header key reading<commit_after>#![allow(dead_code, unused_imports)]

extern crate fitsio_sys as sys;
extern crate libc;

use std::ptr;
use std::ffi;

mod stringutils;

/// Error type
#[derive(Debug, PartialEq, Eq)]
pub struct FitsError {
    status: i32,
    message: String,
}

pub type Result<T> = std::result::Result<T, FitsError>;

/// Hdu description type
///
/// Any way of describing a HDU - number or string which either
/// changes the hdu by absolute number, or by name.
pub trait DescribesHdu {
    fn change_hdu(&self, fptr: &FitsFile) -> Result<()>;
}

impl DescribesHdu for usize {
    fn change_hdu(&self, f: &FitsFile) -> Result<()> {
        let mut _hdu_type = 0;
        let mut status = 0;
        unsafe {
            sys::ffmahd(f.fptr, (*self + 1) as i32, &mut _hdu_type, &mut status);
        }
        match status {
            0 => Ok(()),
            _ => Err(FitsError {
                status: status,
                message: stringutils::status_to_string(status).unwrap(),
            }),
        }
    }
}

impl<'a> DescribesHdu for &'a str {
    fn change_hdu(&self, f: &FitsFile) -> Result<()> {
        let mut _hdu_type = 0;
        let mut status = 0;
        let c_hdu_name = ffi::CString::new(*self).unwrap();

        unsafe {
            sys::ffmnhd(f.fptr,
                   sys::HduType::ANY_HDU as libc::c_int,
                   c_hdu_name.into_raw(),
                   0,
                   &mut status);
        }

        match status {
            0 => Ok(()),
            _ => Err(FitsError {
                status: status,
                message: stringutils::status_to_string(status).unwrap(),
            }),
        }
    }
}

/// Trait applied to types which can be read from a FITS header
///
/// This is currently:
///
/// * i32
/// * i64
/// * f32
/// * f64
/// * String
pub trait ReadsKey {
    fn read_key(f: &FitsFile, name: &str) -> Result<Self> where Self: std::marker::Sized;
}

macro_rules! reads_key_impl {
    ($t:ty, $func:ident) => (
        impl ReadsKey for $t {
            fn read_key(f: &FitsFile, name: &str) -> Result<Self> {
                let c_name = ffi::CString::new(name).unwrap();
                let mut status = 0;
                let mut value: Self = Self::default();

                unsafe {
                    sys::$func(f.fptr,
                           c_name.into_raw(),
                           &mut value,
                           ptr::null_mut(),
                           &mut status);
                }

                match status {
                    0 => Ok(value),
                    s => {
                        Err(FitsError {
                            status: s,
                            message: stringutils::status_to_string(s).unwrap(),
                        })
                    }
                }
            }
        }
    )
}

reads_key_impl!(i32, ffgkyl);
reads_key_impl!(i64, ffgkyj);
reads_key_impl!(f32, ffgkye);
reads_key_impl!(f64, ffgkyd);

impl ReadsKey for String {
    fn read_key(f: &FitsFile, name: &str) -> Result<Self> {
        let c_name = ffi::CString::new(name).unwrap();
        let mut status = 0;
        let mut value: Vec<libc::c_char> = vec![0; sys::MAX_VALUE_LENGTH];

        unsafe {
            sys::ffgkys(f.fptr,
                   c_name.into_raw(),
                   value.as_mut_ptr(),
                   ptr::null_mut(),
                   &mut status);
        }

        match status {
            0 => {
                let value: Vec<u8> = value.iter()
                    .map(|&x| x as u8)
                    .filter(|&x| x != 0)
                    .collect();
                Ok(String::from_utf8(value).unwrap())
            }
            status => {
                Err(FitsError {
                    status: status,
                    message: stringutils::status_to_string(status).unwrap(),
                })
            }
        }

    }
}

pub struct FitsFile {
    fptr: *mut sys::fitsfile,
    pub filename: String,
}

impl FitsFile {
    pub fn open(filename: &str) -> Result<Self> {
        let mut fptr = ptr::null_mut();
        let mut status = 0;
        let c_filename = ffi::CString::new(filename).unwrap();

        unsafe {
            sys::ffopen(&mut fptr as *mut *mut sys::fitsfile,
                   c_filename.as_ptr(),
                   sys::FileOpenMode::READONLY as libc::c_int,
                   &mut status);
        }

        match status {
            0 => {
                Ok(FitsFile {
                    fptr: fptr,
                    filename: filename.to_string(),
                })
            }
            status => {
                Err(FitsError {
                    status: status,
                    message: stringutils::status_to_string(status).unwrap(),
                })
            }
        }

    }

    pub fn create(path: &str) -> Result<Self> {
        let mut fptr = ptr::null_mut();
        let mut status = 0;
        let c_filename = ffi::CString::new(path).unwrap();

        unsafe {
            sys::ffinit(&mut fptr as *mut *mut sys::fitsfile,
                        c_filename.as_ptr(),
                        &mut status);
        }

        match status {
            0 => {
                Ok(FitsFile {
                    fptr: fptr,
                    filename: path.to_string(),
                })
            }
            status => {
                Err(FitsError {
                    status: status,
                    message: stringutils::status_to_string(status).unwrap(),
                })
            }
        }
    }

    pub fn hdu<T: DescribesHdu>(&self, hdu_description: T) -> Result<FitsHdu> {
        try!(hdu_description.change_hdu(self));
        let hdu_number = self.hdu_number();

        Ok(FitsHdu {
            fits_file: self,
            hdunum: hdu_number,
        })
    }

    fn hdu_number(&self) -> usize {
        let mut hdu_num = 0;
        unsafe {
            sys::ffghdn(self.fptr, &mut hdu_num);
        }
        (hdu_num - 1) as usize
    }
}

impl Drop for FitsFile {
    fn drop(&mut self) {
        let mut status = 0;
        unsafe {
            sys::ffclos(self.fptr, &mut status);
        }
    }
}

pub struct FitsHdu<'a> {
    fits_file: &'a FitsFile,
    hdunum: usize,
}

impl<'a> FitsHdu<'a> {
    pub fn read_key<T: ReadsKey>(&self, name: &str) -> Result<T> {
        T::read_key(self.fits_file, name)
    }
}

#[cfg(test)]
mod test {
    extern crate tempdir;
    use super::FitsFile;

    #[test]
    fn opening_an_existing_file() {
        match FitsFile::open("../testdata/full_example.fits") {
            Ok(_) => {}
            Err(e) => panic!("{:?}", e),
        }
    }

    #[test]
    fn creating_a_new_file() {
        let tdir = tempdir::TempDir::new("fitsio-").unwrap();
        let tdir_path = tdir.path();
        let filename = tdir_path.join("test.fits");
        assert!(!filename.exists());

        match FitsFile::create(filename.to_str().unwrap()) {
            Ok(_) => assert!(filename.exists()),
            Err(e) => panic!("Error: {:?}", e),
        }
    }

    #[test]
    fn fetching_a_hdu() {
        let f = FitsFile::open("../testdata/full_example.fits").unwrap();
        for i in 0..2 {
            assert_eq!(f.hdu(i).unwrap().hdunum, i);
        }
        match f.hdu(2) {
            Err(e) => assert_eq!(e.status, 107),
            _ => panic!("Error checking for failure"),
        }

        let tbl_hdu = f.hdu("TESTEXT").unwrap();
        assert_eq!(tbl_hdu.hdunum, 1);
    }

    #[test]
    fn reading_header_keys() {
        let f = FitsFile::open("../testdata/full_example.fits").unwrap();
        match f.hdu(0).unwrap().read_key::<i64>("INTTEST") {
            Ok(value) => assert_eq!(value, 42),
            Err(e) => panic!("Error reading key: {:?}", e),
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    assist_context::{AssistContext, Assists},
    AssistId,
};
use syntax::{
    ast::{self, Impl, NameOwner},
    AstNode,
};
use test_utils::mark;

// Assist: generate_default_from_new
//
// Generates default implementation from new method.
//
// ```
// struct Example { _inner: () }
//
// impl Example {
//     pub fn n$0ew() -> Self {
//         Self { _inner: () }
//     }
// }
// ```
// ->
// ```
// struct Example { _inner: () }
//
// impl Example {
//     pub fn new() -> Self {
//         Self { _inner: () }
//     }
// }
//
// impl Default for Example {
//     fn default() -> Self {
//         Self::new()
//     }
// }
// ```
pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
    let fn_name = fn_node.name()?;

    if fn_name.text() != "new" {
        mark::hit!(other_function_than_new);
        return None;
    }

    if fn_node.param_list()?.params().next().is_some() {
        mark::hit!(new_function_with_parameters);
        return None;
    }

    let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;

    let insert_location = impl_.syntax().text_range();

    acc.add(
        AssistId("generate_default_from_new", crate::AssistKind::Generate),
        "Generate a Default impl from a new fn",
        insert_location,
        move |builder| {
            let code = default_fn_node_for_new(impl_);
            builder.insert(insert_location.end(), code);
        },
    )
}

fn default_fn_node_for_new(impl_: Impl) -> String {
    format!(
        "

impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}",
        impl_.self_ty().unwrap().syntax().text()
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_default() {
        check_assist(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn ne$0w() -> Self {
        Self { _inner: () }
    }
}

fn main() {}
"#,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}

fn main() {}
"#,
        );
    }

    #[test]
    fn generate_default2() {
        check_assist(
            generate_default_from_new,
            r#"
struct Test { value: u32 }

impl Test {
    pub fn ne$0w() -> Self {
        Self { value: 0 }
    }
}
"#,
            r#"
struct Test { value: u32 }

impl Test {
    pub fn new() -> Self {
        Self { value: 0 }
    }
}

impl Default for Test {
    fn default() -> Self {
        Self::new()
    }
}
"#,
        );
    }

    #[test]
    fn new_function_with_parameters() {
        mark::check!(new_function_with_parameters);
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn $0new(value: ()) -> Self {
        Self { _inner: value }
    }
}
"#,
        );
    }

    #[test]
    fn other_function_than_new() {
        mark::check!(other_function_than_new);
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Exmaple {
    pub fn a$0dd() -> Self {
        Self { _inner: () }
    }
}

"#,
        );
    }

    //     #[test]
    //     fn default_block_is_already_present() {
    //         check_assist_not_applicable(generate_default_from_new,
    //         r#"
    // struct Example { _inner: () }

    // impl Exmaple {
    //     pub fn n$0ew() -> Self {
    //         Self { _inner: () }
    //     }
    // }

    // impl Default for Example {
    //     fn default() -> Self {
    //         Self::new()
    //     }
    // }
    // "#,
    //         );
    //     }

    #[test]
    fn standalone_new_function() {
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
fn n$0ew() -> u32 {
    0
}
"#,
        );
    }

    #[test]
    fn multiple_struct_blocks() {
        check_assist(
            generate_default_from_new,
            r#"
struct Example { _inner: () }
struct Test { value: u32 }

impl Example {
    pub fn new$0() -> Self {
        Self { _inner: () }
    }
}
"#,
            r#"
struct Example { _inner: () }
struct Test { value: u32 }

impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}
"#,
        );
    }

    #[test]
    fn when_struct_is_after_impl() {
        check_assist(
            generate_default_from_new,
            r#"
impl Example {
    pub fn $0new() -> Self {
        Self { _inner: () }
    }
}

struct Example { _inner: () }
"#,
            r#"
impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}

struct Example { _inner: () }
"#,
        );
    }
}
<commit_msg>7708: Added the logic to check is default impl is already present.<commit_after>use crate::{
    assist_context::{AssistContext, Assists},
    AssistId,
};
use hir::TypeRef;
use syntax::{
    ast::{self, Impl, NameOwner},
    AstNode,
};
use test_utils::mark;

// Assist: generate_default_from_new
//
// Generates default implementation from new method.
//
// ```
// struct Example { _inner: () }
//
// impl Example {
//     pub fn n$0ew() -> Self {
//         Self { _inner: () }
//     }
// }
// ```
// ->
// ```
// struct Example { _inner: () }
//
// impl Example {
//     pub fn new() -> Self {
//         Self { _inner: () }
//     }
// }
//
// impl Default for Example {
//     fn default() -> Self {
//         Self::new()
//     }
// }
// ```
pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let fn_node = ctx.find_node_at_offset::<ast::Fn>()?;
    let fn_name = fn_node.name()?;

    if fn_name.text() != "new" {
        mark::hit!(other_function_than_new);
        return None;
    }

    if fn_node.param_list()?.params().next().is_some() {
        mark::hit!(new_function_with_parameters);
        return None;
    }

    let impl_ = fn_node.syntax().ancestors().into_iter().find_map(ast::Impl::cast)?;
    if is_default_implemented(ctx, &impl_).is_some() {
        return None;
    }

    let insert_location = impl_.syntax().text_range();

    acc.add(
        AssistId("generate_default_from_new", crate::AssistKind::Generate),
        "Generate a Default impl from a new fn",
        insert_location,
        move |builder| {
            let code = default_fn_node_for_new(impl_);
            builder.insert(insert_location.end(), code);
        },
    )
}

fn default_fn_node_for_new(impl_: Impl) -> String {
    format!(
        "

impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}",
        impl_.self_ty().unwrap().syntax().text()
    )
}

fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> Option<bool> {
    let db = ctx.sema.db;
    let module = impl_.syntax().parent()?;
    let sema_scope = ctx.sema.scope(&module);
    let impls = sema_scope.module()?.impl_defs(db);
    let mut name = None;
    for i in impls {
        if let Some(TypeRef::Path(p)) = i.target_trait(db) {
            name = p.segments().iter().map(|s| s.name.to_string()).find(|n| n == "Default");
        }
    }

    name.map(|n| !n.is_empty())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_default() {
        check_assist(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn ne$0w() -> Self {
        Self { _inner: () }
    }
}

fn main() {}
"#,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}

fn main() {}
"#,
        );
    }

    #[test]
    fn generate_default2() {
        check_assist(
            generate_default_from_new,
            r#"
struct Test { value: u32 }

impl Test {
    pub fn ne$0w() -> Self {
        Self { value: 0 }
    }
}
"#,
            r#"
struct Test { value: u32 }

impl Test {
    pub fn new() -> Self {
        Self { value: 0 }
    }
}

impl Default for Test {
    fn default() -> Self {
        Self::new()
    }
}
"#,
        );
    }

    #[test]
    fn new_function_with_parameters() {
        mark::check!(new_function_with_parameters);
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Example {
    pub fn $0new(value: ()) -> Self {
        Self { _inner: value }
    }
}
"#,
        );
    }

    #[test]
    fn other_function_than_new() {
        mark::check!(other_function_than_new);
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Exmaple {
    pub fn a$0dd() -> Self {
        Self { _inner: () }
    }
}

"#,
        );
    }

    #[test]
    fn default_block_is_already_present() {
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
struct Example { _inner: () }

impl Exmaple {
    pub fn n$0ew() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}
"#,
        );
    }

    #[test]
    fn standalone_new_function() {
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
fn n$0ew() -> u32 {
    0
}
"#,
        );
    }

    #[test]
    fn multiple_struct_blocks() {
        check_assist(
            generate_default_from_new,
            r#"
struct Example { _inner: () }
struct Test { value: u32 }

impl Example {
    pub fn new$0() -> Self {
        Self { _inner: () }
    }
}
"#,
            r#"
struct Example { _inner: () }
struct Test { value: u32 }

impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}
"#,
        );
    }

    #[test]
    fn when_struct_is_after_impl() {
        check_assist(
            generate_default_from_new,
            r#"
impl Example {
    pub fn $0new() -> Self {
        Self { _inner: () }
    }
}

struct Example { _inner: () }
"#,
            r#"
impl Example {
    pub fn new() -> Self {
        Self { _inner: () }
    }
}

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}

struct Example { _inner: () }
"#,
        );
    }

    #[test]
    fn struct_in_module() {
        check_assist(
            generate_default_from_new,
            r#"
mod test {
    struct Example { _inner: () }

    impl Example {
        pub fn n$0ew() -> Self {
            Self { _inner: () }
        }
    }
}
"#,
            r#"
mod test {
    struct Example { _inner: () }

    impl Example {
        pub fn new() -> Self {
            Self { _inner: () }
        }
    }

impl Default for Example {
    fn default() -> Self {
        Self::new()
    }
}
}
"#,
        );
    }

    #[test]
    fn struct_in_module_with_default() {
        check_assist_not_applicable(
            generate_default_from_new,
            r#"
mod test {
    struct Example { _inner: () }

    impl Example {
        pub fn n$0ew() -> Self {
            Self { _inner: () }
        }
    }

    impl Default for Example {
        fn default() -> Self {
            Self::new()
        }
    }
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>/* automatically generated by rust-bindgen */

import bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutInit};
import bindgen::{glutInitDisplayMode, glutPostRedisplay, glutSwapBuffers, glutTimerFunc};
import libc::*;
import dvec::{dvec, extensions};
import ptr::{addr_of, null};
import str::bytes;
import task::{local_data_get, local_data_set};
import unsafe::reinterpret_cast;
import vec::unsafe::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

type GLenum = i32;
type GLint = i32;
type GLfloat = f32;
type GLdouble = f64;

enum Window = c_int;

const DOUBLE: c_uint = 2 as c_uint;

fn destroy<T>(-_value: [T]/~) {
    // let it drop
}

fn init() unsafe {
    let argc = 0 as c_int;
    let command = bytes("glut");
    let argv: (*u8, *u8) = (to_ptr(command), null());
    let argv_p = reinterpret_cast(addr_of(argv));

    glutInit(addr_of(argc), argv_p);

    destroy(command);
}

fn create_window(name: str) -> Window unsafe {
    let bytes = str::bytes(name);
    ret Window(glutCreateWindow(to_ptr(bytes) as *c_char));
}

fn destroy_window(window: Window) unsafe {
    glutDestroyWindow(*window);
}

fn display_callback_tls_key(+_callback: @fn@()) {
    // Empty.
}

extern fn display_callback() unsafe {
    let callback = local_data_get(display_callback_tls_key).get();
    (*callback)();
}

fn display_func(callback: fn@()) unsafe {
    local_data_set(display_callback_tls_key, @callback);
    glutDisplayFunc(display_callback);
}

fn timer_callback_tls_key(+_callback: @dvec<fn@()>) {
    // Empty.
}

extern fn timer_callback(index: int) unsafe {
    let callbacks = local_data_get(timer_callback_tls_key).get();
    ((*callbacks)[index as uint])();
}

fn timer_func(msecs: u32, callback: fn@()) unsafe {
    let callbacks;
    alt local_data_get(timer_callback_tls_key) {
        none {
            callbacks = @dvec();
            local_data_set(timer_callback_tls_key, copy callbacks);
        }
        some(existing_callbacks) {
            callbacks = existing_callbacks;
        }
    }

    callbacks.push(callback);
    let index = (callbacks.len() - 1) as c_int;
    glutTimerFunc(msecs, timer_callback, index);
}

#[cfg(target_os="macos")]
fn check_loop() unsafe {
    ext::glutCheckLoop();
}

#[cfg(target_os="linux")]
fn check_loop() unsafe {
    ext::glutMainLoopEvent();
}

fn init_display_mode(mode: c_uint) unsafe {
    glutInitDisplayMode(mode);
}

fn swap_buffers() unsafe {
    glutSwapBuffers();
}

fn post_redisplay() unsafe {
    glutPostRedisplay();
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
extern mod bindgen {

fn glutInit(++argcp: *c_int, ++argv: **c_char);

fn glutInitDisplayMode(++mode: c_uint);

fn glutInitDisplayString(++string: *c_char);

fn glutInitWindowPosition(++x: c_int, ++y: c_int);

fn glutInitWindowSize(++width: c_int, ++height: c_int);

fn glutMainLoop();

fn glutCreateWindow(++title: *c_char) -> c_int;

fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

fn glutDestroyWindow(++win: c_int);

fn glutPostRedisplay();

fn glutPostWindowRedisplay(++win: c_int);

fn glutSwapBuffers();

fn glutGetWindow() -> c_int;

fn glutSetWindow(++win: c_int);

fn glutSetWindowTitle(++title: *c_char);

fn glutSetIconTitle(++title: *c_char);

fn glutPositionWindow(++x: c_int, ++y: c_int);

fn glutReshapeWindow(++width: c_int, ++height: c_int);

fn glutPopWindow();

fn glutPushWindow();

fn glutIconifyWindow();

fn glutShowWindow();

fn glutHideWindow();

fn glutFullScreen();

fn glutSetCursor(++cursor: c_int);

fn glutWarpPointer(++x: c_int, ++y: c_int);

fn glutEstablishOverlay();

fn glutRemoveOverlay();

fn glutUseLayer(++layer: GLenum);

fn glutPostOverlayRedisplay();

fn glutPostWindowOverlayRedisplay(++win: c_int);

fn glutShowOverlay();

fn glutHideOverlay();

fn glutCreateMenu(++arg1: *u8) -> c_int;

fn glutDestroyMenu(++menu: c_int);

fn glutGetMenu() -> c_int;

fn glutSetMenu(++menu: c_int);

fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

fn glutRemoveMenuItem(++item: c_int);

fn glutAttachMenu(++button: c_int);

fn glutDetachMenu(++button: c_int);

fn glutDisplayFunc(++func: *u8);

fn glutReshapeFunc(++func: *u8);

fn glutKeyboardFunc(++func: *u8);

fn glutMouseFunc(++func: *u8);

fn glutMotionFunc(++func: *u8);

fn glutPassiveMotionFunc(++func: *u8);

fn glutEntryFunc(++func: *u8);

fn glutVisibilityFunc(++func: *u8);

fn glutIdleFunc(++func: *u8);

fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

fn glutMenuStateFunc(++func: *u8);

fn glutSpecialFunc(++func: *u8);

fn glutSpaceballMotionFunc(++func: *u8);

fn glutSpaceballRotateFunc(++func: *u8);

fn glutSpaceballButtonFunc(++func: *u8);

fn glutButtonBoxFunc(++func: *u8);

fn glutDialsFunc(++func: *u8);

fn glutTabletMotionFunc(++func: *u8);

fn glutTabletButtonFunc(++func: *u8);

fn glutMenuStatusFunc(++func: *u8);

fn glutOverlayDisplayFunc(++func: *u8);

fn glutWindowStatusFunc(++func: *u8);

fn glutKeyboardUpFunc(++func: *u8);

fn glutSpecialUpFunc(++func: *u8);

fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

fn glutCopyColormap(++win: c_int);

fn glutGet(++_type: GLenum) -> c_int;

fn glutDeviceGet(++_type: GLenum) -> c_int;

fn glutExtensionSupported(++name: *c_char) -> c_int;

fn glutGetModifiers() -> c_int;

fn glutLayerGet(++_type: GLenum) -> c_int;

fn glutGetProcAddress(++procName: *c_char) -> *c_void;

fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCube(++size: GLdouble);

fn glutSolidCube(++size: GLdouble);

fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutWireDodecahedron();

fn glutSolidDodecahedron();

fn glutWireTeapot(++size: GLdouble);

fn glutSolidTeapot(++size: GLdouble);

fn glutWireOctahedron();

fn glutSolidOctahedron();

fn glutWireTetrahedron();

fn glutSolidTetrahedron();

fn glutWireIcosahedron();

fn glutSolidIcosahedron();

fn glutVideoResizeGet(++param: GLenum) -> c_int;

fn glutSetupVideoResizing();

fn glutStopVideoResizing();

fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutReportErrors();

fn glutIgnoreKeyRepeat(++ignore: c_int);

fn glutSetKeyRepeat(++repeatMode: c_int);

fn glutForceJoystickFunc();

fn glutGameModeString(++string: *c_char);

fn glutEnterGameMode() -> c_int;

fn glutLeaveGameMode();

fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<commit_msg>Fixed deprecated vector syntax<commit_after>/* automatically generated by rust-bindgen */

import bindgen::{glutCreateWindow, glutDestroyWindow, glutDisplayFunc, glutInit};
import bindgen::{glutInitDisplayMode, glutPostRedisplay, glutSwapBuffers, glutTimerFunc};
import libc::*;
import dvec::{dvec, extensions};
import ptr::{addr_of, null};
import str::bytes;
import task::{local_data_get, local_data_set};
import unsafe::reinterpret_cast;
import vec::unsafe::to_ptr;

/* FIXME: global variable glutStrokeRoman */

/* FIXME: global variable glutStrokeMonoRoman */

/* FIXME: global variable glutBitmap9By15 */

/* FIXME: global variable glutBitmap8By13 */

/* FIXME: global variable glutBitmapTimesRoman10 */

/* FIXME: global variable glutBitmapTimesRoman24 */

/* FIXME: global variable glutBitmapHelvetica10 */

/* FIXME: global variable glutBitmapHelvetica12 */

/* FIXME: global variable glutBitmapHelvetica18 */

type GLenum = i32;
type GLint = i32;
type GLfloat = f32;
type GLdouble = f64;

enum Window = c_int;

const DOUBLE: c_uint = 2 as c_uint;

fn destroy<T>(-_value: ~[T]) {
    // let it drop
}

fn init() unsafe {
    let argc = 0 as c_int;
    let command = bytes("glut");
    let argv: (*u8, *u8) = (to_ptr(command), null());
    let argv_p = reinterpret_cast(addr_of(argv));

    glutInit(addr_of(argc), argv_p);

    destroy(command);
}

fn create_window(name: str) -> Window unsafe {
    let bytes = str::bytes(name);
    ret Window(glutCreateWindow(to_ptr(bytes) as *c_char));
}

fn destroy_window(window: Window) unsafe {
    glutDestroyWindow(*window);
}

fn display_callback_tls_key(+_callback: @fn@()) {
    // Empty.
}

extern fn display_callback() unsafe {
    let callback = local_data_get(display_callback_tls_key).get();
    (*callback)();
}

fn display_func(callback: fn@()) unsafe {
    local_data_set(display_callback_tls_key, @callback);
    glutDisplayFunc(display_callback);
}

fn timer_callback_tls_key(+_callback: @dvec<fn@()>) {
    // Empty.
}

extern fn timer_callback(index: int) unsafe {
    let callbacks = local_data_get(timer_callback_tls_key).get();
    ((*callbacks)[index as uint])();
}

fn timer_func(msecs: u32, callback: fn@()) unsafe {
    let callbacks;
    alt local_data_get(timer_callback_tls_key) {
        none {
            callbacks = @dvec();
            local_data_set(timer_callback_tls_key, copy callbacks);
        }
        some(existing_callbacks) {
            callbacks = existing_callbacks;
        }
    }

    callbacks.push(callback);
    let index = (callbacks.len() - 1) as c_int;
    glutTimerFunc(msecs, timer_callback, index);
}

#[cfg(target_os="macos")]
fn check_loop() unsafe {
    ext::glutCheckLoop();
}

#[cfg(target_os="linux")]
fn check_loop() unsafe {
    ext::glutMainLoopEvent();
}

fn init_display_mode(mode: c_uint) unsafe {
    glutInitDisplayMode(mode);
}

fn swap_buffers() unsafe {
    glutSwapBuffers();
}

fn post_redisplay() unsafe {
    glutPostRedisplay();
}

#[cfg(target_os="macos")]
#[nolink]
#[link_args="-framework GLUT"]
extern mod dummy {
}

#[cfg(target_os="linux")]
#[link_name="glut"]
extern mod dummy {
}

#[cfg(target_os="macos")]
#[nolink]
extern mod ext {
    // Mac GLUT extension.
    fn glutCheckLoop();
}

#[cfg(target_os="linux")]
#[nolink]
extern mod ext {
    // freeglut extension.
    fn glutMainLoopEvent();
}

#[nolink]
extern mod bindgen {

fn glutInit(++argcp: *c_int, ++argv: **c_char);

fn glutInitDisplayMode(++mode: c_uint);

fn glutInitDisplayString(++string: *c_char);

fn glutInitWindowPosition(++x: c_int, ++y: c_int);

fn glutInitWindowSize(++width: c_int, ++height: c_int);

fn glutMainLoop();

fn glutCreateWindow(++title: *c_char) -> c_int;

fn glutCreateSubWindow(++win: c_int, ++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int) -> c_int;

fn glutDestroyWindow(++win: c_int);

fn glutPostRedisplay();

fn glutPostWindowRedisplay(++win: c_int);

fn glutSwapBuffers();

fn glutGetWindow() -> c_int;

fn glutSetWindow(++win: c_int);

fn glutSetWindowTitle(++title: *c_char);

fn glutSetIconTitle(++title: *c_char);

fn glutPositionWindow(++x: c_int, ++y: c_int);

fn glutReshapeWindow(++width: c_int, ++height: c_int);

fn glutPopWindow();

fn glutPushWindow();

fn glutIconifyWindow();

fn glutShowWindow();

fn glutHideWindow();

fn glutFullScreen();

fn glutSetCursor(++cursor: c_int);

fn glutWarpPointer(++x: c_int, ++y: c_int);

fn glutEstablishOverlay();

fn glutRemoveOverlay();

fn glutUseLayer(++layer: GLenum);

fn glutPostOverlayRedisplay();

fn glutPostWindowOverlayRedisplay(++win: c_int);

fn glutShowOverlay();

fn glutHideOverlay();

fn glutCreateMenu(++arg1: *u8) -> c_int;

fn glutDestroyMenu(++menu: c_int);

fn glutGetMenu() -> c_int;

fn glutSetMenu(++menu: c_int);

fn glutAddMenuEntry(++label: *c_char, ++value: c_int);

fn glutAddSubMenu(++label: *c_char, ++submenu: c_int);

fn glutChangeToMenuEntry(++item: c_int, ++label: *c_char, ++value: c_int);

fn glutChangeToSubMenu(++item: c_int, ++label: *c_char, ++submenu: c_int);

fn glutRemoveMenuItem(++item: c_int);

fn glutAttachMenu(++button: c_int);

fn glutDetachMenu(++button: c_int);

fn glutDisplayFunc(++func: *u8);

fn glutReshapeFunc(++func: *u8);

fn glutKeyboardFunc(++func: *u8);

fn glutMouseFunc(++func: *u8);

fn glutMotionFunc(++func: *u8);

fn glutPassiveMotionFunc(++func: *u8);

fn glutEntryFunc(++func: *u8);

fn glutVisibilityFunc(++func: *u8);

fn glutIdleFunc(++func: *u8);

fn glutTimerFunc(++millis: c_uint, ++func: *u8, ++value: c_int);

fn glutMenuStateFunc(++func: *u8);

fn glutSpecialFunc(++func: *u8);

fn glutSpaceballMotionFunc(++func: *u8);

fn glutSpaceballRotateFunc(++func: *u8);

fn glutSpaceballButtonFunc(++func: *u8);

fn glutButtonBoxFunc(++func: *u8);

fn glutDialsFunc(++func: *u8);

fn glutTabletMotionFunc(++func: *u8);

fn glutTabletButtonFunc(++func: *u8);

fn glutMenuStatusFunc(++func: *u8);

fn glutOverlayDisplayFunc(++func: *u8);

fn glutWindowStatusFunc(++func: *u8);

fn glutKeyboardUpFunc(++func: *u8);

fn glutSpecialUpFunc(++func: *u8);

fn glutJoystickFunc(++func: *u8, ++pollInterval: c_int);

fn glutSetColor(++arg1: c_int, ++red: GLfloat, ++green: GLfloat, ++blue: GLfloat);

fn glutGetColor(++ndx: c_int, ++component: c_int) -> GLfloat;

fn glutCopyColormap(++win: c_int);

fn glutGet(++_type: GLenum) -> c_int;

fn glutDeviceGet(++_type: GLenum) -> c_int;

fn glutExtensionSupported(++name: *c_char) -> c_int;

fn glutGetModifiers() -> c_int;

fn glutLayerGet(++_type: GLenum) -> c_int;

fn glutGetProcAddress(++procName: *c_char) -> *c_void;

fn glutBitmapCharacter(++font: *c_void, ++character: c_int);

fn glutBitmapWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutStrokeCharacter(++font: *c_void, ++character: c_int);

fn glutStrokeWidth(++font: *c_void, ++character: c_int) -> c_int;

fn glutBitmapLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutStrokeLength(++font: *c_void, ++string: *c_uchar) -> c_int;

fn glutWireSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidSphere(++radius: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutSolidCone(++base: GLdouble, ++height: GLdouble, ++slices: GLint, ++stacks: GLint);

fn glutWireCube(++size: GLdouble);

fn glutSolidCube(++size: GLdouble);

fn glutWireTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutSolidTorus(++innerRadius: GLdouble, ++outerRadius: GLdouble, ++sides: GLint, ++rings: GLint);

fn glutWireDodecahedron();

fn glutSolidDodecahedron();

fn glutWireTeapot(++size: GLdouble);

fn glutSolidTeapot(++size: GLdouble);

fn glutWireOctahedron();

fn glutSolidOctahedron();

fn glutWireTetrahedron();

fn glutSolidTetrahedron();

fn glutWireIcosahedron();

fn glutSolidIcosahedron();

fn glutVideoResizeGet(++param: GLenum) -> c_int;

fn glutSetupVideoResizing();

fn glutStopVideoResizing();

fn glutVideoResize(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutVideoPan(++x: c_int, ++y: c_int, ++width: c_int, ++height: c_int);

fn glutReportErrors();

fn glutIgnoreKeyRepeat(++ignore: c_int);

fn glutSetKeyRepeat(++repeatMode: c_int);

fn glutForceJoystickFunc();

fn glutGameModeString(++string: *c_char);

fn glutEnterGameMode() -> c_int;

fn glutLeaveGameMode();

fn glutGameModeGet(++mode: GLenum) -> c_int;

}
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};

use crate::consts::{constant, Constant};
use crate::syntax::ast::LitKind;
use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if_chain! {
            if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
            if !in_macro(assert_span)
                || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span));
            if let ExprKind::Unary(_, ref lit) = e.node;
            then {
                if let ExprKind::Lit(ref inner) = lit.node {
                    match inner.node {
                        LitKind::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(true) will be optimized out by the compiler",
                                "remove it");
                        },
                        LitKind::Bool(false) => {
                            span_help_and_lint(
                                cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                } else if let Some(bool_const) = constant(cx, cx.tables, lit) {
                    match bool_const.0 {
                        Constant::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: true) will be optimized out by the compiler",
                                "remove it");
                        },
                        Constant::Bool(false) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                }
            }
        }
    }
}
<commit_msg>Don't lint debug_assert!(false)<commit_after>use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};

use crate::consts::{constant, Constant};
use crate::syntax::ast::LitKind;
use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        let mut is_debug_assert = false;
        if_chain! {
            if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
            if !in_macro(assert_span)
                || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| {
                    is_debug_assert = true;
                    // Check that `debug_assert!` itself is not inside a macro
                    !in_macro(span)
                });
            if let ExprKind::Unary(_, ref lit) = e.node;
            then {
                if let ExprKind::Lit(ref inner) = lit.node {
                    match inner.node {
                        LitKind::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(true) will be optimized out by the compiler",
                                "remove it");
                        },
                        LitKind::Bool(false) if !is_debug_assert => {
                            span_help_and_lint(
                                cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                } else if let Some(bool_const) = constant(cx, cx.tables, lit) {
                    match bool_const.0 {
                        Constant::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: true) will be optimized out by the compiler",
                                "remove it");
                        },
                        Constant::Bool(false) if !is_debug_assert => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::util::{msb, Aligned};
use std::arch::x86_64::*;

macro_rules! satd_hbd_avx2 {
  ($(($W:expr, $H:expr)),*) => {
    $(
      paste::item! {
        #[target_feature(enable = "avx2")]
        pub(crate) unsafe extern fn [<rav1e_satd_ $W x $H _hbd_avx2>](
          src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize,
        ) -> u32 {
          // Size of hadamard transform should be 4x4 or 8x8.
          // 4x* and *x4 use 4x4 and all other use 8x8.
          // Because these are constants via the macro system,
          // the branches here will be optimized out.
          let size: usize = $W.min($H).min(8);
          let sizei = size as isize;

          let mut sum = 0u64;

          // Loop over chunks the size of the chosen transform
          for chunk_y in (0isize..$H).step_by(size) {
            for chunk_x in (0isize..$W).step_by(size) {
              let buf = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
              let input1 = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
              let input2 = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
              for y in 0..(sizei) {
                let y1 = chunk_y + y;
                for x in 0..(sizei) {
                  let x1 = chunk_x + x;
                  input1.as_mut_ptr().offset(y * sizei + x).write(src.offset(y1 * src_stride + x1).read() as i32);
                  input2.as_mut_ptr().offset(y * sizei + x).write(dst.offset(y1 * dst_stride + x1).read() as i32);
                }
              }

              // Move the difference of the transforms to a buffer
              for y in 0..(sizei) {
                if size == 4 {
                  let row_src = _mm_load_si128(input1.as_ptr().offset(y * sizei) as *const __m128i);
                  let row_dst = _mm_load_si128(input2.as_ptr().offset(y * sizei) as *const __m128i);
                  let diff = _mm_sub_epi32(row_src, row_dst);
                  _mm_store_si128(buf.as_mut_ptr().offset(y * sizei) as *mut __m128i, diff);
                } else {
                  let row_src = _mm256_load_si256(input1.as_ptr().offset(y * sizei) as *const __m256i);
                  let row_dst = _mm256_load_si256(input2.as_ptr().offset(y * sizei) as *const __m256i);
                  let diff = _mm256_sub_epi32(row_src, row_dst);
                  _mm256_store_si256(buf.as_mut_ptr().offset(y * sizei) as *mut __m256i, diff);
                }
              }

              // Perform the hadamard transform on the differences,
              // Then sum the absolute values of the transformed differences
              if size == 4 {
                hadamard4x4(buf.as_mut_ptr());
                let row1 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(0) as *const __m256i));
                let row2 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(8) as *const __m256i));
                let sum_t = _mm256_add_epi32(row1, row2);
                let mut abs = Aligned::<[u32; 8]>::uninitialized();
                _mm256_store_si256(abs.data.as_mut_ptr() as *mut __m256i, sum_t);
                sum += abs.data.iter().copied().map(|a| a as u64).sum::<u64>();
              } else {
                hadamard8x8(buf.as_mut_ptr());
                let row1 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(0) as *const __m256i));
                let row2 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(8) as *const __m256i));
                let row3 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(16) as *const __m256i));
                let row4 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(24) as *const __m256i));
                let row5 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(32) as *const __m256i));
                let row6 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(40) as *const __m256i));
                let row7 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(48) as *const __m256i));
                let row8 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(56) as *const __m256i));
                let sum1 = _mm256_add_epi32(row1, row2);
                let sum2 = _mm256_add_epi32(row3, row4);
                let sum3 = _mm256_add_epi32(row5, row6);
                let sum4 = _mm256_add_epi32(row7, row8);
                let sum5 = _mm256_add_epi32(sum1, sum2);
                let sum6 = _mm256_add_epi32(sum3, sum4);
                let sum_t = _mm256_add_epi32(sum5, sum6);
                let mut abs_sums = Aligned::<[u32; 8]>::uninitialized();
                _mm256_store_si256(abs_sums.data.as_mut_ptr() as *mut __m256i, sum_t);
                sum += abs_sums.data.iter().copied().map(|a| a as u64).sum::<u64>();
              }
            }
          }

          // Normalize the results
          let ln = msb(size as i32) as u64;
          ((sum + (1 << ln >> 1)) >> ln) as u32
        }
      }
    )*
  }
}

satd_hbd_avx2!(
  (4, 4),
  (4, 8),
  (4, 16),
  (8, 4),
  (8, 8),
  (8, 16),
  (8, 32),
  (16, 4),
  (16, 8),
  (16, 16),
  (16, 32),
  (16, 64),
  (32, 8),
  (32, 16),
  (32, 32),
  (32, 64),
  (64, 16),
  (64, 32),
  (64, 64),
  (64, 128),
  (128, 64),
  (128, 128)
);

#[inline(always)]
const fn butterfly(a: i32, b: i32) -> (i32, i32) {
  ((a + b), (a - b))
}

#[inline(always)]
#[allow(clippy::identity_op, clippy::erasing_op)]
unsafe fn hadamard4_1d(
  data: *mut i32, n: usize, stride0: usize, stride1: usize,
) {
  for i in 0..n {
    let sub = data.add(i * stride0);
    let (a0, a1) =
      butterfly(sub.add(0 * stride1).read(), sub.add(1 * stride1).read());
    let (a2, a3) =
      butterfly(sub.add(2 * stride1).read(), sub.add(3 * stride1).read());
    let (b0, b2) = butterfly(a0, a2);
    let (b1, b3) = butterfly(a1, a3);
    sub.add(0 * stride1).write(b0);
    sub.add(1 * stride1).write(b1);
    sub.add(2 * stride1).write(b2);
    sub.add(3 * stride1).write(b3);
  }
}

#[inline(always)]
#[allow(clippy::identity_op, clippy::erasing_op)]
unsafe fn hadamard8_1d(
  data: *mut i32, n: usize, stride0: usize, stride1: usize,
) {
  for i in 0..n {
    let sub = data.add(i * stride0);

    let (a0, a1) =
      butterfly(sub.add(0 * stride1).read(), sub.add(1 * stride1).read());
    let (a2, a3) =
      butterfly(sub.add(2 * stride1).read(), sub.add(3 * stride1).read());
    let (a4, a5) =
      butterfly(sub.add(4 * stride1).read(), sub.add(5 * stride1).read());
    let (a6, a7) =
      butterfly(sub.add(6 * stride1).read(), sub.add(7 * stride1).read());

    let (b0, b2) = butterfly(a0, a2);
    let (b1, b3) = butterfly(a1, a3);
    let (b4, b6) = butterfly(a4, a6);
    let (b5, b7) = butterfly(a5, a7);

    let (c0, c4) = butterfly(b0, b4);
    let (c1, c5) = butterfly(b1, b5);
    let (c2, c6) = butterfly(b2, b6);
    let (c3, c7) = butterfly(b3, b7);

    sub.add(0 * stride1).write(c0);
    sub.add(1 * stride1).write(c1);
    sub.add(2 * stride1).write(c2);
    sub.add(3 * stride1).write(c3);
    sub.add(4 * stride1).write(c4);
    sub.add(5 * stride1).write(c5);
    sub.add(6 * stride1).write(c6);
    sub.add(7 * stride1).write(c7);
  }
}

#[inline(always)]
fn hadamard2d(data: *mut i32, (w, h): (usize, usize)) {
  /*Vertical transform.*/
  let vert_func = if h == 4 { hadamard4_1d } else { hadamard8_1d };
  unsafe {
    vert_func(data, w, 1, h);
  }
  /*Horizontal transform.*/
  let horz_func = if w == 4 { hadamard4_1d } else { hadamard8_1d };
  unsafe {
    horz_func(data, h, w, 1);
  }
}

#[inline(always)]
fn hadamard4x4(data: *mut i32) {
  hadamard2d(data, (4, 4));
}

#[inline(always)]
fn hadamard8x8(data: *mut i32) {
  hadamard2d(data, (8, 8));
}
<commit_msg>Reduce compile time for hbd satd intrinsics<commit_after>use crate::util::{msb, Aligned};
use std::arch::x86_64::*;

macro_rules! satd_hbd_avx2 {
  ($(($W:expr, $H:expr)),*) => {
    $(
      paste::item! {
        #[target_feature(enable = "avx2")]
        pub(crate) unsafe extern fn [<rav1e_satd_ $W x $H _hbd_avx2>](
          src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize,
        ) -> u32 {
          // Size of hadamard transform should be 4x4 or 8x8.
          // 4x* and *x4 use 4x4 and all other use 8x8.
          // Because these are constants via the macro system,
          // the branches here will be optimized out.
          let size: usize = $W.min($H).min(8);

          let mut sum = 0u64;

          // Loop over chunks the size of the chosen transform
          for chunk_y in (0isize..$H).step_by(size) {
            for chunk_x in (0isize..$W).step_by(size) {
              let src = src.offset(chunk_y * src_stride + chunk_x);
              let dst = dst.offset(chunk_y * dst_stride + chunk_x);
              if (size == 4) {
                sum += satd_kernel_4x4_hbd_avx2(src, src_stride, dst, dst_stride);
              } else {
                sum += satd_kernel_8x8_hbd_avx2(src, src_stride, dst, dst_stride);
              }
            }
          }

          // Normalize the results
          let ln = msb(size as i32) as u64;
          ((sum + (1 << ln >> 1)) >> ln) as u32
        }
      }
    )*
  }
}

macro_rules! satd_kernel_hbd_avx2 {
  ($(($W:expr, $H:expr)),*) => {
    $(
      paste::item! {
        #[target_feature(enable = "avx2")]
        unsafe extern fn [<satd_kernel_ $W x $H _hbd_avx2>](
          src: *const u16, src_stride: isize, dst: *const u16, dst_stride: isize,
        ) -> u64 {
          // Size of hadamard kernel should be 4x4 or 8x8.
          // Because these are constants via the macro system,
          // the branches here will be optimized out.
          let size: usize = $W.min($H).min(8);
          let sizei = size as isize;

          let buf = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
          let input1 = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
          let input2 = &mut Aligned::<[i32; 8 * 8]>::uninitialized().data[..size * size];
          for y in 0..(sizei) {
            for x in 0..(sizei) {
              input1.as_mut_ptr().offset(y * sizei + x).write(src.offset(y * src_stride + x).read() as i32);
              input2.as_mut_ptr().offset(y * sizei + x).write(dst.offset(y * dst_stride + x).read() as i32);
            }
          }

          // Move the difference of the transforms to a buffer
          for y in 0..(sizei) {
            if size == 4 {
              let row_src = _mm_load_si128(input1.as_ptr().offset(y * sizei) as *const __m128i);
              let row_dst = _mm_load_si128(input2.as_ptr().offset(y * sizei) as *const __m128i);
              let diff = _mm_sub_epi32(row_src, row_dst);
              _mm_store_si128(buf.as_mut_ptr().offset(y * sizei) as *mut __m128i, diff);
            } else {
              let row_src = _mm256_load_si256(input1.as_ptr().offset(y * sizei) as *const __m256i);
              let row_dst = _mm256_load_si256(input2.as_ptr().offset(y * sizei) as *const __m256i);
              let diff = _mm256_sub_epi32(row_src, row_dst);
              _mm256_store_si256(buf.as_mut_ptr().offset(y * sizei) as *mut __m256i, diff);
            }
          }

          // Perform the hadamard transform on the differences,
          // Then sum the absolute values of the transformed differences
          if size == 4 {
            hadamard4x4(buf.as_mut_ptr());
            let row1 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(0) as *const __m256i));
            let row2 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(8) as *const __m256i));
            let sum_t = _mm256_add_epi32(row1, row2);
            let mut abs = Aligned::<[u32; 8]>::uninitialized();
            _mm256_store_si256(abs.data.as_mut_ptr() as *mut __m256i, sum_t);
            abs.data.iter().copied().map(|a| a as u64).sum::<u64>()
          } else {
            hadamard8x8(buf.as_mut_ptr());
            let row1 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(0) as *const __m256i));
            let row2 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(8) as *const __m256i));
            let row3 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(16) as *const __m256i));
            let row4 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(24) as *const __m256i));
            let row5 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(32) as *const __m256i));
            let row6 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(40) as *const __m256i));
            let row7 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(48) as *const __m256i));
            let row8 = _mm256_abs_epi32(_mm256_load_si256(buf.as_ptr().add(56) as *const __m256i));
            let sum1 = _mm256_add_epi32(row1, row2);
            let sum2 = _mm256_add_epi32(row3, row4);
            let sum3 = _mm256_add_epi32(row5, row6);
            let sum4 = _mm256_add_epi32(row7, row8);
            let sum5 = _mm256_add_epi32(sum1, sum2);
            let sum6 = _mm256_add_epi32(sum3, sum4);
            let sum_t = _mm256_add_epi32(sum5, sum6);
            let mut abs_sums = Aligned::<[u32; 8]>::uninitialized();
            _mm256_store_si256(abs_sums.data.as_mut_ptr() as *mut __m256i, sum_t);
            abs_sums.data.iter().copied().map(|a| a as u64).sum::<u64>()
          }
        }
      }
    )*
  }
}

satd_kernel_hbd_avx2!((4, 4), (8, 8));

satd_hbd_avx2!(
  (4, 4),
  (4, 8),
  (4, 16),
  (8, 4),
  (8, 8),
  (8, 16),
  (8, 32),
  (16, 4),
  (16, 8),
  (16, 16),
  (16, 32),
  (16, 64),
  (32, 8),
  (32, 16),
  (32, 32),
  (32, 64),
  (64, 16),
  (64, 32),
  (64, 64),
  (64, 128),
  (128, 64),
  (128, 128)
);

#[inline(always)]
const fn butterfly(a: i32, b: i32) -> (i32, i32) {
  ((a + b), (a - b))
}

#[inline(always)]
#[allow(clippy::identity_op, clippy::erasing_op)]
unsafe fn hadamard4_1d(
  data: *mut i32, n: usize, stride0: usize, stride1: usize,
) {
  for i in 0..n {
    let sub = data.add(i * stride0);
    let (a0, a1) =
      butterfly(sub.add(0 * stride1).read(), sub.add(1 * stride1).read());
    let (a2, a3) =
      butterfly(sub.add(2 * stride1).read(), sub.add(3 * stride1).read());
    let (b0, b2) = butterfly(a0, a2);
    let (b1, b3) = butterfly(a1, a3);
    sub.add(0 * stride1).write(b0);
    sub.add(1 * stride1).write(b1);
    sub.add(2 * stride1).write(b2);
    sub.add(3 * stride1).write(b3);
  }
}

#[inline(always)]
#[allow(clippy::identity_op, clippy::erasing_op)]
unsafe fn hadamard8_1d(
  data: *mut i32, n: usize, stride0: usize, stride1: usize,
) {
  for i in 0..n {
    let sub = data.add(i * stride0);

    let (a0, a1) =
      butterfly(sub.add(0 * stride1).read(), sub.add(1 * stride1).read());
    let (a2, a3) =
      butterfly(sub.add(2 * stride1).read(), sub.add(3 * stride1).read());
    let (a4, a5) =
      butterfly(sub.add(4 * stride1).read(), sub.add(5 * stride1).read());
    let (a6, a7) =
      butterfly(sub.add(6 * stride1).read(), sub.add(7 * stride1).read());

    let (b0, b2) = butterfly(a0, a2);
    let (b1, b3) = butterfly(a1, a3);
    let (b4, b6) = butterfly(a4, a6);
    let (b5, b7) = butterfly(a5, a7);

    let (c0, c4) = butterfly(b0, b4);
    let (c1, c5) = butterfly(b1, b5);
    let (c2, c6) = butterfly(b2, b6);
    let (c3, c7) = butterfly(b3, b7);

    sub.add(0 * stride1).write(c0);
    sub.add(1 * stride1).write(c1);
    sub.add(2 * stride1).write(c2);
    sub.add(3 * stride1).write(c3);
    sub.add(4 * stride1).write(c4);
    sub.add(5 * stride1).write(c5);
    sub.add(6 * stride1).write(c6);
    sub.add(7 * stride1).write(c7);
  }
}

#[inline(always)]
fn hadamard2d(data: *mut i32, (w, h): (usize, usize)) {
  /*Vertical transform.*/
  let vert_func = if h == 4 { hadamard4_1d } else { hadamard8_1d };
  unsafe {
    vert_func(data, w, 1, h);
  }
  /*Horizontal transform.*/
  let horz_func = if w == 4 { hadamard4_1d } else { hadamard8_1d };
  unsafe {
    horz_func(data, h, w, 1);
  }
}

#[inline(always)]
fn hadamard4x4(data: *mut i32) {
  hadamard2d(data, (4, 4));
}

#[inline(always)]
fn hadamard8x8(data: *mut i32) {
  hadamard2d(data, (8, 8));
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

#[cfg(any(target_os = "windows", test))]
mod wtf8;

use std::path::PathBuf;

/// Interprets given bytes as an operating system path.
///
/// On Linux, the path is constructed from bytes as is since system paths can
/// be made of arbitrary sequence of bytes.
///
/// On Windows, the [WTF-8][wtf8] encoding is used.
///
/// [wtf8]: https://simonsapin.github.io/wtf-8
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
///
/// let path = rrg_proto::path::from_bytes(b"foo/bar/baz".to_vec()).unwrap();
///
/// let mut components = path.components()
///     .map(|component| component.as_os_str());
///
/// assert_eq!(components.next(), Some(OsStr::new("foo")));
/// assert_eq!(components.next(), Some(OsStr::new("bar")));
/// assert_eq!(components.next(), Some(OsStr::new("baz")));
/// assert_eq!(components.next(), None);
/// ```
pub fn from_bytes(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    from_bytes_impl(bytes)
}

/// Serializes given path to a byte sequence.
///
/// On Linux, the path is emitted as is since system paths can consist of
/// arbitrary bytes.
///
/// On Windows, the [WTF-8][wtf8] encoding is used.
///
/// [wtf8]: https://simonsapin.github.io/wtf-8
///
/// # Examples
///
/// ```
/// use std::path::PathBuf;
///
/// let path = PathBuf::from("foo/bar/baz");
/// assert_eq!(rrg_proto::path::into_bytes(path), b"foo/bar/baz");
/// ```
pub fn into_bytes(path: PathBuf) -> Vec<u8> {
    into_bytes_impl(path)
}

#[cfg(target_family = "unix")]
fn from_bytes_impl(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    use std::os::unix::ffi::OsStringExt as _;
    Ok(std::ffi::OsString::from_vec(bytes).into())
}

#[cfg(target_family = "windows")]
fn from_bytes_impl(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    let bytes_u16 = wtf8::into_ill_formed_utf16(bytes)?;

    use std::os::windows::ffi::OsStringExt as _;
    Ok(std::ffi::OsString::from_wide(&bytes_u16).into())
}

#[cfg(target_family = "unix")]
fn into_bytes_impl(path: PathBuf) -> Vec<u8> {
    use std::os::unix::ffi::OsStringExt as _;
    std::ffi::OsString::from(path).into_vec()
}

#[cfg(target_family = "windows")]
fn into_bytes_impl(path: PathBuf) -> Vec<u8> {
    let string = std::ffi::OsString::from(path);

    use std::os::windows::ffi::OsStrExt as _;
    wtf8::from_ill_formed_utf16(string.as_os_str().encode_wide())
}

#[derive(Debug, PartialEq, Eq)]
pub struct ParseError {
    kind: ParseErrorKind,
}

impl std::fmt::Display for ParseError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        #[cfg(target_family = "unix")]
        let _ = fmt; // Unused.

        match self.kind {
            #[cfg(target_family = "windows")]
            ParseErrorKind::Wtf8(ref error) => write!(fmt, "{}", error),
        }
    }
}

impl std::error::Error for ParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self.kind {
            #[cfg(target_family = "windows")]
            ParseErrorKind::Wtf8(ref error) => Some(error),
        }
    }
}

#[cfg(target_family = "windows")]
impl From<wtf8::ParseError> for ParseError {

    fn from(error: wtf8::ParseError) -> ParseError {
        ParseError {
            kind: ParseErrorKind::Wtf8(error),
        }
    }
}

#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
enum ParseErrorKind {
    #[cfg(target_family = "windows")]
    Wtf8(wtf8::ParseError),
}
<commit_msg>Add simple docs for path parsing errors.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

#[cfg(any(target_os = "windows", test))]
mod wtf8;

use std::path::PathBuf;

/// Interprets given bytes as an operating system path.
///
/// On Linux, the path is constructed from bytes as is since system paths can
/// be made of arbitrary sequence of bytes.
///
/// On Windows, the [WTF-8][wtf8] encoding is used.
///
/// [wtf8]: https://simonsapin.github.io/wtf-8
///
/// # Examples
///
/// ```
/// use std::ffi::OsStr;
///
/// let path = rrg_proto::path::from_bytes(b"foo/bar/baz".to_vec()).unwrap();
///
/// let mut components = path.components()
///     .map(|component| component.as_os_str());
///
/// assert_eq!(components.next(), Some(OsStr::new("foo")));
/// assert_eq!(components.next(), Some(OsStr::new("bar")));
/// assert_eq!(components.next(), Some(OsStr::new("baz")));
/// assert_eq!(components.next(), None);
/// ```
pub fn from_bytes(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    from_bytes_impl(bytes)
}

/// Serializes given path to a byte sequence.
///
/// On Linux, the path is emitted as is since system paths can consist of
/// arbitrary bytes.
///
/// On Windows, the [WTF-8][wtf8] encoding is used.
///
/// [wtf8]: https://simonsapin.github.io/wtf-8
///
/// # Examples
///
/// ```
/// use std::path::PathBuf;
///
/// let path = PathBuf::from("foo/bar/baz");
/// assert_eq!(rrg_proto::path::into_bytes(path), b"foo/bar/baz");
/// ```
pub fn into_bytes(path: PathBuf) -> Vec<u8> {
    into_bytes_impl(path)
}

#[cfg(target_family = "unix")]
fn from_bytes_impl(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    use std::os::unix::ffi::OsStringExt as _;
    Ok(std::ffi::OsString::from_vec(bytes).into())
}

#[cfg(target_family = "windows")]
fn from_bytes_impl(bytes: Vec<u8>) -> Result<PathBuf, ParseError> {
    let bytes_u16 = wtf8::into_ill_formed_utf16(bytes)?;

    use std::os::windows::ffi::OsStringExt as _;
    Ok(std::ffi::OsString::from_wide(&bytes_u16).into())
}

#[cfg(target_family = "unix")]
fn into_bytes_impl(path: PathBuf) -> Vec<u8> {
    use std::os::unix::ffi::OsStringExt as _;
    std::ffi::OsString::from(path).into_vec()
}

#[cfg(target_family = "windows")]
fn into_bytes_impl(path: PathBuf) -> Vec<u8> {
    let string = std::ffi::OsString::from(path);

    use std::os::windows::ffi::OsStrExt as _;
    wtf8::from_ill_formed_utf16(string.as_os_str().encode_wide())
}

/// A type representing errors that can occur when parsing paths.
#[derive(Debug, PartialEq, Eq)]
pub struct ParseError {
    /// Detailed information about the error.
    kind: ParseErrorKind,
}

impl std::fmt::Display for ParseError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        #[cfg(target_family = "unix")]
        let _ = fmt; // Unused.

        match self.kind {
            #[cfg(target_family = "windows")]
            ParseErrorKind::Wtf8(ref error) => write!(fmt, "{}", error),
        }
    }
}

impl std::error::Error for ParseError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self.kind {
            #[cfg(target_family = "windows")]
            ParseErrorKind::Wtf8(ref error) => Some(error),
        }
    }
}

#[cfg(target_family = "windows")]
impl From<wtf8::ParseError> for ParseError {

    fn from(error: wtf8::ParseError) -> ParseError {
        ParseError {
            kind: ParseErrorKind::Wtf8(error),
        }
    }
}

/// A type enumerating all possible error kinds of path parsing errors.
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
enum ParseErrorKind {
    /// Parsing failed because of issues with decoding a WTF-8 string.
    #[cfg(target_family = "windows")]
    Wtf8(wtf8::ParseError),
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate exonum;
extern crate exonum_testkit;
#[macro_use]
extern crate pretty_assertions;

use exonum::{api::{private::NodeInfo, public::HealthCheckInfo},
             helpers::user_agent,
             messages::PROTOCOL_MAJOR_VERSION};
use exonum_testkit::{ApiKind, TestKitBuilder};

#[test]
fn test_healthcheck_connectivity_false() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: HealthCheckInfo = api.get(ApiKind::System, "v1/healthcheck");
    let expected = HealthCheckInfo {
        connectivity: false,
    };
    assert_eq!(info, expected);
}

#[test]
fn test_user_agent_info() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: String = api.get(ApiKind::System, "v1/user_agent");
    let expected = user_agent::get();
    assert_eq!(info, expected);
}

#[test]
fn test_network() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: NodeInfo = api.get_private(ApiKind::System, "/v1/network");

    assert_eq!(
        info.core_version,
        option_env!("CARGO_PKG_VERSION").map(|ver| ver.to_owned())
    );
    assert_eq!(info.protocol_version, PROTOCOL_MAJOR_VERSION);
    assert!(info.services.is_empty());
}
<commit_msg>Service metainfo endpoint [ECR-792] (#719)<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate exonum;
extern crate exonum_testkit;
#[macro_use]
extern crate pretty_assertions;

use exonum::{api::{private::NodeInfo, public::HealthCheckInfo},
             helpers::user_agent,
             messages::PROTOCOL_MAJOR_VERSION};
use exonum_testkit::{ApiKind, TestKitBuilder};

#[test]
fn test_healthcheck_connectivity_false() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: HealthCheckInfo = api.get(ApiKind::System, "v1/healthcheck");
    let expected = HealthCheckInfo {
        connectivity: false,
    };
    assert_eq!(info, expected);
}

#[test]
fn test_user_agent_info() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: String = api.get(ApiKind::System, "v1/user_agent");
    let expected = user_agent::get();
    assert_eq!(info, expected);
}

#[test]
fn test_network() {
    let testkit = TestKitBuilder::validator().with_validators(2).create();
    let api = testkit.api();
    let info: NodeInfo = api.get_private(ApiKind::System, "/v1/network");

    assert!(info.core_version.is_some());
    assert_eq!(info.protocol_version, PROTOCOL_MAJOR_VERSION);
    assert!(info.services.is_empty());
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Unix-specific extensions to primitives in the `std::process` module.

#![unstable(feature = "thread_extensions", issue = "29791")]

#[allow(deprecated)]
use os::unix::raw::pthread_t;
use sys_common::{AsInner, IntoInner};
use thread::JoinHandle;

#[unstable(feature = "thread_extensions", issue = "29791")]
#[allow(deprecated)]
pub type RawPthread = pthread_t;

/// Unix-specific extensions to `std::thread::JoinHandle`
#[unstable(feature = "thread_extensions", issue = "29791")]
pub trait JoinHandleExt {
    /// Extracts the raw pthread_t without taking ownership
    fn as_pthread_t(&self) -> RawPthread;
    /// Consumes the thread, returning the raw pthread_t
    ///
    /// This function **transfers ownership** of the underlying pthread_t to
    /// the caller. Callers are then the unique owners of the pthread_t and
    /// must either detech or join the pthread_t once it's no longer needed.
    fn into_pthread_t(self) -> RawPthread;
}

#[unstable(feature = "thread_extensions", issue = "29791")]
impl<T> JoinHandleExt for JoinHandle<T> {
    fn as_pthread_t(&self) -> RawPthread {
        self.as_inner().id() as RawPthread
    }
    fn into_pthread_t(self) -> RawPthread {
        self.into_inner().into_id() as RawPthread
    }
}
<commit_msg>Rollup merge of #32654 - tbu-:pr_doc_joinhandleext, r=sfackler<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Unix-specific extensions to primitives in the `std::process` module.

#![unstable(feature = "thread_extensions", issue = "29791")]

#[allow(deprecated)]
use os::unix::raw::pthread_t;
use sys_common::{AsInner, IntoInner};
use thread::JoinHandle;

#[unstable(feature = "thread_extensions", issue = "29791")]
#[allow(deprecated)]
pub type RawPthread = pthread_t;

/// Unix-specific extensions to `std::thread::JoinHandle`
#[unstable(feature = "thread_extensions", issue = "29791")]
pub trait JoinHandleExt {
    /// Extracts the raw pthread_t without taking ownership
    fn as_pthread_t(&self) -> RawPthread;
    /// Consumes the thread, returning the raw pthread_t
    ///
    /// This function **transfers ownership** of the underlying pthread_t to
    /// the caller. Callers are then the unique owners of the pthread_t and
    /// must either detach or join the pthread_t once it's no longer needed.
    fn into_pthread_t(self) -> RawPthread;
}

#[unstable(feature = "thread_extensions", issue = "29791")]
impl<T> JoinHandleExt for JoinHandle<T> {
    fn as_pthread_t(&self) -> RawPthread {
        self.as_inner().id() as RawPthread
    }
    fn into_pthread_t(self) -> RawPthread {
        self.into_inner().into_id() as RawPthread
    }
}
<|endoftext|>