<commit_before>use std::collections::VecDeque;
use std::fmt;
use term;
use time::precise_time_s;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<u64>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// How many seconds have elapsed since the download started
    seconds_elapsed: u32,
    /// The terminal we write the information to.
    term: Box<term::StdoutTerminal>,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            seconds_elapsed: 0,
            last_sec: None,
            term: term::stdout().expect("Failed to open terminal"),
        }
    }
    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len);
    }
    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        match self.last_sec {
            None => self.last_sec = Some(precise_time_s()),
            Some(start) => {
                let elapsed = precise_time_s() - start;
                if elapsed >= 1.0 {
                    self.seconds_elapsed += 1;

                    self.display();
                    self.last_sec = Some(precise_time_s());
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs.push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        let _ = writeln!(&mut self.term, "");
        self.last_sec = None;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        let total_h = HumanReadable(self.total_downloaded as f64);
        let sum = self.downloaded_last_few_secs
                      .iter()
                      .fold(0usize, |a, &v| a + v);
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 {
            (sum / len) as u64
        } else {
            0
        };
        let speed_h = HumanReadable(speed as f64);

        match self.content_len {
            Some(content_len) => {
                use std::borrow::Cow;

                let percent = (self.total_downloaded as f64 / content_len as f64) * 100.;
                let content_len_h = HumanReadable(content_len as f64);
                let remaining = content_len - self.total_downloaded as u64;
                let eta = if speed > 0 {
                    Cow::Owned(format!("{}s", remaining / speed))
                } else {
                    Cow::Borrowed("Unknown")
                };
                let _ = write!(&mut self.term,
                               "{} / {} ({:.2}%) ~{}/s ETA: {}",
                               total_h,
                               content_len_h,
                               percent,
                               speed_h,
                               eta);
            }
            None => {
                let _ = write!(&mut self.term, "Total: {} Speed: {}/s", total_h, speed_h);
            }
        }
        // delete_line() doesn't seem to clear the line properly.
        // Instead, let's just print some whitespace to clear it.
        let _ = write!(&mut self.term, "                ");
        let _ = self.term.flush();
        let _ = self.term.carriage_return();
    }
}

/// Human readable representation of data size in bytes
struct HumanReadable<T>(T);

impl<T: Into<f64> + Clone> fmt::Display for HumanReadable<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const KIB: f64 = 1024.0;
        const MIB: f64 = 1048576.0;
        let size: f64 = self.0.clone().into();

        if size >= MIB {
            write!(f, "{:.2} MiB", size / MIB)
        } else if size >= KIB {
            write!(f, "{:.2} KiB", size / KIB)
        } else {
            write!(f, "{} B", size)
        }
    }
}
<commit_msg>Remove "approx." sigil from download speed info<commit_after>use std::collections::VecDeque;
use std::fmt;
use term;
use time::precise_time_s;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<u64>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// How many seconds have elapsed since the download started
    seconds_elapsed: u32,
    /// The terminal we write the information to.
    term: Box<term::StdoutTerminal>,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            seconds_elapsed: 0,
            last_sec: None,
            term: term::stdout().expect("Failed to open terminal"),
        }
    }
    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len);
    }
    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        match self.last_sec {
            None => self.last_sec = Some(precise_time_s()),
            Some(start) => {
                let elapsed = precise_time_s() - start;
                if elapsed >= 1.0 {
                    self.seconds_elapsed += 1;

                    self.display();
                    self.last_sec = Some(precise_time_s());
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs.push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        let _ = writeln!(&mut self.term, "");
        self.last_sec = None;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        let total_h = HumanReadable(self.total_downloaded as f64);
        let sum = self.downloaded_last_few_secs
                      .iter()
                      .fold(0usize, |a, &v| a + v);
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 {
            (sum / len) as u64
        } else {
            0
        };
        let speed_h = HumanReadable(speed as f64);

        match self.content_len {
            Some(content_len) => {
                use std::borrow::Cow;

                let percent = (self.total_downloaded as f64 / content_len as f64) * 100.;
                let content_len_h = HumanReadable(content_len as f64);
                let remaining = content_len - self.total_downloaded as u64;
                let eta = if speed > 0 {
                    Cow::Owned(format!("{}s", remaining / speed))
                } else {
                    Cow::Borrowed("Unknown")
                };
                let _ = write!(&mut self.term,
                               "{} / {} ({:.2}%) {}/s ETA: {}",
                               total_h,
                               content_len_h,
                               percent,
                               speed_h,
                               eta);
            }
            None => {
                let _ = write!(&mut self.term, "Total: {} Speed: {}/s", total_h, speed_h);
            }
        }
        // delete_line() doesn't seem to clear the line properly.
        // Instead, let's just print some whitespace to clear it.
        let _ = write!(&mut self.term, "                ");
        let _ = self.term.flush();
        let _ = self.term.carriage_return();
    }
}

/// Human readable representation of data size in bytes
struct HumanReadable<T>(T);

impl<T: Into<f64> + Clone> fmt::Display for HumanReadable<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        const KIB: f64 = 1024.0;
        const MIB: f64 = 1048576.0;
        let size: f64 = self.0.clone().into();

        if size >= MIB {
            write!(f, "{:.2} MiB", size / MIB)
        } else if size >= KIB {
            write!(f, "{:.2} KiB", size / KIB)
        } else {
            write!(f, "{} B", size)
        }
    }
}
<|endoftext|>


<commit_before>use impl_prelude::*;
use lapack::c::{sgeqrf, sorgqr};
use std::fmt::Debug;

/// Error for QR-based computations.
#[derive(Debug, Clone)]
pub enum QRError {
    /// The layout of the matrix is not compatible
    BadLayout,

    /// The dimensions of the raw qr and tau don't match
    InconsistentDimensions,

    /// Implementation error, please submit as bug.
    IllegalParameter(i32),
}

/// Enum for muliplication by Q.
#[repr(u8)]
#[derive(Debug, Clone)]
pub enum QRMultiply {
    /// Compute Q * A for the input matrix A
    Left = b'L',

    /// Compute A * Q for the input matrix A
    Right = b'R',
}

/// Representation of the components Q, R of the factorization of
/// matrix A.
#[derive(Debug)]
pub struct QRFactors<T: QR> {
    mat: Array<T, Ix2>,
    tau: Vec<T>,

    /// Number of rows in the original matrix
    pub m: usize,

    /// Number of columns in the original matrix
    pub n: usize,
}

impl<T: QR> QRFactors<T> {
    /// Create a `QRFactors` object from the output of the LAPACKE
    /// functions.
    fn from_raw<Matrix>(mat: Matrix, tau: Vec<T>) -> Result<QRFactors<T>, QRError>
        where Matrix: Into<Array<T, Ix2>>
    {
        let mut ma = mat.into();
        let (m, n) = ma.dim();

        if slice_and_layout_mut(&mut ma).is_none() {
            return Err(QRError::BadLayout);
        }

        Ok(QRFactors {
            mat: ma,
            tau: tau,
            m: m,
            n: n,
        })
    }

    pub fn compute<D1: Data<Elem=T>>(mat: &ArrayBase<D1, Ix2>)
                                     -> Result<QRFactors<T>, QRError> {
        QR::compute(mat)
    }

    // /// Return `A * Q`, for the `Q` stored internally.
    // pub fn left_multiply_by_q<D1: Data<Elem=T>>(&self, a: &ArrayBase<D1, Ix2>)
    //                                             -> Result<Array<T, Ix2>, QRError> {
    //     QR::multiply_by_q(&self.mat, &self.tau, a, QRMultiply::Left)
    // }

    // /// Return `A * Q`, for the `Q` stored internally.
    // pub fn right_multiply_by_q<D1: Data<Elem=T>>(&self, a: &ArrayBase<D1, Ix2>)
    //                                              -> Result<Array<T, Ix2>, QRError> {
    //     QR::multiply_by_q(&self.mat, &self.tau, a, QRMultiply::Right)
    // }

    /// Return the first `k` columns of the matrix Q of the QR
    /// factorization.
    ///
    /// `Q` is generated such that the columns of `Q` form an
    /// orthogonal basis for the first `k` columns of `A`.
    ///
    /// When `k` is None, compute enough columns (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn qk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        QR::compute_q(&self.mat, &self.tau, kr.unwrap_or(cmp::min(self.m, self.n)))
    }

    /// Return the `m` by `min(m, n)` matrix `Q`.
    ///
    /// Equivalent to `self.qk(None)`.
    ///
    /// `self.q()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn q(&self) -> Result<Array<T, Ix2>, QRError> {
        self.qk(None)
    }

    /// Return the first 'k' rows of the matrix R of the QR
    /// factorization.
    ///
    /// When `k` is None, compute enough rows (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn rk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        let p = kr.unwrap_or(cmp::min(self.m, self.n));
        QR::compute_r(&self.mat, p)
    }

    /// Return the first `min(m, n)` by `n` matrix R of the QR
    /// factorization.
    ///
    /// Equivalent to `self::rk(None)`.
    ///
    /// `self.r()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn r(&self) -> Result<Array<T, Ix2>, QRError> {
        self.rk(None)
    }
}

/// Trait defined on scalars to support QR-factorization.
pub trait QR: Sized + Clone + Debug {
    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    ///
    /// Similar to `compute`, but consumes the input.
    fn compute_into(a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError>;

    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    fn compute<D1: Data>(a: &ArrayBase<D1, Ix2>) -> Result<QRFactors<Self>, QRError>
        where D1: Data<Elem = Self>
    {
        Self::compute_into(a.to_owned())
    }

    /// multiply an input matrix by `Q`.
    ///
    /// Not intended to be used by end-users.  `side` indicates
    /// whether to pre-or-post-multiply the input by `Q`.
    // fn multiply_by_q<D1, D2>(mat: &ArrayBase<D1, Ix2>,
    //                          tau: &[Self],
    //                          a: &ArrayBase<D2, Ix2>,
    //                          mult: QRMultiply)
    //                   -> Result<Array<Self, Ix2>, QRError>
    //     where D1: Data<Elem = Self>,
    //           D2: Data<Elem = Self>;

    /// Compute Q from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;

    /// Compute R from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;
}

impl QR for f32 {
    fn compute_into(mut a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError> {
        let dim = a.dim();

        let (info, tau) = {
            let (mut slice, layout, lda) = match slice_and_layout_mut(&mut a) {
                None => return Err(QRError::BadLayout),
                Some(x) => x,
            };

            let mut tau = Vec::new();
            tau.resize(cmp::min(dim.0, dim.1), 0.0);

            // workspace query
            (sgeqrf(layout,
                    dim.0 as i32,
                    dim.1 as i32,
                    &mut slice,
                    lda as i32,
                    &mut tau),
             tau)
        };

        println!("{:?}\n {:?}\n", a, tau);

        if info == 0 {
            QRFactors::from_raw(a, tau)
        } else if info < 0 {
            Err(QRError::IllegalParameter(-info))
        } else {
            unreachable!();
        }
    }

    // fn multiply_by_q<D1, D2>(a: &ArrayBase<D1, Ix2>,
    //                          tau: &[Self],
    //                          c: &ArrayBase<D2, Ix2>,
    //                          mult: QRMultiply)
    //                   -> Result<Array<Self, Ix2>, QRError>
    //     where D1: Data<Elem = Self>,
    //           D2: Data<Elem = Self>
    // {
    //     let (m, n) = a.dim();
    //     let (cm, cn) = c.dim();

    //     let result_dim = match mult {
    //         QRMultiply::Left => cm == n
    //         QRMultiply::Right => {
    //             if cn == m {
    //                 (cm, n)

    //     };

    //     if !matching_dim {
    //         return Err(QRError::InconsistentDimensions);
    //     }

    //     let (slice, layout, lda) = match slice_and_layout(&a) {
    //         None => return Err(QRError::BadLayout),
    //         Some(fwd) => fwd,
    //     };

    //     let mut c_result = matrix_with_layout(c.dim(), layout);

    //     let info = {
    //         let (c_slice, ldc) = match slice_and_layout_mut(&mut c_result) {
    //             None => unreachable!(),
    //             Some((slice, _, ldc)) => (slice, ldc),
    //         };

    //         sormqr(layout,
    //                mult as u8,
    //                b'N',
    //                cm as i32,
    //                cn as i32,
    //                tau.len() as i32,
    //                slice,
    //                lda as i32,
    //                tau,
    //                c_slice,
    //                ldc as i32)
    //     };

    //     if info == 0 {
    //         Ok(c_result)
    //     } else if info < 0 {
    //         Err(QRError::IllegalParameter(-info))
    //     } else {
    //         unreachable!();
    //     }
    // }

    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>
    {

        let (m, n) = mat.dim();
        if k > m {
            return Err(QRError::InconsistentDimensions);
        }

        // Initialize q with the
        let mut q = mat.slice(s![.., ..k as isize]).to_owned();

        let info = {
            let (slice, layout, ldq) = match slice_and_layout_mut(&mut q) {
                None => unreachable!(),
                Some(fwd) => fwd,
            };

            sorgqr(layout,
                   m as i32,
                   k as i32,
                   cmp::min(k, n) as i32,
                   slice,
                   ldq as i32,
                   tau)
        };
        if info == 0 {
            Ok(q)
        } else {
            Err(QRError::IllegalParameter(-info))
        }
    }

    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>
    {
        let (m, n) = mat.dim();

        let nn = cmp::min(m, n);
        if k > nn {
            return Err(QRError::InconsistentDimensions);
        }

        let mut r = Array::zeros((k as usize, n));

        // Copy the upper triangular/trapezoidal part of the matrix to
        // R.
        r.slice_mut(s![..k as isize, ..]).assign(&mat.slice(s![..k as isize, ..]));

        // Replace zeros below the diagonal.
        for (i, mut row) in r.outer_iter_mut().enumerate().take(nn as usize) {
            row.slice_mut(s![..i as isize]).assign_scalar(&0.0);
        }

        Ok(r)
    }
}
<commit_msg>feat(qr) add Magnitude trait to QR<commit_after>use impl_prelude::*;
use lapack::c::{sgeqrf, sorgqr};
use std::fmt::Debug;
use types::Magnitude;

/// Error for QR-based computations.
#[derive(Debug, Clone)]
pub enum QRError {
    /// The layout of the matrix is not compatible
    BadLayout,

    /// The dimensions of the raw qr and tau don't match
    InconsistentDimensions,

    /// Implementation error, please submit as bug.
    IllegalParameter(i32),
}

/// Enum for muliplication by Q.
#[repr(u8)]
#[derive(Debug, Clone)]
pub enum QRMultiply {
    /// Compute Q * A for the input matrix A
    Left = b'L',

    /// Compute A * Q for the input matrix A
    Right = b'R',
}

/// Representation of the components Q, R of the factorization of
/// matrix A.
#[derive(Debug)]
pub struct QRFactors<T: QR> {
    mat: Array<T, Ix2>,
    tau: Vec<T>,

    /// Number of rows in the original matrix
    pub m: usize,

    /// Number of columns in the original matrix
    pub n: usize,
}

impl<T: QR> QRFactors<T> {
    /// Create a `QRFactors` object from the output of the LAPACKE
    /// functions.
    fn from_raw<Matrix>(mat: Matrix, tau: Vec<T>) -> Result<QRFactors<T>, QRError>
        where Matrix: Into<Array<T, Ix2>>
    {
        let mut ma = mat.into();
        let (m, n) = ma.dim();

        if slice_and_layout_mut(&mut ma).is_none() {
            return Err(QRError::BadLayout);
        }

        Ok(QRFactors {
            mat: ma,
            tau: tau,
            m: m,
            n: n,
        })
    }

    pub fn compute<D1: Data<Elem=T>>(mat: &ArrayBase<D1, Ix2>)
                                     -> Result<QRFactors<T>, QRError> {
        QR::compute(mat)
    }

    // /// Return `A * Q`, for the `Q` stored internally.
    // pub fn left_multiply_by_q<D1: Data<Elem=T>>(&self, a: &ArrayBase<D1, Ix2>)
    //                                             -> Result<Array<T, Ix2>, QRError> {
    //     QR::multiply_by_q(&self.mat, &self.tau, a, QRMultiply::Left)
    // }

    // /// Return `A * Q`, for the `Q` stored internally.
    // pub fn right_multiply_by_q<D1: Data<Elem=T>>(&self, a: &ArrayBase<D1, Ix2>)
    //                                              -> Result<Array<T, Ix2>, QRError> {
    //     QR::multiply_by_q(&self.mat, &self.tau, a, QRMultiply::Right)
    // }

    /// Return the first `k` columns of the matrix Q of the QR
    /// factorization.
    ///
    /// `Q` is generated such that the columns of `Q` form an
    /// orthogonal basis for the first `k` columns of `A`.
    ///
    /// When `k` is None, compute enough columns (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn qk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        QR::compute_q(&self.mat, &self.tau, kr.unwrap_or(cmp::min(self.m, self.n)))
    }

    /// Return the `m` by `min(m, n)` matrix `Q`.
    ///
    /// Equivalent to `self.qk(None)`.
    ///
    /// `self.q()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn q(&self) -> Result<Array<T, Ix2>, QRError> {
        self.qk(None)
    }

    /// Return the first 'k' rows of the matrix R of the QR
    /// factorization.
    ///
    /// When `k` is None, compute enough rows (`min(m, n)`) to
    /// faithfully recreate the original matrix A.
    pub fn rk<K: Into<Option<usize>>>(&self, k: K) -> Result<Array<T, Ix2>, QRError> {
        let kr = k.into();
        let p = kr.unwrap_or(cmp::min(self.m, self.n));
        QR::compute_r(&self.mat, p)
    }

    /// Return the first `min(m, n)` by `n` matrix R of the QR
    /// factorization.
    ///
    /// Equivalent to `self::rk(None)`.
    ///
    /// `self.r()` is large enough so that `&self.q() * &self.r()`
    /// will faithfully reproduce the original matrix `A`.
    #[inline]
    pub fn r(&self) -> Result<Array<T, Ix2>, QRError> {
        self.rk(None)
    }
}

/// Trait defined on scalars to support QR-factorization.
pub trait QR: Sized + Clone + Magnitude + Debug {
    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    ///
    /// Similar to `compute`, but consumes the input.
    fn compute_into(a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError>;

    /// Return a `QRFactors` structure, containing the QR
    /// factorization of the input matrix `A`.
    fn compute<D1: Data>(a: &ArrayBase<D1, Ix2>) -> Result<QRFactors<Self>, QRError>
        where D1: Data<Elem = Self>
    {
        Self::compute_into(a.to_owned())
    }

    /// multiply an input matrix by `Q`.
    ///
    /// Not intended to be used by end-users.  `side` indicates
    /// whether to pre-or-post-multiply the input by `Q`.
    // fn multiply_by_q<D1, D2>(mat: &ArrayBase<D1, Ix2>,
    //                          tau: &[Self],
    //                          a: &ArrayBase<D2, Ix2>,
    //                          mult: QRMultiply)
    //                   -> Result<Array<Self, Ix2>, QRError>
    //     where D1: Data<Elem = Self>,
    //           D2: Data<Elem = Self>;

    /// Compute Q from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;

    /// Compute R from raw parts.
    ///
    /// Not intended to be used by end-users.
    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>;
}

impl QR for f32 {
    fn compute_into(mut a: Array<Self, Ix2>) -> Result<QRFactors<Self>, QRError> {
        let dim = a.dim();

        let (info, tau) = {
            let (mut slice, layout, lda) = match slice_and_layout_mut(&mut a) {
                None => return Err(QRError::BadLayout),
                Some(x) => x,
            };

            let mut tau = Vec::new();
            tau.resize(cmp::min(dim.0, dim.1), 0.0);

            // workspace query
            (sgeqrf(layout,
                    dim.0 as i32,
                    dim.1 as i32,
                    &mut slice,
                    lda as i32,
                    &mut tau),
             tau)
        };

        println!("{:?}\n {:?}\n", a, tau);

        if info == 0 {
            QRFactors::from_raw(a, tau)
        } else if info < 0 {
            Err(QRError::IllegalParameter(-info))
        } else {
            unreachable!();
        }
    }

    // fn multiply_by_q<D1, D2>(a: &ArrayBase<D1, Ix2>,
    //                          tau: &[Self],
    //                          c: &ArrayBase<D2, Ix2>,
    //                          mult: QRMultiply)
    //                   -> Result<Array<Self, Ix2>, QRError>
    //     where D1: Data<Elem = Self>,
    //           D2: Data<Elem = Self>
    // {
    //     let (m, n) = a.dim();
    //     let (cm, cn) = c.dim();

    //     let result_dim = match mult {
    //         QRMultiply::Left => cm == n
    //         QRMultiply::Right => {
    //             if cn == m {
    //                 (cm, n)

    //     };

    //     if !matching_dim {
    //         return Err(QRError::InconsistentDimensions);
    //     }

    //     let (slice, layout, lda) = match slice_and_layout(&a) {
    //         None => return Err(QRError::BadLayout),
    //         Some(fwd) => fwd,
    //     };

    //     let mut c_result = matrix_with_layout(c.dim(), layout);

    //     let info = {
    //         let (c_slice, ldc) = match slice_and_layout_mut(&mut c_result) {
    //             None => unreachable!(),
    //             Some((slice, _, ldc)) => (slice, ldc),
    //         };

    //         sormqr(layout,
    //                mult as u8,
    //                b'N',
    //                cm as i32,
    //                cn as i32,
    //                tau.len() as i32,
    //                slice,
    //                lda as i32,
    //                tau,
    //                c_slice,
    //                ldc as i32)
    //     };

    //     if info == 0 {
    //         Ok(c_result)
    //     } else if info < 0 {
    //         Err(QRError::IllegalParameter(-info))
    //     } else {
    //         unreachable!();
    //     }
    // }

    fn compute_q<D1>(mat: &ArrayBase<D1, Ix2>,
                     tau: &[Self],
                     k: usize)
                     -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>
    {

        let (m, n) = mat.dim();
        if k > m {
            return Err(QRError::InconsistentDimensions);
        }

        // Initialize q with the
        let mut q = mat.slice(s![.., ..k as isize]).to_owned();

        let info = {
            let (slice, layout, ldq) = match slice_and_layout_mut(&mut q) {
                None => unreachable!(),
                Some(fwd) => fwd,
            };

            sorgqr(layout,
                   m as i32,
                   k as i32,
                   cmp::min(k, n) as i32,
                   slice,
                   ldq as i32,
                   tau)
        };
        if info == 0 {
            Ok(q)
        } else {
            Err(QRError::IllegalParameter(-info))
        }
    }

    fn compute_r<D1>(mat: &ArrayBase<D1, Ix2>, k: usize) -> Result<Array<Self, Ix2>, QRError>
        where D1: Data<Elem = Self>
    {
        let (m, n) = mat.dim();

        let nn = cmp::min(m, n);
        if k > nn {
            return Err(QRError::InconsistentDimensions);
        }

        let mut r = Array::zeros((k as usize, n));

        // Copy the upper triangular/trapezoidal part of the matrix to
        // R.
        r.slice_mut(s![..k as isize, ..]).assign(&mat.slice(s![..k as isize, ..]));

        // Replace zeros below the diagonal.
        for (i, mut row) in r.outer_iter_mut().enumerate().take(nn as usize) {
            row.slice_mut(s![..i as isize]).assign_scalar(&0.0);
        }

        Ok(r)
    }
}
<|endoftext|>


<commit_before>/*

Idea: provide functions for 'exhaustive' and 'random' modification of vecs.

  two functions, "return all edits" and "return a random edit" <-- leaning toward this model
    or
  two functions, "return the number of possible edits" and "return edit #n"

It would be nice if this could be data-driven, so the two functions could share information:
  type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di);
  const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
https://github.com/graydon/rust/issues/570

vec_edits is not an iter because iters might go away.

*/

use std;
import std::vec;
import std::vec::slice;
import std::vec::len;
import std::int;

fn vec_omit<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + slice(v, i + 1u, len(v))
}
fn vec_dup<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i]] + slice(v, i, len(v))
}
fn vec_swadj<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v))
}
fn vec_prefix<@T>(v: [T], i: uint) -> [T] { slice(v, 0u, i) }
fn vec_suffix<@T>(v: [T], i: uint) -> [T] { slice(v, i, len(v)) }

fn vec_poke<@T>(v: [T], i: uint, x: T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i + 1u, len(v))
}
fn vec_insert<@T>(v: [T], i: uint, x: T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i, len(v))
}

// Iterates over 0...length, skipping the specified number on each side.
iter ix(skip_low: uint, skip_high: uint, length: uint) -> uint {
    let i: uint = skip_low;
    while i + skip_high <= length { put i; i += 1u; }
}

// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
fn vec_edits<@T>(v: [T], xs: [T]) -> [[T]] {
    let edits: [[T]] = [];
    let Lv: uint = len(v);

    if Lv != 1u {
        // When Lv == 1u, this is redundant with omit.
        edits += [[]];
    }
    if Lv >= 3u {
        // When Lv == 2u, this is redundant with swap.
        edits += [vec::reversed(v)];
    }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_omit(v, i)]; }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_dup(v, i)]; }
    for each i: uint in ix(0u, 2u, Lv) { edits += [vec_swadj(v, i)]; }
    for each i: uint in ix(1u, 2u, Lv) { edits += [vec_prefix(v, i)]; }
    for each i: uint in ix(2u, 1u, Lv) { edits += [vec_suffix(v, i)]; }

    for each j: uint in ix(0u, 1u, len(xs)) {
        for each i: uint in ix(0u, 1u, Lv) {
            edits += [vec_poke(v, i, xs[j])];
        }
        for each i: uint in ix(0u, 0u, Lv) {
            edits += [vec_insert(v, i, xs[j])];
        }
    }

    edits
}

// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
fn vec_to_str(v: [int]) -> str {
    let i = 0u;
    let s = "[";
    while i < len(v) {
        s += int::str(v[i]);
        if i + 1u < len(v) { s += ", " }
        i += 1u;
    }
    ret s + "]";
}

fn show_edits(a: [int], xs: [int]) {
    log_err "=== Edits of " + vec_to_str(a) + " ===";
    let b = vec_edits(a, xs);
    for each i: uint in ix(0u, 1u, len(b)) { log_err vec_to_str(b[i]); }
}

fn demo_edits() {
    let xs = [7, 8];
    show_edits([], xs);
    show_edits([1], xs);
    show_edits([1, 2], xs);
    show_edits([1, 2, 3], xs);
    show_edits([1, 2, 3, 4], xs);
}

fn main() { demo_edits(); }
<commit_msg>Fix syntax error<commit_after>/*

Idea: provide functions for 'exhaustive' and 'random' modification of vecs.

  two functions, "return all edits" and "return a random edit" <-- leaning toward this model
    or
  two functions, "return the number of possible edits" and "return edit #n"

It would be nice if this could be data-driven, so the two functions could share information:
  type vec_modifier = rec(fn (<T> v, uint i) -> [T] fun, uint lo, uint di);
  const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
https://github.com/graydon/rust/issues/570

vec_edits is not an iter because iters might go away.

*/

use std;
import std::vec;
import std::vec::slice;
import std::vec::len;
import std::int;

fn vec_omit<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + slice(v, i + 1u, len(v))
}
fn vec_dup<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i]] + slice(v, i, len(v))
}
fn vec_swadj<@T>(v: [T], i: uint) -> [T] {
    slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v))
}
fn vec_prefix<@T>(v: [T], i: uint) -> [T] { slice(v, 0u, i) }
fn vec_suffix<@T>(v: [T], i: uint) -> [T] { slice(v, i, len(v)) }

fn vec_poke<@T>(v: [T], i: uint, x: T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i + 1u, len(v))
}
fn vec_insert<@T>(v: [T], i: uint, x: T) -> [T] {
    slice(v, 0u, i) + [x] + slice(v, i, len(v))
}

// Iterates over 0...length, skipping the specified number on each side.
iter ix(skip_low: uint, skip_high: uint, length: uint) -> uint {
    let i: uint = skip_low;
    while i + skip_high <= length { put i; i += 1u; }
}

// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
fn vec_edits<@T>(v: [T], xs: [T]) -> [[T]] {
    let edits: [[T]] = [];
    let Lv: uint = len(v);

    if Lv != 1u {
        // When Lv == 1u, this is redundant with omit.
        edits += [[]];
    }
    if Lv >= 3u {
        // When Lv == 2u, this is redundant with swap.
        edits += [vec::reversed(v)];
    }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_omit(v, i)]; }
    for each i: uint in ix(0u, 1u, Lv) { edits += [vec_dup(v, i)]; }
    for each i: uint in ix(0u, 2u, Lv) { edits += [vec_swadj(v, i)]; }
    for each i: uint in ix(1u, 2u, Lv) { edits += [vec_prefix(v, i)]; }
    for each i: uint in ix(2u, 1u, Lv) { edits += [vec_suffix(v, i)]; }

    for each j: uint in ix(0u, 1u, len(xs)) {
        for each i: uint in ix(0u, 1u, Lv) {
            edits += [vec_poke(v, i, xs[j])];
        }
        for each i: uint in ix(0u, 0u, Lv) {
            edits += [vec_insert(v, i, xs[j])];
        }
    }

    edits
}

// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
fn vec_to_str(v: [int]) -> str {
    let i = 0u;
    let s = "[";
    while i < len(v) {
        s += int::str(v[i]);
        if i + 1u < len(v) { s += ", "; }
        i += 1u;
    }
    ret s + "]";
}

fn show_edits(a: [int], xs: [int]) {
    log_err "=== Edits of " + vec_to_str(a) + " ===";
    let b = vec_edits(a, xs);
    for each i: uint in ix(0u, 1u, len(b)) { log_err vec_to_str(b[i]); }
}

fn demo_edits() {
    let xs = [7, 8];
    show_edits([], xs);
    show_edits([1], xs);
    show_edits([1, 2], xs);
    show_edits([1, 2, 3], xs);
    show_edits([1, 2, 3, 4], xs);
}

fn main() { demo_edits(); }
<|endoftext|>


<commit_before>//! Create window.

// External crates.
use collections::Deque;
use collections::ringbuf::RingBuf;
use glfw;
use gl;
use piston::event;
use piston::keyboard;
use piston::mouse;
use piston::GameWindow;
use piston::GameWindowSettings;

/// Contains stuff for game window.
pub struct GameWindowGLFW {
    /// The window.
    window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    glfw: glfw::Glfw,
    /// Game window settings.
    settings: GameWindowSettings,
    event_queue: RingBuf<event::Event>,
}

impl GameWindowGLFW {
    /// Creates a new game window for GLFW.
    pub fn new(settings: GameWindowSettings) -> GameWindowGLFW {
        use glfw::Context;

        // Create GLFW window.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_key_polling(true);
        window.set_mouse_button_polling(true);
        window.set_cursor_pos_polling(true);
        // or polling all event
        //window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| glfw.get_proc_address(s));

        GameWindowGLFW {
            window: window,
            events: events,
            glfw: glfw,
            settings: settings,
            event_queue: RingBuf::<event::Event>::new(),
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                    if self.settings.exit_on_esc => {
                        self.window.set_should_close(true);
                    },
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push_back(
                        event::KeyPressed(glfw_map_key(key)));
                },
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push_back(
                        event::KeyReleased(glfw_map_key(key)));
                },
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push_back(
                        event::MouseButtonPressed(glfw_map_mouse(button)));
                },
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push_back(
                        event::MouseButtonReleased(glfw_map_mouse(button)));
                },
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push_back(
                        event::MouseMoved(x, y, None));
                },
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push_back(
                        event::MouseScrolled(x, y));
                },
                _ => {},
            }
        }
    }
}

impl GameWindow for GameWindowGLFW {
    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.window.should_close()
    }

    fn swap_buffers(&self) {
        use glfw::Context;

        self.window.swap_buffers();
    }

    fn poll_event(&mut self) -> event::Event {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front().unwrap()
        } else {
            event::NoEvent
        }
    }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}

<commit_msg>Activated polling of scroll events<commit_after>//! Create window.

// External crates.
use collections::Deque;
use collections::ringbuf::RingBuf;
use glfw;
use gl;
use piston::event;
use piston::keyboard;
use piston::mouse;
use piston::GameWindow;
use piston::GameWindowSettings;

/// Contains stuff for game window.
pub struct GameWindowGLFW {
    /// The window.
    window: glfw::Window,
    /// Receives events from window.
    events: Receiver<(f64, glfw::WindowEvent)>,
    /// GLFW context.
    glfw: glfw::Glfw,
    /// Game window settings.
    settings: GameWindowSettings,
    event_queue: RingBuf<event::Event>,
}

impl GameWindowGLFW {
    /// Creates a new game window for GLFW.
    pub fn new(settings: GameWindowSettings) -> GameWindowGLFW {
        use glfw::Context;

        // Create GLFW window.
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let (window, events) = glfw.create_window(
            settings.size[0],
            settings.size[1],
            settings.title.as_slice(), glfw::Windowed
        ).expect("Failed to create GLFW window.");
        window.set_key_polling(true);
        window.set_mouse_button_polling(true);
        window.set_cursor_pos_polling(true);
        window.set_scroll_polling(true);
        // or polling all event
        //window.set_all_polling(true);
        window.make_current();

        // Load the OpenGL function pointers
        gl::load_with(|s| glfw.get_proc_address(s));

        GameWindowGLFW {
            window: window,
            events: events,
            glfw: glfw,
            settings: settings,
            event_queue: RingBuf::<event::Event>::new(),
        }
    }

    fn flush_messages(&mut self) {
        if self.event_queue.len() != 0 {
            return;
        }

        self.glfw.poll_events();
        for (_, event) in glfw::flush_messages(&self.events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _)
                    if self.settings.exit_on_esc => {
                        self.window.set_should_close(true);
                    },
                glfw::KeyEvent(key, _, glfw::Press, _) => {
                    self.event_queue.push_back(
                        event::KeyPressed(glfw_map_key(key)));
                },
                glfw::KeyEvent(key, _, glfw::Release, _) => {
                    self.event_queue.push_back(
                        event::KeyReleased(glfw_map_key(key)));
                },
                glfw::MouseButtonEvent(button, glfw::Press, _) => {
                    self.event_queue.push_back(
                        event::MouseButtonPressed(glfw_map_mouse(button)));
                },
                glfw::MouseButtonEvent(button, glfw::Release, _) => {
                    self.event_queue.push_back(
                        event::MouseButtonReleased(glfw_map_mouse(button)));
                },
                glfw::CursorPosEvent(x, y) => {
                    self.event_queue.push_back(
                        event::MouseMoved(x, y, None));
                },
                glfw::ScrollEvent(x, y) => {
                    self.event_queue.push_back(
                        event::MouseScrolled(x, y));
                },
                _ => {},
            }
        }
    }
}

impl GameWindow for GameWindowGLFW {
    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.window.should_close()
    }

    fn swap_buffers(&self) {
        use glfw::Context;

        self.window.swap_buffers();
    }

    fn poll_event(&mut self) -> event::Event {
        self.flush_messages();

        if self.event_queue.len() != 0 {
            self.event_queue.pop_front().unwrap()
        } else {
            event::NoEvent
        }
    }
}

fn glfw_map_key(keycode: glfw::Key) -> keyboard::Key {
    match keycode {
        glfw::Key0 => keyboard::D0,
        glfw::Key1 => keyboard::D1,
        glfw::Key2 => keyboard::D2,
        glfw::Key3 => keyboard::D3,
        glfw::Key4 => keyboard::D4,
        glfw::Key5 => keyboard::D5,
        glfw::Key6 => keyboard::D6,
        glfw::Key7 => keyboard::D7,
        glfw::Key8 => keyboard::D8,
        glfw::Key9 => keyboard::D9,
        glfw::KeyA => keyboard::A,
        glfw::KeyB => keyboard::B,
        glfw::KeyC => keyboard::C,
        glfw::KeyD => keyboard::D,
        glfw::KeyE => keyboard::E,
        glfw::KeyF => keyboard::F,
        glfw::KeyG => keyboard::G,
        glfw::KeyH => keyboard::H,
        glfw::KeyI => keyboard::I,
        glfw::KeyJ => keyboard::J,
        glfw::KeyK => keyboard::K,
        glfw::KeyL => keyboard::L,
        glfw::KeyM => keyboard::M,
        glfw::KeyN => keyboard::N,
        glfw::KeyO => keyboard::O,
        glfw::KeyP => keyboard::P,
        glfw::KeyQ => keyboard::Q,
        glfw::KeyR => keyboard::R,
        glfw::KeyS => keyboard::S,
        glfw::KeyT => keyboard::T,
        glfw::KeyU => keyboard::U,
        glfw::KeyV => keyboard::V,
        glfw::KeyW => keyboard::W,
        glfw::KeyX => keyboard::X,
        glfw::KeyY => keyboard::Y,
        glfw::KeyZ => keyboard::Z,
        glfw::KeyApostrophe => keyboard::Unknown,
        glfw::KeyBackslash => keyboard::Backslash,
        glfw::KeyBackspace => keyboard::Backspace,
        glfw::KeyCapsLock => keyboard::CapsLock,
        glfw::KeyDelete => keyboard::Delete,
        glfw::KeyComma => keyboard::Comma,
        glfw::KeyDown => keyboard::Down,
        glfw::KeyEnd => keyboard::End,
        glfw::KeyEnter => keyboard::Return,
        glfw::KeyEqual => keyboard::Equals,
        glfw::KeyEscape => keyboard::Escape,
        glfw::KeyF1 => keyboard::F1,
        glfw::KeyF2 => keyboard::F2,
        glfw::KeyF3 => keyboard::F3,
        glfw::KeyF4 => keyboard::F4,
        glfw::KeyF5 => keyboard::F5,
        glfw::KeyF6 => keyboard::F6,
        glfw::KeyF7 => keyboard::F7,
        glfw::KeyF8 => keyboard::F8,
        glfw::KeyF9 => keyboard::F9,
        glfw::KeyF10 => keyboard::F10,
        glfw::KeyF11 => keyboard::F11,
        glfw::KeyF12 => keyboard::F12,
        glfw::KeyF13 => keyboard::F13,
        glfw::KeyF14 => keyboard::F14,
        glfw::KeyF15 => keyboard::F15,
        glfw::KeyF16 => keyboard::F16,
        glfw::KeyF17 => keyboard::F17,
        glfw::KeyF18 => keyboard::F18,
        glfw::KeyF19 => keyboard::F19,
        glfw::KeyF20 => keyboard::F20,
        glfw::KeyF21 => keyboard::F21,
        glfw::KeyF22 => keyboard::F22,
        glfw::KeyF23 => keyboard::F23,
        glfw::KeyF24 => keyboard::F24,
        // Possibly next code.
        glfw::KeyF25 => keyboard::Unknown,
        glfw::KeyKp0 => keyboard::NumPad0,
        glfw::KeyKp1 => keyboard::NumPad1,
        glfw::KeyKp2 => keyboard::NumPad2,
        glfw::KeyKp3 => keyboard::NumPad3,
        glfw::KeyKp4 => keyboard::NumPad4,
        glfw::KeyKp5 => keyboard::NumPad5,
        glfw::KeyKp6 => keyboard::NumPad6,
        glfw::KeyKp7 => keyboard::NumPad7,
        glfw::KeyKp8 => keyboard::NumPad8,
        glfw::KeyKp9 => keyboard::NumPad9,
        glfw::KeyKpDecimal => keyboard::NumPadDecimal,
        glfw::KeyKpDivide => keyboard::NumPadDivide,
        glfw::KeyKpMultiply => keyboard::NumPadMultiply,
        glfw::KeyKpSubtract => keyboard::NumPadMinus,
        glfw::KeyKpAdd => keyboard::NumPadPlus,
        glfw::KeyKpEnter => keyboard::NumPadEnter,
        glfw::KeyKpEqual => keyboard::NumPadEquals,
        glfw::KeyLeftShift => keyboard::LShift,
        glfw::KeyLeftControl => keyboard::LCtrl,
        glfw::KeyLeftAlt => keyboard::LAlt,
        glfw::KeyLeftSuper => keyboard::LGui,
        glfw::KeyRightShift => keyboard::RShift,
        glfw::KeyRightControl => keyboard::RCtrl,
        glfw::KeyRightAlt => keyboard::RAlt,
        glfw::KeyRightSuper => keyboard::RGui,
        // Map to backslash?
        glfw::KeyGraveAccent => keyboard::Unknown,
        glfw::KeyHome => keyboard::Home,
        glfw::KeyInsert => keyboard::Insert,
        glfw::KeyLeft => keyboard::Left,
        glfw::KeyLeftBracket => keyboard::LeftBracket,
        glfw::KeyMenu => keyboard::Menu,
        glfw::KeyMinus => keyboard::Minus,
        glfw::KeyNumLock => keyboard::NumLockClear,
        glfw::KeyPageDown => keyboard::PageDown,
        glfw::KeyPageUp => keyboard::PageUp,
        glfw::KeyPause => keyboard::Pause,
        glfw::KeyPeriod => keyboard::Period,
        glfw::KeyPrintScreen => keyboard::PrintScreen,
        glfw::KeyRight => keyboard::Right,
        glfw::KeyRightBracket => keyboard::RightBracket,
        glfw::KeyScrollLock => keyboard::ScrollLock,
        glfw::KeySemicolon => keyboard::Semicolon,
        glfw::KeySlash => keyboard::Slash,
        glfw::KeySpace => keyboard::Space,
        glfw::KeyTab => keyboard::Tab,
        glfw::KeyUp => keyboard::Up,
        glfw::KeyWorld1 => keyboard::Unknown,
        glfw::KeyWorld2 => keyboard::Unknown,
        // _ => keyboard::Unknown,
    }
}

fn glfw_map_mouse(mouse_button: glfw::MouseButton) -> mouse::Button {
    match mouse_button {
        glfw::MouseButton1 => mouse::Left,
        glfw::MouseButton2 => mouse::Right,
        glfw::MouseButton3 => mouse::Middle,
        glfw::MouseButton4 => mouse::X1,
        glfw::MouseButton5 => mouse::X2,
        glfw::MouseButton6 => mouse::Button6,
        glfw::MouseButton7 => mouse::Button7,
        glfw::MouseButton8 => mouse::Button8,
    }
}

<|endoftext|>


<commit_before>//! A window implemented by SDL2 back-end.

// External crates.
use std::mem::transmute;
use gl;
use gfx;
use sdl2;
use piston::{
    GameWindow,
    GameWindowSettings,
};
use piston::input;
use piston::input::keyboard;
use piston::input::mouse;
use shader_version::opengl::OpenGL;

/// A widow implemented by SDL2 back-end.
pub struct GameWindowSDL2 {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    settings: GameWindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
}

impl GameWindowSDL2 {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: GameWindowSettings) -> GameWindowSDL2 {
        sdl2::init(sdl2::InitEverything);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OpenGL | sdl2::video::Resizable
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        GameWindowSDL2 {
            settings: settings,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }

    /// Creates a gfx devince and front end.
    pub fn gfx(&self) -> (gfx::GlDevice, gfx::Frame) {
        let device = gfx::GlDevice::new(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });
        let (w, h) = self.get_size();
        let frame = gfx::Frame::new(w as u16, h as u16);
        (device, frame)
    }
}

impl Drop for GameWindowSDL2 {
    fn drop(&mut self) {
        self.capture_cursor(false);
    }
}

impl GameWindow for GameWindowSDL2 {
    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.should_close
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_drawable_size();
        (w as u32, h as u32)
    }

    fn close(&mut self) {
        self.should_close = true;
    }

    fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }

    fn capture_cursor(&mut self, enabled: bool) {
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }

    fn poll_event(&mut self) -> Option<input::InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; }
            sdl2::event::TextInputEvent(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::MouseWheelEvent(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            _ => {}
        }
        None
    }
}

pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode.code() as u64).unwrap()
}

pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}

<commit_msg>Set MSAA mode<commit_after>//! A window implemented by SDL2 back-end.

// External crates.
use std::mem::transmute;
use gl;
use gfx;
use sdl2;
use piston::{
    GameWindow,
    GameWindowSettings,
};
use piston::input;
use piston::input::keyboard;
use piston::input::mouse;
use shader_version::opengl::OpenGL;

/// A widow implemented by SDL2 back-end.
pub struct GameWindowSDL2 {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    settings: GameWindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
}

impl GameWindowSDL2 {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: GameWindowSettings) -> GameWindowSDL2 {
        sdl2::init(sdl2::InitEverything);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );
        if settings.samples != 0 {
            sdl2::video::gl_set_attribute(sdl2::video::GLMultiSampleBuffers, 1);
            sdl2::video::gl_set_attribute(
                sdl2::video::GLMultiSampleSamples,
                settings.samples as int
            );
        }

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OpenGL | sdl2::video::Resizable
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        GameWindowSDL2 {
            settings: settings,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }

    /// Creates a gfx devince and front end.
    pub fn gfx(&self) -> (gfx::GlDevice, gfx::Frame) {
        let device = gfx::GlDevice::new(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });
        let (w, h) = self.get_size();
        let frame = gfx::Frame::new(w as u16, h as u16);
        (device, frame)
    }
}

impl Drop for GameWindowSDL2 {
    fn drop(&mut self) {
        self.capture_cursor(false);
    }
}

impl GameWindow for GameWindowSDL2 {
    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.should_close
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_drawable_size();
        (w as u32, h as u32)
    }

    fn close(&mut self) {
        self.should_close = true;
    }

    fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }

    fn capture_cursor(&mut self, enabled: bool) {
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }

    fn poll_event(&mut self) -> Option<input::InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; }
            sdl2::event::TextInputEvent(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::MouseWheelEvent(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            _ => {}
        }
        None
    }
}

pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode.code() as u64).unwrap()
}

pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}
<|endoftext|>


<commit_before>// vim: tw=80
use super::*;

use crate::{
    mock_function::MockFunction,
    mockable_item::{MockableItem, MockableModule}
};

/// A Mock item
pub(crate) enum MockItem {
    Module(MockItemModule),
    Struct(MockItemStruct)
}

impl From<MockableItem> for MockItem {
    fn from(mockable: MockableItem) -> MockItem {
        match mockable {
            MockableItem::Struct(s) => MockItem::Struct(
                MockItemStruct::from(s)
            ),
            MockableItem::Module(mod_) => MockItem::Module(
                MockItemModule::from(mod_)
            )
        }
    }
}

impl ToTokens for MockItem {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            MockItem::Module(mod_) => mod_.to_tokens(tokens),
            MockItem::Struct(s) => s.to_tokens(tokens)
        }
    }
}

enum MockItemContent {
    Fn(MockFunction),
    Tokens(TokenStream)
}

pub(crate) struct MockItemModule {
    vis: Visibility,
    mock_ident: Ident,
    orig_ident: Option<Ident>,
    content: Vec<MockItemContent>
}

impl From<MockableModule> for MockItemModule {
    fn from(mod_: MockableModule) -> MockItemModule {
        let mock_ident = mod_.mock_ident.clone();
        let orig_ident = mod_.orig_ident;
        let content = mod_.content.into_iter().filter_map(|item| {
            let span = item.span();
            match item {
                Item::ExternCrate(_) | Item::Impl(_) =>
                {
                    // Ignore
                    None
                },
                Item::Static(is) => {
                    Some(MockItemContent::Tokens(is.into_token_stream()))
                },
                Item::Const(ic) => {
                    Some(MockItemContent::Tokens(ic.into_token_stream()))
                },
                Item::Fn(f) => {
                    let mf = mock_function::Builder::new(&f.sig, &f.vis)
                        .attrs(&f.attrs)
                        .parent(&mock_ident)
                        .levels(1)
                        .call_levels(0)
                        .build();
                    Some(MockItemContent::Fn(mf))
                },
                Item::Mod(_) | Item::ForeignMod(_)
                    | Item::Struct(_) | Item::Enum(_)
                    | Item::Union(_) | Item::Trait(_) =>
                {
                    compile_error(span,
                        "Mockall does not yet support deriving nested mocks");
                    None
                },
                Item::Type(ty) => {
                    Some(MockItemContent::Tokens(ty.into_token_stream()))
                },
                Item::TraitAlias(ta) => {
                    Some(MockItemContent::Tokens(ta.into_token_stream()))
                },
                Item::Use(u) => {
                    Some(MockItemContent::Tokens(u.into_token_stream()))
                },
                _ => {
                    compile_error(span, "Unsupported item");
                    None
                }
            }
        }).collect::<Vec<_>>();

        MockItemModule {
            vis: mod_.vis,
            mock_ident: mod_.mock_ident,
            orig_ident,
            content
        }
    }
}

impl ToTokens for MockItemModule {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let mut body = TokenStream::new();
        let mut cp_body = TokenStream::new();
        let modname = &self.mock_ident;

        for item in self.content.iter() {
            match item {
                MockItemContent::Tokens(ts) => ts.to_tokens(&mut body),
                MockItemContent::Fn(f) => {
                    let call = f.call(None);
                    let ctx_fn = f.context_fn(None);
                    let priv_mod = f.priv_module();
                    quote!(
                        #priv_mod
                        #call
                        #ctx_fn
                    ).to_tokens(&mut body);
                    f.checkpoint().to_tokens(&mut cp_body);
                },
            }
        }

        quote!(
            /// Verify that all current expectations for this function are
            /// satisfied and clear them.
            pub fn checkpoint() { #cp_body }
        ).to_tokens(&mut body);
        let docstr = {
            if let Some(ident) = &self.orig_ident {
                let inner = format!("Mock version of the `{}` module", ident);
                quote!( #[doc = #inner])
            } else {
                // TODO: write doc string
                quote!(#[allow(missing_docs)])
            }
        };
        quote!(
            #docstr
            // TODO: remove the allow unused_unit
            // https://github.com/asomers/mockall/issues/149
            #[allow(clippy::unused_unit)]
            pub mod #modname {
                #body
        }).to_tokens(tokens);
    }
}
<commit_msg>Fix a harmless visibility handling error<commit_after>// vim: tw=80
use super::*;

use crate::{
    mock_function::MockFunction,
    mockable_item::{MockableItem, MockableModule}
};

/// A Mock item
pub(crate) enum MockItem {
    Module(MockItemModule),
    Struct(MockItemStruct)
}

impl From<MockableItem> for MockItem {
    fn from(mockable: MockableItem) -> MockItem {
        match mockable {
            MockableItem::Struct(s) => MockItem::Struct(
                MockItemStruct::from(s)
            ),
            MockableItem::Module(mod_) => MockItem::Module(
                MockItemModule::from(mod_)
            )
        }
    }
}

impl ToTokens for MockItem {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            MockItem::Module(mod_) => mod_.to_tokens(tokens),
            MockItem::Struct(s) => s.to_tokens(tokens)
        }
    }
}

enum MockItemContent {
    Fn(MockFunction),
    Tokens(TokenStream)
}

pub(crate) struct MockItemModule {
    vis: Visibility,
    mock_ident: Ident,
    orig_ident: Option<Ident>,
    content: Vec<MockItemContent>
}

impl From<MockableModule> for MockItemModule {
    fn from(mod_: MockableModule) -> MockItemModule {
        let mock_ident = mod_.mock_ident.clone();
        let orig_ident = mod_.orig_ident;
        let content = mod_.content.into_iter().filter_map(|item| {
            let span = item.span();
            match item {
                Item::ExternCrate(_) | Item::Impl(_) =>
                {
                    // Ignore
                    None
                },
                Item::Static(is) => {
                    Some(MockItemContent::Tokens(is.into_token_stream()))
                },
                Item::Const(ic) => {
                    Some(MockItemContent::Tokens(ic.into_token_stream()))
                },
                Item::Fn(f) => {
                    let mf = mock_function::Builder::new(&f.sig, &f.vis)
                        .attrs(&f.attrs)
                        .parent(&mock_ident)
                        .levels(1)
                        .call_levels(0)
                        .build();
                    Some(MockItemContent::Fn(mf))
                },
                Item::Mod(_) | Item::ForeignMod(_)
                    | Item::Struct(_) | Item::Enum(_)
                    | Item::Union(_) | Item::Trait(_) =>
                {
                    compile_error(span,
                        "Mockall does not yet support deriving nested mocks");
                    None
                },
                Item::Type(ty) => {
                    Some(MockItemContent::Tokens(ty.into_token_stream()))
                },
                Item::TraitAlias(ta) => {
                    Some(MockItemContent::Tokens(ta.into_token_stream()))
                },
                Item::Use(u) => {
                    Some(MockItemContent::Tokens(u.into_token_stream()))
                },
                _ => {
                    compile_error(span, "Unsupported item");
                    None
                }
            }
        }).collect::<Vec<_>>();

        MockItemModule {
            vis: mod_.vis,
            mock_ident: mod_.mock_ident,
            orig_ident,
            content
        }
    }
}

impl ToTokens for MockItemModule {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let mut body = TokenStream::new();
        let mut cp_body = TokenStream::new();
        let modname = &self.mock_ident;
        let vis = &self.vis;

        for item in self.content.iter() {
            match item {
                MockItemContent::Tokens(ts) => ts.to_tokens(&mut body),
                MockItemContent::Fn(f) => {
                    let call = f.call(None);
                    let ctx_fn = f.context_fn(None);
                    let priv_mod = f.priv_module();
                    quote!(
                        #priv_mod
                        #call
                        #ctx_fn
                    ).to_tokens(&mut body);
                    f.checkpoint().to_tokens(&mut cp_body);
                },
            }
        }

        quote!(
            /// Verify that all current expectations for this function are
            /// satisfied and clear them.
            pub fn checkpoint() { #cp_body }
        ).to_tokens(&mut body);
        let docstr = {
            if let Some(ident) = &self.orig_ident {
                let inner = format!("Mock version of the `{}` module", ident);
                quote!( #[doc = #inner])
            } else {
                // TODO: write doc string
                quote!(#[allow(missing_docs)])
            }
        };
        quote!(
            #docstr
            // TODO: remove the allow unused_unit
            // https://github.com/asomers/mockall/issues/149
            #[allow(clippy::unused_unit)]
            #vis mod #modname {
                #body
        }).to_tokens(tokens);
    }
}
<|endoftext|>


<commit_before>//! Bindings to the client library `libwayland-server.so`
//!
//! The generated handle is named `WAYLAND_SERVER_HANDLE`

use super::common::*;
use libc::{gid_t, pid_t, uid_t};
use std::os::raw::{c_char, c_int, c_void};

pub enum wl_client { }
pub enum wl_display { }
pub enum wl_event_loop { }
pub enum wl_event_source { }
pub enum wl_global { }
pub enum wl_resource { }
pub enum wl_shm_buffer { }

pub type wl_event_loop_fd_func_t = unsafe extern "C" fn(c_int, u32, *mut c_void) -> c_int;
pub type wl_event_loop_timer_func_t = unsafe extern "C" fn(*mut c_void) -> c_int;
pub type wl_event_loop_signal_func_t = unsafe extern "C" fn(c_int, *mut c_void) -> c_int;
pub type wl_event_loop_idle_func_t = unsafe extern "C" fn(*mut c_void) -> ();
pub type wl_global_bind_func_t = unsafe extern "C" fn(*mut wl_client, *mut c_void, u32, u32) -> ();
pub type wl_notify_func_t = unsafe extern "C" fn(*mut wl_listener, *mut c_void) -> ();
pub type wl_resource_destroy_func_t = unsafe extern "C" fn(*mut wl_resource) -> ();

#[repr(C)]
pub struct wl_listener {
    pub link: wl_list,
    pub notify: wl_notify_func_t
}

#[repr(C)]
pub struct wl_signal {
    pub listener_list: wl_list
}

external_library!(WaylandServer, "wayland-server",
    functions:
    // wl_client
        fn wl_client_flush(*mut wl_client) -> (),
        fn wl_client_destroy(*mut wl_client) -> (),
        fn wl_client_get_display(*mut wl_client) -> *mut wl_display,
        fn wl_client_get_credentials(*mut wl_client, *mut pid_t, *mut uid_t, *mut gid_t) -> (),
        fn wl_client_get_object(*mut wl_client, u32) -> *mut wl_resource,
        fn wl_client_add_destroy_listener(*mut wl_client, *mut wl_listener) -> (),
        fn wl_client_get_destroy_listener(*mut wl_client, wl_notify_func_t) -> *mut wl_listener,
        fn wl_client_post_no_memory(*mut wl_client) -> (),
        fn wl_resource_create(*mut wl_client, *const wl_interface, c_int, u32) -> *mut wl_resource,
    // wl_display
        fn wl_client_create(*mut wl_display, c_int) -> *mut wl_client,
        fn wl_display_create() -> *mut wl_display,
        fn wl_display_destroy(*mut wl_display) -> (),
        fn wl_display_get_serial(*mut wl_display) -> u32,
        fn wl_display_next_serial(*mut wl_display) -> u32,
        fn wl_display_add_socket(*mut wl_display, *const c_char) -> c_int,
        fn wl_display_add_socket_auto(*mut wl_display) -> *const c_char,
        fn wl_display_add_socket_fd(*mut wl_display, c_int) -> c_int,
        fn wl_display_add_shm_format(*mut wl_display, u32) -> *mut u32,
        fn wl_display_get_event_loop(*mut wl_display) -> *mut wl_event_loop,
        fn wl_display_terminate(*mut wl_display) -> (),
        fn wl_display_run(*mut wl_display) -> (),
        fn wl_display_flush_clients(*mut wl_display) -> (),
        fn wl_display_add_destroy_listener(*mut wl_display, *mut wl_listener) -> (),
        fn wl_display_get_destroy_listener(*mut wl_display, wl_notify_func_t) -> *mut wl_listener,
        fn wl_global_create(*mut wl_display, *const wl_interface, c_int, *mut c_void, wl_global_bind_func_t) -> *mut wl_global,
        fn wl_display_init_shm(*mut wl_display) -> c_int,
    // wl_event_loop
        fn wl_event_loop_create() -> *mut wl_event_loop,
        fn wl_event_loop_destroy(*mut wl_event_loop) -> (),
        fn wl_event_loop_add_fd(*mut wl_event_loop, c_int, u32, wl_event_loop_fd_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_add_timer(*mut wl_event_loop, wl_event_loop_timer_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_add_signal(*mut wl_event_loop, c_int, wl_event_loop_signal_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_dispatch(*mut wl_event_loop, c_int) -> c_int,
        fn wl_event_loop_dispatch_idle(*mut wl_event_loop) -> (),
        fn wl_event_loop_add_idle(*mut wl_event_loop, wl_event_loop_idle_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_get_fd(*mut wl_event_loop) -> c_int,
        fn wl_event_loop_add_destroy_listener(*mut wl_event_loop, *mut wl_listener) -> (),
        fn wl_event_loop_get_destroy_listener(*mut wl_event_loop, wl_notify_func_t) -> *mut wl_listener,
    // wl_event_source
        fn wl_event_source_fd_update(*mut wl_event_source, u32) -> c_int,
        fn wl_event_source_timer_update(*mut wl_event_source, c_int) -> c_int,
        fn wl_event_source_remove(*mut wl_event_source) -> c_int,
        fn wl_event_source_check(*mut wl_event_source) -> (),
    // wl_global
        fn wl_global_destroy(*mut wl_global) -> (),
    // wl_resource
        fn wl_resource_post_event_array(*mut wl_resource, u32, *mut wl_argument) -> (),
        fn wl_resource_queue_event_array(*mut wl_resource, u32, *mut wl_argument) -> (),
        fn wl_resource_post_no_memory(*mut wl_resource) -> (),
        fn wl_resource_set_implementation(*mut wl_resource, *const c_void, *mut c_void, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_set_dispatcher(*mut wl_resource, wl_dispatcher_func_t, *const c_void, *mut c_void, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_destroy(*mut wl_resource) -> (),
        fn wl_resource_get_client(*mut wl_resource) -> *mut wl_client,
        fn wl_resource_get_id(*mut wl_resource) -> u32,
        fn wl_resource_get_link(*mut wl_resource) -> *mut wl_list,
        fn wl_resource_from_link(*mut wl_list) -> *mut wl_resource,
        fn wl_resource_find_for_client(*mut wl_list, *mut wl_client) -> (),
        fn wl_resource_set_user_data(*mut wl_resource, *mut c_void) -> (),
        fn wl_resource_get_user_data(*mut wl_resource) -> *mut c_void,
        fn wl_resource_get_version(*mut wl_resource) -> c_int,
        fn wl_resource_set_destructor(*mut wl_resource, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_instance_of(*mut wl_resource, *const wl_interface, *const c_void) -> c_int,
        fn wl_resource_add_destroy_listener(*mut wl_resource, wl_notify_func_t) -> (),
        fn wl_resource_get_destroy_listener(*mut wl_resource,wl_notify_func_t) -> *mut wl_listener,
    // wl_shm
        fn wl_shm_buffer_begin_access(*mut wl_shm_buffer) -> (),
        fn wl_shm_buffer_end_access(*mut wl_shm_buffer) -> (),
        fn wl_shm_buffer_get(*mut wl_resource) -> *mut wl_shm_buffer,
        fn wl_shm_buffer_get_data(*mut wl_shm_buffer) -> *mut c_void,
        fn wl_shm_buffer_get_stride(*mut wl_shm_buffer) -> i32,
        fn wl_shm_buffer_get_format(*mut wl_shm_buffer) -> u32,
        fn wl_shm_buffer_get_width(*mut wl_shm_buffer) -> i32,
        fn wl_shm_buffer_get_height(*mut wl_shm_buffer) -> i32,
    // wl_log
        fn wl_log_set_handler_server(wl_log_func_t) -> (),
    // wl_list
        fn wl_list_init(*mut wl_list) -> (),
        fn wl_list_insert(*mut wl_list, *mut wl_list) -> (),
        fn wl_list_remove(*mut wl_list) -> (),
        fn wl_list_length(*const wl_list) -> c_int,
        fn wl_list_empty(*const wl_list) -> c_int,
        fn wl_list_insert_list(*mut wl_list,*mut wl_list) -> (),

    // arrays
        fn wl_array_init(*mut wl_array) -> (),
        fn wl_array_release(*mut wl_array) -> (),
        fn wl_array_add(*mut wl_array,usize) -> (),
        fn wl_array_copy(*mut wl_array, *mut wl_array) -> (),
    varargs:
        fn wl_resource_post_event(*mut wl_resource, u32) -> (),
        fn wl_resource_queue_event(*mut wl_resource, u32) -> (),
        fn wl_resource_post_error(*mut wl_resource, u32, *const c_char) -> (),
);

#[cfg(feature = "dlopen")]
lazy_static!(
    pub static ref WAYLAND_SERVER_OPTION: Option<WaylandServer> = {
        match WaylandServer::open("libwayland-server.so") {
            Ok(h) => Some(h),
            Err(::dlib::DlError::NotFound) => None,
            Err(::dlib::DlError::MissingSymbol(s)) => {
                use std::io::Write;
                let _ = write!(::std::io::stderr(),
                               "[wayland-server] Found library libwayland-server.so cannot be used: symbol {} is missing.",
                               s);
                None
            }
        }
    };
    pub static ref WAYLAND_SERVER_HANDLE: &'static WaylandServer = {
        WAYLAND_SERVER_OPTION.as_ref().expect("Library libwayland-server.so could not be loaded.")
    };
);

#[cfg(not(feature = "dlopen"))]
pub fn is_lib_available() -> bool {
    true
}
#[cfg(feature = "dlopen")]
pub fn is_lib_available() -> bool {
    WAYLAND_SERVER_OPTION.is_some()
}
<commit_msg>sys: wl_signal_* functions<commit_after>//! Bindings to the client library `libwayland-server.so`
//!
//! The generated handle is named `WAYLAND_SERVER_HANDLE`

use super::common::*;
use libc::{gid_t, pid_t, uid_t};
use std::os::raw::{c_char, c_int, c_void};

pub enum wl_client { }
pub enum wl_display { }
pub enum wl_event_loop { }
pub enum wl_event_source { }
pub enum wl_global { }
pub enum wl_resource { }
pub enum wl_shm_buffer { }

pub type wl_event_loop_fd_func_t = unsafe extern "C" fn(c_int, u32, *mut c_void) -> c_int;
pub type wl_event_loop_timer_func_t = unsafe extern "C" fn(*mut c_void) -> c_int;
pub type wl_event_loop_signal_func_t = unsafe extern "C" fn(c_int, *mut c_void) -> c_int;
pub type wl_event_loop_idle_func_t = unsafe extern "C" fn(*mut c_void) -> ();
pub type wl_global_bind_func_t = unsafe extern "C" fn(*mut wl_client, *mut c_void, u32, u32) -> ();
pub type wl_notify_func_t = unsafe extern "C" fn(*mut wl_listener, *mut c_void) -> ();
pub type wl_resource_destroy_func_t = unsafe extern "C" fn(*mut wl_resource) -> ();

#[repr(C)]
pub struct wl_listener {
    pub link: wl_list,
    pub notify: wl_notify_func_t
}

#[repr(C)]
pub struct wl_signal {
    pub listener_list: wl_list
}

external_library!(WaylandServer, "wayland-server",
    functions:
    // wl_client
        fn wl_client_flush(*mut wl_client) -> (),
        fn wl_client_destroy(*mut wl_client) -> (),
        fn wl_client_get_display(*mut wl_client) -> *mut wl_display,
        fn wl_client_get_credentials(*mut wl_client, *mut pid_t, *mut uid_t, *mut gid_t) -> (),
        fn wl_client_get_object(*mut wl_client, u32) -> *mut wl_resource,
        fn wl_client_add_destroy_listener(*mut wl_client, *mut wl_listener) -> (),
        fn wl_client_get_destroy_listener(*mut wl_client, wl_notify_func_t) -> *mut wl_listener,
        fn wl_client_post_no_memory(*mut wl_client) -> (),
        fn wl_resource_create(*mut wl_client, *const wl_interface, c_int, u32) -> *mut wl_resource,
    // wl_display
        fn wl_client_create(*mut wl_display, c_int) -> *mut wl_client,
        fn wl_display_create() -> *mut wl_display,
        fn wl_display_destroy(*mut wl_display) -> (),
        fn wl_display_get_serial(*mut wl_display) -> u32,
        fn wl_display_next_serial(*mut wl_display) -> u32,
        fn wl_display_add_socket(*mut wl_display, *const c_char) -> c_int,
        fn wl_display_add_socket_auto(*mut wl_display) -> *const c_char,
        fn wl_display_add_socket_fd(*mut wl_display, c_int) -> c_int,
        fn wl_display_add_shm_format(*mut wl_display, u32) -> *mut u32,
        fn wl_display_get_event_loop(*mut wl_display) -> *mut wl_event_loop,
        fn wl_display_terminate(*mut wl_display) -> (),
        fn wl_display_run(*mut wl_display) -> (),
        fn wl_display_flush_clients(*mut wl_display) -> (),
        fn wl_display_add_destroy_listener(*mut wl_display, *mut wl_listener) -> (),
        fn wl_display_get_destroy_listener(*mut wl_display, wl_notify_func_t) -> *mut wl_listener,
        fn wl_global_create(*mut wl_display, *const wl_interface, c_int, *mut c_void, wl_global_bind_func_t) -> *mut wl_global,
        fn wl_display_init_shm(*mut wl_display) -> c_int,
    // wl_event_loop
        fn wl_event_loop_create() -> *mut wl_event_loop,
        fn wl_event_loop_destroy(*mut wl_event_loop) -> (),
        fn wl_event_loop_add_fd(*mut wl_event_loop, c_int, u32, wl_event_loop_fd_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_add_timer(*mut wl_event_loop, wl_event_loop_timer_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_add_signal(*mut wl_event_loop, c_int, wl_event_loop_signal_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_dispatch(*mut wl_event_loop, c_int) -> c_int,
        fn wl_event_loop_dispatch_idle(*mut wl_event_loop) -> (),
        fn wl_event_loop_add_idle(*mut wl_event_loop, wl_event_loop_idle_func_t, *mut c_void) -> *mut wl_event_source,
        fn wl_event_loop_get_fd(*mut wl_event_loop) -> c_int,
        fn wl_event_loop_add_destroy_listener(*mut wl_event_loop, *mut wl_listener) -> (),
        fn wl_event_loop_get_destroy_listener(*mut wl_event_loop, wl_notify_func_t) -> *mut wl_listener,
    // wl_event_source
        fn wl_event_source_fd_update(*mut wl_event_source, u32) -> c_int,
        fn wl_event_source_timer_update(*mut wl_event_source, c_int) -> c_int,
        fn wl_event_source_remove(*mut wl_event_source) -> c_int,
        fn wl_event_source_check(*mut wl_event_source) -> (),
    // wl_global
        fn wl_global_destroy(*mut wl_global) -> (),
    // wl_resource
        fn wl_resource_post_event_array(*mut wl_resource, u32, *mut wl_argument) -> (),
        fn wl_resource_queue_event_array(*mut wl_resource, u32, *mut wl_argument) -> (),
        fn wl_resource_post_no_memory(*mut wl_resource) -> (),
        fn wl_resource_set_implementation(*mut wl_resource, *const c_void, *mut c_void, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_set_dispatcher(*mut wl_resource, wl_dispatcher_func_t, *const c_void, *mut c_void, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_destroy(*mut wl_resource) -> (),
        fn wl_resource_get_client(*mut wl_resource) -> *mut wl_client,
        fn wl_resource_get_id(*mut wl_resource) -> u32,
        fn wl_resource_get_link(*mut wl_resource) -> *mut wl_list,
        fn wl_resource_from_link(*mut wl_list) -> *mut wl_resource,
        fn wl_resource_find_for_client(*mut wl_list, *mut wl_client) -> (),
        fn wl_resource_set_user_data(*mut wl_resource, *mut c_void) -> (),
        fn wl_resource_get_user_data(*mut wl_resource) -> *mut c_void,
        fn wl_resource_get_version(*mut wl_resource) -> c_int,
        fn wl_resource_set_destructor(*mut wl_resource, Option<wl_resource_destroy_func_t>) -> (),
        fn wl_resource_instance_of(*mut wl_resource, *const wl_interface, *const c_void) -> c_int,
        fn wl_resource_add_destroy_listener(*mut wl_resource, wl_notify_func_t) -> (),
        fn wl_resource_get_destroy_listener(*mut wl_resource,wl_notify_func_t) -> *mut wl_listener,
    // wl_shm
        fn wl_shm_buffer_begin_access(*mut wl_shm_buffer) -> (),
        fn wl_shm_buffer_end_access(*mut wl_shm_buffer) -> (),
        fn wl_shm_buffer_get(*mut wl_resource) -> *mut wl_shm_buffer,
        fn wl_shm_buffer_get_data(*mut wl_shm_buffer) -> *mut c_void,
        fn wl_shm_buffer_get_stride(*mut wl_shm_buffer) -> i32,
        fn wl_shm_buffer_get_format(*mut wl_shm_buffer) -> u32,
        fn wl_shm_buffer_get_width(*mut wl_shm_buffer) -> i32,
        fn wl_shm_buffer_get_height(*mut wl_shm_buffer) -> i32,
    // wl_log
        fn wl_log_set_handler_server(wl_log_func_t) -> (),
    // wl_list
        fn wl_list_init(*mut wl_list) -> (),
        fn wl_list_insert(*mut wl_list, *mut wl_list) -> (),
        fn wl_list_remove(*mut wl_list) -> (),
        fn wl_list_length(*const wl_list) -> c_int,
        fn wl_list_empty(*const wl_list) -> c_int,
        fn wl_list_insert_list(*mut wl_list,*mut wl_list) -> (),

    // arrays
        fn wl_array_init(*mut wl_array) -> (),
        fn wl_array_release(*mut wl_array) -> (),
        fn wl_array_add(*mut wl_array,usize) -> (),
        fn wl_array_copy(*mut wl_array, *mut wl_array) -> (),
    varargs:
        fn wl_resource_post_event(*mut wl_resource, u32) -> (),
        fn wl_resource_queue_event(*mut wl_resource, u32) -> (),
        fn wl_resource_post_error(*mut wl_resource, u32, *const c_char) -> (),
);

#[cfg(feature = "dlopen")]
lazy_static!(
    pub static ref WAYLAND_SERVER_OPTION: Option<WaylandServer> = {
        match WaylandServer::open("libwayland-server.so") {
            Ok(h) => Some(h),
            Err(::dlib::DlError::NotFound) => None,
            Err(::dlib::DlError::MissingSymbol(s)) => {
                use std::io::Write;
                let _ = write!(::std::io::stderr(),
                               "[wayland-server] Found library libwayland-server.so cannot be used: symbol {} is missing.",
                               s);
                None
            }
        }
    };
    pub static ref WAYLAND_SERVER_HANDLE: &'static WaylandServer = {
        WAYLAND_SERVER_OPTION.as_ref().expect("Library libwayland-server.so could not be loaded.")
    };
);

#[cfg(not(feature = "dlopen"))]
pub fn is_lib_available() -> bool {
    true
}
#[cfg(feature = "dlopen")]
pub fn is_lib_available() -> bool {
    WAYLAND_SERVER_OPTION.is_some()
}

pub mod signal {
    #[cfg(feature = "dlopen")]
    use super::WAYLAND_SERVER_HANDLE as WSH;
    #[cfg(not(feature = "dlopen"))]
    use super::{wl_list_init, wl_list_insert};
    use super::{wl_signal, wl_listener, wl_notify_func_t};
    use common::wl_list;
    use std::os::raw::c_void;

    // TODO: Is this really not UB ?
    macro_rules! offset_of(
        ($ty:ty, $field:ident) => {
            &(*(0 as *const $ty)).$field as *const _ as usize
        }
    );

    macro_rules! container_of(
        ($ptr: expr, $container: ty, $field: ident) => {
            ($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
        }
    );

    macro_rules! list_for_each(
        ($pos: ident, $head:expr, $container: ty, $field: ident, $action: block) => {
            let mut $pos = container_of!((*$head).next, $container, $field);
            while &mut (*$pos).$field as *mut _ != $head {
                $action;
                $pos = container_of!((*$pos).$field.next, $container, $field);
            }
        }
    );

    macro_rules! list_for_each_safe(
        ($pos: ident, $head: expr, $container: ty, $field: ident, $action: block) => {
            let mut $pos = container_of!((*$head).next, $container, $field);
            let mut tmp = container_of!((*$pos).$field.next, $container, $field);
            while &mut (*$pos).$field as *mut _ != $head {
                $action;
                $pos = tmp;
                tmp = container_of!((*$pos).$field.next, $container, $field);
            }
        }
    );

    pub unsafe fn wl_signal_init(signal: *mut wl_signal) {
        ffi_dispatch!(WSH, wl_list_init, &mut (*signal).listener_list);
    }

    pub unsafe fn wl_signal_add(signal: *mut wl_signal, listener: *mut wl_listener) {
        ffi_dispatch!(WSH, wl_list_insert, (*signal).listener_list.prev, &mut (*listener).link)
    }

    pub unsafe fn wl_signal_get(signal: *mut wl_signal, notify: wl_notify_func_t) -> *mut wl_listener {
        list_for_each!(l, &mut (*signal).listener_list as *mut wl_list, wl_listener, link, {
            if (*l).notify == notify {
                return l;
            }
        });
        return ::std::ptr::null_mut();
    }

    pub unsafe fn wl_signal_emit(signal: *mut wl_signal, data: *mut c_void) {
        list_for_each_safe!(l, &mut (*signal).listener_list as *mut wl_list, wl_listener, link, {
            ((*l).notify)(l, data);
        });
    }
}
<|endoftext|>