<commit_before>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj: TraitObject = mem::transmute(&error as &dyn StdError);
            let vtable = obj.vtable;
            let inner = ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            };
            Error {
                inner: mem::transmute(Box::new(inner)),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        unsafe {
            mem::transmute(TraitObject {
                data: &self.error,
                vtable: self.vtable,
            })
        }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        unsafe {
            mem::transmute(TraitObject {
                data: &mut self.error,
                vtable: self.vtable,
            })
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

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

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[allow(dead_code)]
    fn assert_error_autotraits()
    where
        Error: Unpin + Send + Sync + 'static,
    {
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<commit_msg>Specify generic params on every transmute<commit_after>use crate::context::ContextError;
use std::any::TypeId;
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` functions a lot like `Box<dyn std::error::Error>`, with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`
/// - `Error` guarantees that a backtrace will exist, even if the error type
///   did not provide one
/// - `Error` is represented as a narrow pointer - exactly one word in size,
///   instead of two.
pub struct Error {
    inner: Box<ErrorImpl<()>>,
}

impl Error {
    /// Create a new error object from any error type.
    ///
    /// The error type must be threadsafe and `'static`, so that the `Error`
    /// will be as well.
    ///
    /// If the error type does not provide a backtrace, a backtrace will be
    /// created here to ensure that a backtrace exists.
    pub fn new<E>(error: E) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        Error::construct(error, TypeId::of::<E>())
    }

    #[doc(hidden)]
    pub fn new_adhoc<M>(message: M) -> Self
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::construct(MessageError(message), TypeId::of::<M>())
    }

    fn construct<E>(error: E, type_id: TypeId) -> Self
    where
        E: StdError + Send + Sync + 'static,
    {
        let backtrace = match error.backtrace() {
            Some(_) => None,
            None => Some(Backtrace::capture()),
        };

        unsafe {
            let obj = mem::transmute::<&dyn StdError, TraitObject>(&error);
            let vtable = obj.vtable;
            let inner = Box::new(ErrorImpl {
                vtable,
                type_id,
                backtrace,
                error,
            });
            Error {
                inner: mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner),
            }
        }
    }

    /// Wrap the error value with additional context.
    pub fn context<C>(self, context: C) -> Self
    where
        C: Display + Send + Sync + 'static,
    {
        Error::from(ContextError {
            error: self,
            context,
        })
    }

    /// View this error object as the underlying error.
    pub fn as_dyn_error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        &**self
    }

    /// View this error object as the underlying error, mutably.
    pub fn as_dyn_error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        &mut **self
    }

    /// Get the backtrace for this Error.
    pub fn backtrace(&self) -> &Backtrace {
        // NB: this unwrap can only fail if the underlying error's backtrace
        // method is nondeterministic, which would only happen in maliciously
        // constructed code
        self.inner
            .backtrace
            .as_ref()
            .or_else(|| self.inner.error().backtrace())
            .expect("backtrace capture failed")
    }

    /// An iterator of the chain of source errors contained by this Error.
    ///
    /// This iterator will visit every error in the cause chain of this error
    /// object, beginning with the error that this error object was created
    /// from.
    pub fn chain(&self) -> Chain {
        Chain {
            next: Some(self.inner.error()),
        }
    }

    /// Returns `true` if `E` is the type wrapped by this error object.
    pub fn is<E>(&self) -> bool
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        TypeId::of::<E>() == self.inner.type_id
    }

    /// Attempt to downcast the error object to a concrete type.
    pub fn downcast<E>(self) -> Result<E, Self>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if let Some(error) = self.downcast_ref::<E>() {
            unsafe {
                let error = ptr::read(error);
                drop(ptr::read(&self.inner));
                mem::forget(self);
                Ok(error)
            }
        } else {
            Err(self)
        }
    }

    /// Downcast this error object by reference.
    pub fn downcast_ref<E>(&self) -> Option<&E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&*(self.inner.error() as *const dyn StdError as *const E)) }
        } else {
            None
        }
    }

    /// Downcast this error object by mutable reference.
    pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
    where
        E: Display + Debug + Send + Sync + 'static,
    {
        if self.is::<E>() {
            unsafe { Some(&mut *(self.inner.error_mut() as *mut dyn StdError as *mut E)) }
        } else {
            None
        }
    }
}

impl<E> From<E> for Error
where
    E: StdError + Send + Sync + 'static,
{
    fn from(error: E) -> Self {
        Error::new(error)
    }
}

impl Deref for Error {
    type Target = dyn StdError + Send + Sync + 'static;
    fn deref(&self) -> &Self::Target {
        self.inner.error()
    }
}

impl DerefMut for Error {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.inner.error_mut()
    }
}

impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self.inner.error())?;

        let mut errors = self.chain().skip(1).enumerate();

        if let Some((n, error)) = errors.next() {
            writeln!(f, "\ncaused by:")?;
            writeln!(f, "\t{}: {}", n, error)?;
            for (n, error) in errors {
                writeln!(f, "\t{}: {}", n, error)?;
            }
        }

        let backtrace = self.backtrace();

        match backtrace.status() {
            BacktraceStatus::Captured => {
                writeln!(f, "\n{}", backtrace)?;
            }
            BacktraceStatus::Disabled => {
                writeln!(
                    f,
                    "\nbacktrace disabled; run with RUST_BACKTRACE=1 environment variable to display a backtrace"
                )?;
            }
            _ => {}
        }

        Ok(())
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.inner.error())
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ptr::drop_in_place(self.inner.error_mut()) }
    }
}

// repr C to ensure that `E` remains in the final position
#[repr(C)]
struct ErrorImpl<E> {
    vtable: *const (),
    type_id: TypeId,
    backtrace: Option<Backtrace>,
    error: E,
}

// repr C to ensure that transmuting from trait objects is safe
#[repr(C)]
struct TraitObject {
    data: *const (),
    vtable: *const (),
}

#[repr(transparent)]
struct MessageError<M>(M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

impl ErrorImpl<()> {
    fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &self.error,
            vtable: self.vtable,
        };

        unsafe { mem::transmute::<TraitObject, &(dyn StdError + Send + Sync + 'static)>(object) }
    }

    fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
        let object = TraitObject {
            data: &mut self.error,
            vtable: self.vtable,
        };

        unsafe {
            mem::transmute::<TraitObject, &mut (dyn StdError + Send + Sync + 'static)>(object)
        }
    }
}

/// Iterator of a chain of source errors.
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

impl<'a> Iterator for Chain<'a> {
    type Item = &'a (dyn StdError + 'static);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next.take()?;
        self.next = next.source();
        Some(next)
    }
}

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

    use std::marker::Unpin;
    use std::mem;

    #[test]
    fn size_of_error() {
        assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
    }

    #[allow(dead_code)]
    fn assert_error_autotraits()
    where
        Error: Unpin + Send + Sync + 'static,
    {
    }

    #[test]
    fn destructors_work() {
        use std::sync::*;

        #[derive(Debug)]
        struct HasDrop(Box<Arc<Mutex<bool>>>);
        impl StdError for HasDrop {}
        impl Display for HasDrop {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "does something")
            }
        }
        impl Drop for HasDrop {
            fn drop(&mut self) {
                let mut has_dropped = self.0.lock().unwrap();
                assert!(!*has_dropped);
                *has_dropped = true;
            }
        }

        let has_dropped = Arc::new(Mutex::new(false));

        drop(Error::from(HasDrop(Box::new(has_dropped.clone()))));

        assert!(*has_dropped.lock().unwrap());
    }
}
<|endoftext|>


<commit_before>use ffi;
use libc::{c_uint, c_int, c_void};
use num::complex::Complex64;

use plan::RawPlan;

/// How much effort FFTW should put into computing the best strategy
/// to use.
///
/// The `FFTW_WISDOM_ONLY` rigor level is replaced by the
pub enum Rigor {
    Estimate,
    Measure,
    Patient,
    Exhaustive,
}
impl Rigor {
    fn flags(self) -> c_uint {
        match self {
            Estimate => ffi::FFTW_ESTIMATE,
            Measure => ffi::FFTW_MEASURE,
            Patient => ffi::FFTW_PATIENT,
            Exhaustive => ffi::FFTW_EXHAUSTIVE,
        }
    }
}

/// The direction of the transform to perform..
pub enum Direction {
    Forward, Backward
}

/// Control the basic properties of a set of transforms.
pub struct Planner {
    rigor: Rigor,
    wisdom_restriction: bool,
    direction: Direction,
}

impl Planner {
    /// Construct a new planner with default values.
    ///
    /// This defaults to a forward transform with estimate rigor.
    pub fn new() -> Planner {
        Planner {
            rigor: Estimate,
            wisdom_restriction: false,
            direction: Forward,
        }
    }

    /// Set the rigor to use for this plan.
    pub fn rigor(&mut self, r: Rigor) -> &mut Planner {
        self.rigor = r;
        self
    }
    /// Set whether the planner should only be successfully created if
    /// there exists wisdom created with at least the rigor level set.
    pub fn wisdom_restriction(&mut self, wisdom_only: bool) -> &mut Planner {
        self.wisdom_restriction = wisdom_only;
        self
    }

    /// Set the direction of the transform to perform.
    pub fn direction(&mut self, direction: Direction) -> &mut Planner {
        self.direction = direction;
        self
    }

    fn flags(&self) -> c_uint {
        self.rigor.flags() | if self.wisdom_restriction {
            ffi::FFTW_WISDOM_ONLY
        } else {
            0
        }
    }
    fn dir(&self) -> c_int {
        match self.direction {
            Forward => ffi::FFTW_FORWARD,
            Backward => ffi::FFTW_BACKWARD,
        }
    }

    pub fn inplace(&self) -> InPlacePlanner {
        InPlacePlanner { plan: *self }
    }

    pub fn c2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: c2c,
        }
    }
    pub fn c2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len() / 2 + 1);
        PlanMem {
            plan: *self,
            n: 2 * (in_.len() as c_int - 1),
            in_: in_,
            out: Some(out),
            planner: c2r,
        }
    }
    pub fn r2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() / 2 + 1 <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2c,
        }
    }
    #[cfg(r2r_is_hard)]
    pub fn r2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2r,
        }
    }
}

pub struct InPlacePlanner {
    plan: Planner
}

impl InPlacePlanner {
    pub fn c2c<I>(&self, in_: I) -> PlanMem<I, I>
        where I: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= 0xFF_FF_FF_FF);
        PlanMem {
            plan: self.plan,
            n: in_.len() as c_int,
            in_: in_,
            out: None,
            planner: c2c,
        }
    }
}

unsafe fn c2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_1d(n,
                          in_ as *mut ffi::fftw_complex, out as *mut ffi::fftw_complex,
                          sign, flags)
}
unsafe fn r2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_r2c_1d(n,
                              in_ as *mut f64, out as *mut ffi::fftw_complex,
                              flags)
}
unsafe fn c2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_c2r_1d(n,
                              in_ as *mut ffi::fftw_complex, out as *mut f64,
                              flags)
}
#[cfg(r2r_is_hard)]
unsafe fn r2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_r2r_1d(n,
                          in_ as *mut f64, out as *mut f64,
                          sign, flags)
}

pub struct PlanMem<I, O> {
    plan: Planner,
    n: c_int,
    in_: I,
    out: Option<O>,
    planner: unsafe fn(c_int, *mut c_void, *mut c_void, c_int, c_uint) -> ffi::fftw_plan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> PlanMem<I, O> {
    pub fn plan(mut self) -> Result<Planned<I, O>, PlanMem<I, O>> {
        let in_ptr = self.in_.as_mut_ptr() as *mut c_void;
        let out_ptr = match self.out {
            None => in_ptr,
            Some(ref mut o) => o.as_mut_ptr() as *mut c_void,
        };

        let plan = RawPlan::new(|| unsafe {
            (self.planner)(self.n,
                           in_ptr,
                           out_ptr,
                           self.plan.dir(),
                           self.plan.flags())
        });

        match plan {
            None => Err(self),
            Some(p) => Ok(Planned { mem: self, plan: p })
        }
    }
}

pub struct Planned<I, O> {
    mem: PlanMem<I, O>,
    plan: RawPlan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> Planned<I, O> {
    pub fn input(&mut self) -> &mut [X] {
        &mut *self.mem.in_
    }
    pub fn output(&mut self) -> Option<&mut [Y]> {
        self.mem.out.as_mut().map(|o| &mut **o)
    }

    pub fn execute(&mut self) {
        unsafe {
            self.plan.execute()
        }
    }
}
<commit_msg>More assertions.<commit_after>use ffi;
use libc::{c_uint, c_int, c_void};
use num::complex::Complex64;

use plan::RawPlan;

/// How much effort FFTW should put into computing the best strategy
/// to use.
///
/// The `FFTW_WISDOM_ONLY` rigor level is replaced by the
pub enum Rigor {
    Estimate,
    Measure,
    Patient,
    Exhaustive,
}
impl Rigor {
    fn flags(self) -> c_uint {
        match self {
            Estimate => ffi::FFTW_ESTIMATE,
            Measure => ffi::FFTW_MEASURE,
            Patient => ffi::FFTW_PATIENT,
            Exhaustive => ffi::FFTW_EXHAUSTIVE,
        }
    }
}

/// The direction of the transform to perform..
pub enum Direction {
    Forward, Backward
}

/// Control the basic properties of a set of transforms.
pub struct Planner {
    rigor: Rigor,
    wisdom_restriction: bool,
    direction: Direction,
}

impl Planner {
    /// Construct a new planner with default values.
    ///
    /// This defaults to a forward transform with estimate rigor.
    pub fn new() -> Planner {
        Planner {
            rigor: Estimate,
            wisdom_restriction: false,
            direction: Forward,
        }
    }

    /// Set the rigor to use for this plan.
    pub fn rigor(&mut self, r: Rigor) -> &mut Planner {
        self.rigor = r;
        self
    }
    /// Set whether the planner should only be successfully created if
    /// there exists wisdom created with at least the rigor level set.
    pub fn wisdom_restriction(&mut self, wisdom_only: bool) -> &mut Planner {
        self.wisdom_restriction = wisdom_only;
        self
    }

    /// Set the direction of the transform to perform.
    pub fn direction(&mut self, direction: Direction) -> &mut Planner {
        self.direction = direction;
        self
    }

    fn flags(&self) -> c_uint {
        self.rigor.flags() | if self.wisdom_restriction {
            ffi::FFTW_WISDOM_ONLY
        } else {
            0
        }
    }
    fn dir(&self) -> c_int {
        match self.direction {
            Forward => ffi::FFTW_FORWARD,
            Backward => ffi::FFTW_BACKWARD,
        }
    }

    pub fn inplace(&self) -> InPlacePlanner {
        InPlacePlanner { plan: *self }
    }

    pub fn c2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= 0x7F_FF_FF_FF);
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: c2c,
        }
    }
    pub fn c2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[Complex64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= 0x7F_FF_FF_FF);
        assert!(in_.len() <= out.len() / 2 + 1);
        PlanMem {
            plan: *self,
            n: 2 * (in_.len() as c_int - 1),
            in_: in_,
            out: Some(out),
            planner: c2r,
        }
    }
    pub fn r2c<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= 0x7F_FF_FF_FF);
        assert!(in_.len() / 2 + 1 <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2c,
        }
    }
    #[cfg(r2r_is_hard)]
    pub fn r2r<I, O>(&self, in_: I, out: O) -> PlanMem<I, O>
        where I: DerefMut<[f64]>, O: DerefMut<[f64]>
    {
        assert!(in_.len() <= 0x7F_FF_FF_FF);
        assert!(in_.len() <= out.len());
        PlanMem {
            plan: *self,
            n: in_.len() as c_int,
            in_: in_,
            out: Some(out),
            planner: r2r,
        }
    }
}

pub struct InPlacePlanner {
    plan: Planner
}

impl InPlacePlanner {
    pub fn c2c<I>(&self, in_: I) -> PlanMem<I, I>
        where I: DerefMut<[Complex64]>
    {
        assert!(in_.len() <= 0x7F_FF_FF_FF);
        PlanMem {
            plan: self.plan,
            n: in_.len() as c_int,
            in_: in_,
            out: None,
            planner: c2c,
        }
    }
}

unsafe fn c2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_1d(n,
                          in_ as *mut ffi::fftw_complex, out as *mut ffi::fftw_complex,
                          sign, flags)
}
unsafe fn r2c(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_r2c_1d(n,
                              in_ as *mut f64, out as *mut ffi::fftw_complex,
                              flags)
}
unsafe fn c2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              _sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_dft_c2r_1d(n,
                              in_ as *mut ffi::fftw_complex, out as *mut f64,
                              flags)
}
#[cfg(r2r_is_hard)]
unsafe fn r2r(n: c_int, in_: *mut c_void, out: *mut c_void,
              sign: c_int, flags: c_uint) -> ffi::fftw_plan {
    ffi::fftw_plan_r2r_1d(n,
                          in_ as *mut f64, out as *mut f64,
                          sign, flags)
}

pub struct PlanMem<I, O> {
    plan: Planner,
    n: c_int,
    in_: I,
    out: Option<O>,
    planner: unsafe fn(c_int, *mut c_void, *mut c_void, c_int, c_uint) -> ffi::fftw_plan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> PlanMem<I, O> {
    pub fn plan(mut self) -> Result<Planned<I, O>, PlanMem<I, O>> {
        let in_ptr = self.in_.as_mut_ptr() as *mut c_void;
        let out_ptr = match self.out {
            None => in_ptr,
            Some(ref mut o) => o.as_mut_ptr() as *mut c_void,
        };

        let plan = RawPlan::new(|| unsafe {
            (self.planner)(self.n,
                           in_ptr,
                           out_ptr,
                           self.plan.dir(),
                           self.plan.flags())
        });

        match plan {
            None => Err(self),
            Some(p) => Ok(Planned { mem: self, plan: p })
        }
    }
}

pub struct Planned<I, O> {
    mem: PlanMem<I, O>,
    plan: RawPlan,
}

impl<X, Y, I: DerefMut<[X]>, O: DerefMut<[Y]>> Planned<I, O> {
    pub fn input(&mut self) -> &mut [X] {
        &mut *self.mem.in_
    }
    pub fn output(&mut self) -> Option<&mut [Y]> {
        self.mem.out.as_mut().map(|o| &mut **o)
    }

    pub fn execute(&mut self) {
        unsafe {
            self.plan.execute()
        }
    }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::fmt;

/// Errors that can be return from various operatiors
///
#[derive(Debug)]
pub enum Error {
    /// Returned if menu Menu function isn't supported
    MenusNotSupported,
    /// Menu already exists
    MenuExists(String),
    /// Menu already exists
    WindowCreate(String),
    /// Unable to Update
    UpdateFailed(String),
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::MenusNotSupported => "Menus not supported",
            Error::MenuExists(_) => "Menu already exists",
            Error::WindowCreate(_) => "Failed to create window",
            Error::UpdateFailed(_) => "Failed to Update",
        }
    }

    fn cause(&self) -> Option<&dyn StdError> {
        match *self {
            Error::MenusNotSupported => None,
            Error::MenuExists(_) => None,
            Error::WindowCreate(_) => None,
            Error::UpdateFailed(_) => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::MenusNotSupported => write!(fmt, "{}", self.description()),
            Error::MenuExists(ref e) => write!(fmt, "{} {:?}", self.description(), e),
            Error::WindowCreate(ref e) => write!(fmt, "{} {:?}", self.description(), e),
            Error::UpdateFailed(ref e) => write!(fmt, "{} {:?}", self.description(), e),
        }
    }
}
<commit_msg>Change Error to use custom fmt::Debug messages (#152)<commit_after>use std::fmt;

/// Errors that can be returned from various operations
///
pub enum Error {
    /// Returned if menu Menu function isn't supported
    MenusNotSupported,
    /// Menu already exists
    MenuExists(String),
    /// Menu already exists
    WindowCreate(String),
    /// Unable to Update
    UpdateFailed(String),
}

impl fmt::Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::MenusNotSupported => write!(formatter, "Menus not supported"),
            Error::MenuExists(_) => write!(formatter, "Menu already exists"),
            Error::WindowCreate(_) => write!(formatter, "Failed to create window"),
            Error::UpdateFailed(_) => write!(formatter, "Failed to Update"),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::MenusNotSupported => write!(fmt, "{:?}", self),
            Error::MenuExists(ref e) => write!(fmt, "{:?} {:?}", self, e),
            Error::WindowCreate(ref e) => write!(fmt, "{:?} {:?}", self, e),
            Error::UpdateFailed(ref e) => write!(fmt, "{:?} {:?}", self, e),
        }
    }
}
<|endoftext|>


<commit_before>use error_chain::ChainedError;
use ffmpeg::{format, Rational};
use ffmpeg::frame::Video as VideoFrame;
use fine_grained::Stopwatch;
use std::cell::RefCell;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Mutex, RwLock, Once, ONCE_INIT};
use std::thread;

use encode;
use errors::*;

lazy_static! {
    static ref CAPTURING: RwLock<bool> = RwLock::new(false);

    static ref ENCODER: Mutex<Option<encode::Encoder>> = Mutex::new(None);

    /// Receives buffers to write pixels to.
    static ref BUF_RECEIVER: Mutex<Option<Receiver<Buffer>>> = Mutex::new(None);

    /// Sends events and frames to encode to the capture thread.
    static ref SEND_TO_CAPTURE_THREAD: Mutex<Option<Sender<CaptureThreadEvent>>> = Mutex::new(None);
}

thread_local! {
    static STOPWATCH: RefCell<Option<Stopwatch>> = RefCell::new(None);
}

struct CaptureParameters {
    filename: String,
    time_base: Rational,
    crf: String,
    preset: String,
}

enum CaptureThreadEvent {
    CaptureStart(CaptureParameters),
    CaptureStop,
    Frame(Buffer),
}

pub struct Buffer {
    data: Vec<u8>,
    width: u32,
    height: u32,
}

impl Buffer {
    fn new() -> Self {
        Self {
            data: Vec::new(),
            width: 0,
            height: 0,
        }
    }

    pub fn set_resolution(&mut self, width: u32, height: u32) {
        if self.width != width || self.height != height {
            println!("Changing resolution from {}×{} to {}×{}.",
                     self.width, self.height,
                     width, height);

            self.data.resize((width * height * 3) as usize, 0);
            self.width = width;
            self.height = height;
        }
    }

    pub fn as_mut_slice(&mut self) -> &mut [u8] {
        self.data.as_mut_slice()
    }

    pub fn copy_to_frame(&self, frame: &mut VideoFrame) {
        // Make sure frame is of correct size.
        if self.width != frame.width() || self.height != frame.height() {
            *frame = VideoFrame::new(format::Pixel::RGB24, self.width, self.height);
        }

        // Copy the pixel data into the frame.
        let linesize = unsafe { ((*frame.as_ptr()).linesize[0]) as u32 };
        let mut data = frame.data_mut(0);

        for y in 0..self.height {
            unsafe {
                ptr::copy_nonoverlapping(self.data.as_ptr().offset((y * self.width * 3) as isize),
                                         data.as_mut_ptr()
                                             .offset(((self.height - y - 1) * linesize) as
                                                     isize),
                                         (self.width * 3) as usize);
            }
        }
    }
}

fn capture_thread(buf_sender: Sender<Buffer>, event_receiver: Receiver<CaptureThreadEvent>) {
    // Send the buffer to the game thread right away.
    buf_sender.send(Buffer::new()).unwrap();

    // This is our frame which will only be reallocated on resolution changes.
    let mut frame = VideoFrame::empty();

    // This is set to true on encoding error or cap_stop and reset on cap_start.
    // When this is true, ignore any received frames.
    let mut drop_frames = true;

    // Encoding parameters, set on CaptureStart.
    let mut parameters = None;

    // Event loop for the capture thread.
    loop {
        match event_receiver.recv().unwrap() {
            CaptureThreadEvent::CaptureStart(params) => {
                drop_frames = false;
                parameters = Some(params);
            }

            CaptureThreadEvent::CaptureStop => {
                *ENCODER.lock().unwrap() = None;
                drop_frames = true;
            }

            CaptureThreadEvent::Frame(buffer) => {
                if drop_frames {
                    continue;
                }

                if let Err(ref e) = encode(buffer,
                                           &buf_sender,
                                           parameters.as_ref().unwrap(),
                                           &mut frame) {
                    *CAPTURING.write().unwrap() = false;
                    drop_frames = true;
                    println!("Encoding error: {}", e.display());
                }
            }
        }
    }
}

fn start_encoder(filename: &str,
                 (width, height): (u32, u32),
                 time_base: Rational,
                 crf: &str,
                 preset: &str) -> Result<encode::Encoder> {
    encode::Encoder::start(filename,
                           (width, height),
                           time_base,
                           crf,
                           preset)
}

fn encode(buf: Buffer,
          buf_sender: &Sender<Buffer>,
          parameters: &CaptureParameters,
          frame: &mut VideoFrame)
          -> Result<()> {
    buf.copy_to_frame(frame);

    // We're done with buf, now it can receive the next pack of pixels.
    buf_sender.send(buf).unwrap();

    // Let's encode the frame we just received.
    let mut encoder = ENCODER.lock().unwrap();

    // If the encoder wasn't initialized or if the frame size changed, initialize it.
    if encoder.as_ref()
              .map_or(true,
                      |enc| enc.width() != frame.width() || enc.height() != frame.height()) {
        *encoder = Some(start_encoder(&parameters.filename,
                                      (frame.width(), frame.height()),
                                      parameters.time_base,
                                      &parameters.crf,
                                      &parameters.preset)
                            .chain_err(|| "could not start the video encoder")?);
    }

    // Encode the frame.
    encoder.as_mut().unwrap().encode(&frame)
        .chain_err(|| "could not encode the frame")?;

    Ok(())
}

pub fn initialize() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        let (tx, rx) = channel::<Buffer>();
        let (tx2, rx2) = channel::<CaptureThreadEvent>();

        *BUF_RECEIVER.lock().unwrap() = Some(rx);
        *SEND_TO_CAPTURE_THREAD.lock().unwrap() = Some(tx2);

        thread::spawn(move || capture_thread(tx, rx2));
    });
}

pub fn get_buffer((width, height): (u32, u32)) -> Buffer {
    let mut buf = BUF_RECEIVER.lock().unwrap()
        .as_ref().unwrap()
        .recv().unwrap();

    buf.set_resolution(width, height);

    buf
}

pub fn capture(buf: Buffer) {
    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::Frame(buf)).unwrap();
}

pub fn is_capturing() -> bool {
    *CAPTURING.read().unwrap()
}

pub fn capture_block_start() {
    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().as_mut() {
        sw.start();
    });
}

pub fn capture_block_end() {
    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().as_mut() {
        sw.lap();
        sw.stop();
    });
}

command!(cap_start, |mut engine| {
    let mut parameters = CaptureParameters {
        filename: String::new(),
        time_base: Rational::new(1, 1),
        crf: String::new(),
        preset: String::new(),
    };

    cap_filename.with(|c| match c.to_string(&mut engine) {
        Ok(filename) => parameters.filename = filename,
        Err(_) => {
            engine.con_print("Invalid cap_filename.\n");
            return;
        }
    });
    cap_fps.with(|c| match c.parse(&mut engine) {
        Ok(fps) => parameters.time_base = (1, fps).into(),
        Err(_) => {
            engine.con_print("Invalid cap_fps.\n");
            return;
        }
    });
    cap_crf.with(|c| match c.parse(&mut engine) {
        Ok(crf) => parameters.crf = crf,
        Err(_) => {
            engine.con_print("Invalid cap_crf.\n");
            return;
        }
    });
    cap_preset.with(|c| match c.parse(&mut engine) {
        Ok(preset) => parameters.preset = preset,
        Err(_) => {
            engine.con_print("Invalid cap_preset.\n");
            return;
        }
    });

    *CAPTURING.write().unwrap() = true;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStart(parameters)).unwrap();

    STOPWATCH.with(|sw| *sw.borrow_mut() = Some(Stopwatch::new()));
});

command!(cap_stop, |engine| {
    *CAPTURING.write().unwrap() = false;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStop).unwrap();

    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().take() {
        let frames = sw.number_of_laps();

        if frames > 0 {
            engine.con_print(&format!("Captured {} frames in {} seconds (~{} msec of overhead per frame)\n",
                                      frames,
                                      sw.total_time() as f64 / 1_000_000_000f64,
                                      (sw.total_time() / frames as u64) as f64 / 1_000_000f64));
        }
    });
});

cvar!(cap_crf, "15");
cvar!(cap_filename, "capture.mp4");
cvar!(cap_fps, "60");
cvar!(cap_preset, "veryfast");
<commit_msg>Handle errors better in cap_start<commit_after>use error_chain::ChainedError;
use ffmpeg::{format, Rational};
use ffmpeg::frame::Video as VideoFrame;
use fine_grained::Stopwatch;
use std::cell::RefCell;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Mutex, RwLock, Once, ONCE_INIT};
use std::thread;

use encode;
use errors::*;

lazy_static! {
    static ref CAPTURING: RwLock<bool> = RwLock::new(false);

    static ref ENCODER: Mutex<Option<encode::Encoder>> = Mutex::new(None);

    /// Receives buffers to write pixels to.
    static ref BUF_RECEIVER: Mutex<Option<Receiver<Buffer>>> = Mutex::new(None);

    /// Sends events and frames to encode to the capture thread.
    static ref SEND_TO_CAPTURE_THREAD: Mutex<Option<Sender<CaptureThreadEvent>>> = Mutex::new(None);
}

thread_local! {
    static STOPWATCH: RefCell<Option<Stopwatch>> = RefCell::new(None);
}

struct CaptureParameters {
    filename: String,
    time_base: Rational,
    crf: String,
    preset: String,
}

enum CaptureThreadEvent {
    CaptureStart(CaptureParameters),
    CaptureStop,
    Frame(Buffer),
}

pub struct Buffer {
    data: Vec<u8>,
    width: u32,
    height: u32,
}

impl Buffer {
    fn new() -> Self {
        Self {
            data: Vec::new(),
            width: 0,
            height: 0,
        }
    }

    pub fn set_resolution(&mut self, width: u32, height: u32) {
        if self.width != width || self.height != height {
            println!("Changing resolution from {}×{} to {}×{}.",
                     self.width, self.height,
                     width, height);

            self.data.resize((width * height * 3) as usize, 0);
            self.width = width;
            self.height = height;
        }
    }

    pub fn as_mut_slice(&mut self) -> &mut [u8] {
        self.data.as_mut_slice()
    }

    pub fn copy_to_frame(&self, frame: &mut VideoFrame) {
        // Make sure frame is of correct size.
        if self.width != frame.width() || self.height != frame.height() {
            *frame = VideoFrame::new(format::Pixel::RGB24, self.width, self.height);
        }

        // Copy the pixel data into the frame.
        let linesize = unsafe { ((*frame.as_ptr()).linesize[0]) as u32 };
        let mut data = frame.data_mut(0);

        for y in 0..self.height {
            unsafe {
                ptr::copy_nonoverlapping(self.data.as_ptr().offset((y * self.width * 3) as isize),
                                         data.as_mut_ptr()
                                             .offset(((self.height - y - 1) * linesize) as
                                                     isize),
                                         (self.width * 3) as usize);
            }
        }
    }
}

fn capture_thread(buf_sender: Sender<Buffer>, event_receiver: Receiver<CaptureThreadEvent>) {
    // Send the buffer to the game thread right away.
    buf_sender.send(Buffer::new()).unwrap();

    // This is our frame which will only be reallocated on resolution changes.
    let mut frame = VideoFrame::empty();

    // This is set to true on encoding error or cap_stop and reset on cap_start.
    // When this is true, ignore any received frames.
    let mut drop_frames = true;

    // Encoding parameters, set on CaptureStart.
    let mut parameters = None;

    // Event loop for the capture thread.
    loop {
        match event_receiver.recv().unwrap() {
            CaptureThreadEvent::CaptureStart(params) => {
                drop_frames = false;
                parameters = Some(params);
            }

            CaptureThreadEvent::CaptureStop => {
                *ENCODER.lock().unwrap() = None;
                drop_frames = true;
            }

            CaptureThreadEvent::Frame(buffer) => {
                if drop_frames {
                    continue;
                }

                if let Err(ref e) = encode(buffer,
                                           &buf_sender,
                                           parameters.as_ref().unwrap(),
                                           &mut frame) {
                    *CAPTURING.write().unwrap() = false;
                    drop_frames = true;
                    println!("Encoding error: {}", e.display());
                }
            }
        }
    }
}

fn start_encoder(filename: &str,
                 (width, height): (u32, u32),
                 time_base: Rational,
                 crf: &str,
                 preset: &str) -> Result<encode::Encoder> {
    encode::Encoder::start(filename,
                           (width, height),
                           time_base,
                           crf,
                           preset)
}

fn encode(buf: Buffer,
          buf_sender: &Sender<Buffer>,
          parameters: &CaptureParameters,
          frame: &mut VideoFrame)
          -> Result<()> {
    buf.copy_to_frame(frame);

    // We're done with buf, now it can receive the next pack of pixels.
    buf_sender.send(buf).unwrap();

    // Let's encode the frame we just received.
    let mut encoder = ENCODER.lock().unwrap();

    // If the encoder wasn't initialized or if the frame size changed, initialize it.
    if encoder.as_ref()
              .map_or(true,
                      |enc| enc.width() != frame.width() || enc.height() != frame.height()) {
        *encoder = Some(start_encoder(&parameters.filename,
                                      (frame.width(), frame.height()),
                                      parameters.time_base,
                                      &parameters.crf,
                                      &parameters.preset)
                            .chain_err(|| "could not start the video encoder")?);
    }

    // Encode the frame.
    encoder.as_mut().unwrap().encode(&frame)
        .chain_err(|| "could not encode the frame")?;

    Ok(())
}

pub fn initialize() {
    static INIT: Once = ONCE_INIT;
    INIT.call_once(|| {
        let (tx, rx) = channel::<Buffer>();
        let (tx2, rx2) = channel::<CaptureThreadEvent>();

        *BUF_RECEIVER.lock().unwrap() = Some(rx);
        *SEND_TO_CAPTURE_THREAD.lock().unwrap() = Some(tx2);

        thread::spawn(move || capture_thread(tx, rx2));
    });
}

pub fn get_buffer((width, height): (u32, u32)) -> Buffer {
    let mut buf = BUF_RECEIVER.lock().unwrap()
        .as_ref().unwrap()
        .recv().unwrap();

    buf.set_resolution(width, height);

    buf
}

pub fn capture(buf: Buffer) {
    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::Frame(buf)).unwrap();
}

pub fn is_capturing() -> bool {
    *CAPTURING.read().unwrap()
}

pub fn capture_block_start() {
    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().as_mut() {
        sw.start();
    });
}

pub fn capture_block_end() {
    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().as_mut() {
        sw.lap();
        sw.stop();
    });
}

command!(cap_start, |mut engine| {
    let mut parameters = CaptureParameters {
        filename: String::new(),
        time_base: Rational::new(1, 1),
        crf: String::new(),
        preset: String::new(),
    };

    match cap_filename.with(|c| c.to_string(&mut engine))
        .chain_err(|| "invalid cap_filename") {
        Ok(filename) => parameters.filename = filename,
        Err(ref e) => {
            engine.con_print(&format!("{}", e.display()));
            return;
        }
    };
    match cap_fps.with(|c| c.parse(&mut engine))
        .chain_err(|| "invalid cap_fps") {
        Ok(fps) => parameters.time_base = (1, fps).into(),
        Err(ref e) => {
            engine.con_print(&format!("{}", e.display()));
            return;
        }
    };
    match cap_crf.with(|c| c.parse(&mut engine))
        .chain_err(|| "invalid cap_crf") {
        Ok(crf) => parameters.crf = crf,
        Err(ref e) => {
            engine.con_print(&format!("{}", e.display()));
            return;
        }
    };
    match cap_preset.with(|c| c.parse(&mut engine))
        .chain_err(|| "invalid cap_preset") {
        Ok(preset) => parameters.preset = preset,
        Err(ref e) => {
            engine.con_print(&format!("{}", e.display()));
            return;
        }
    };

    *CAPTURING.write().unwrap() = true;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStart(parameters)).unwrap();

    STOPWATCH.with(|sw| *sw.borrow_mut() = Some(Stopwatch::new()));
});

command!(cap_stop, |engine| {
    *CAPTURING.write().unwrap() = false;

    SEND_TO_CAPTURE_THREAD.lock().unwrap()
        .as_ref().unwrap()
        .send(CaptureThreadEvent::CaptureStop).unwrap();

    STOPWATCH.with(|sw| if let Some(sw) = sw.borrow_mut().take() {
        let frames = sw.number_of_laps();

        if frames > 0 {
            engine.con_print(&format!("Captured {} frames in {} seconds (~{} msec of overhead per frame)\n",
                                      frames,
                                      sw.total_time() as f64 / 1_000_000_000f64,
                                      (sw.total_time() / frames as u64) as f64 / 1_000_000f64));
        }
    });
});

cvar!(cap_crf, "15");
cvar!(cap_filename, "capture.mp4");
cvar!(cap_fps, "60");
cvar!(cap_preset, "veryfast");
<|endoftext|>


<commit_before>// Copyright (c) Carl-Erwin Griffith
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

use crate::core::codec::text::utf8;
use crate::core::codepointinfo::CodepointInfo;
use crate::core::mark::Mark;
use crate::core::screen::Screen;
use crate::core::view::View;

pub fn get_lines_offsets<'a>(
    view: &View<'a>,
    start_offset: u64,
    end_offset: u64,
    screen_width: usize,
    screen_height: usize,
) -> Vec<(u64, u64)> {
    let mut v = Vec::<(u64, u64)>::new();

    let mut m = Mark::new(start_offset);

    let doc = view.document.as_ref().unwrap().borrow_mut();

    let screen_width = ::std::cmp::max(1, screen_width);
    let screen_height = ::std::cmp::max(4, screen_height);

    // get beginning of the line @offset
    m.move_to_beginning_of_line(&doc.buffer, utf8::get_prev_codepoint);

    // and build tmp screens until end_offset if found
    let mut screen = Screen::new(screen_width, screen_height);

    let max_offset = doc.buffer.size as u64;
    let max_size = (screen_width * screen_height * 4) as usize;

    loop {
        // fill screen
        let mut data = vec![];
        doc.buffer.read(m.offset, max_size, &mut data);

        let _ = build_screen_layout(&data, m.offset, max_offset, &mut screen);

        // push lines offsets
        // FIXME: find a better way to iterate over the used lines
        for i in 0..screen.current_line_index {
            if !v.is_empty() && i == 0 {
                // do not push line range twice
                continue;
            }

            let s = screen.line[i].get_first_cpi().unwrap().offset;
            let e = screen.line[i].get_last_cpi().unwrap().offset;

            v.push((s, e));

            if s >= end_offset || e == max_offset {
                return v;
            }
        }

        // eof reached ?
        // FIXME: the api is not yet READY
        // we must find a way to cover all filled lines
        if screen.current_line_index < screen.height {
            let s = screen.line[screen.current_line_index]
                .get_first_cpi()
                .unwrap()
                .offset;

            let e = screen.line[screen.current_line_index]
                .get_last_cpi()
                .unwrap()
                .offset;
            v.push((s, e));
            return v;
        }

        // TODO: activate only in debug builds
        if 0 == 1 {
            match screen.find_cpi_by_offset(m.offset) {
                (Some(cpi), x, y) => {
                    assert_eq!(x, 0);
                    assert_eq!(y, 0);
                    assert_eq!(cpi.offset, m.offset);
                }
                _ => panic!("implementation error"),
            }
        }

        if let Some(l) = screen.get_last_used_line() {
            if let Some(cpi) = l.get_first_cpi() {
                m.offset = cpi.offset; // update next screen start
            }
        }

        screen.clear(); // prepare next screen
    }
}

//////////////////////////////////
// This function will run the configured filters
// until the screen is full or eof is reached
// the filters will be configured per view to allow multiple interpretation of the same document
// data will be replaced by a "FileMMap"
pub fn build_screen_layout(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    screen: &mut Screen,
) -> u64 {
    let max_cpi = screen.width * screen.height;

    // utf8
    let (vec, _) = decode_slice_to_vec(data, base_offset, max_offset, max_cpi);

    // hexa
    //let (vec, _) = raw_slice_to_hex_vec(data, base_offset, max_offset, max_cpi);

    screen.first_offset = base_offset;
    let mut last_pushed_offset = base_offset;
    let mut prev_cp = ' ';
    let mut column_count = 0;
    for cpi in &vec {
        if prev_cp == '\r' || prev_cp == '\n' {
            column_count = 0;
        }

        let (ok, _) = match (prev_cp, cpi.cp) {
            // TODO: handle \r\n
            (_, '\t') => {
                prev_cp = cpi.cp;
                let mut filtered_cp = *cpi;
                filtered_cp.displayed_cp = ' ';

                let mut last = (false, 0);

                let tab_size = 8;

                let padding = tab_size - (column_count % tab_size);

                for _ in 0..padding {
                    last = screen.push(filtered_cp);
                    column_count += 1;
                }
                last
            }

            _ => {
                prev_cp = cpi.cp;
                column_count += 1;
                screen.push(*cpi)
            }
        };

        if !ok {
            break;
        }

        last_pushed_offset = cpi.offset;
    }

    screen.doc_max_offset = max_offset;
    screen.last_offset = last_pushed_offset;
    last_pushed_offset
}

fn decode_slice_to_vec(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    max_cpi: usize,
) -> (Vec<CodepointInfo>, u64) {
    let mut vec = Vec::with_capacity(max_cpi);

    let mut off: u64 = 0;
    let last_off = data.len() as u64;

    while off != last_off {
        let (cp, _, size) = utf8::get_codepoint(data, off);
        vec.push(filter_codepoint(cp, base_offset + off));
        off += size as u64;
        if vec.len() == max_cpi {
            break;
        }
    }

    // eof handling
    if base_offset + last_off == max_offset {
        vec.push(CodepointInfo {
            cp: ' ',
            displayed_cp: '$',
            offset: base_offset + last_off,
            is_selected: true,
        });
    }

    (vec, base_offset + off)
}

//
fn _raw_slice_to_hex_vec(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    max_cpi: usize,
) -> (Vec<CodepointInfo>, u64) {
    let mut vec = Vec::with_capacity(max_cpi);

    let mut off: u64 = base_offset;
    let last_off = data.len() as u64;

    let hexchars: [char; 16] = [
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
    ];

    while off < last_off {
        let mut width = 0;
        for i in 0..16 {
            if off + i >= last_off {
                break;
            }

            let hi: usize = (data[(off + i) as usize] >> 4) as usize;
            let low: usize = (data[(off + i) as usize] & 0x0f) as usize;

            let cp = hexchars[hi];
            vec.push(filter_codepoint(cp, off + i));
            let cp = hexchars[low];
            vec.push(filter_codepoint(cp, off + i));
            vec.push(filter_codepoint(' ', off + i));

            if vec.len() == max_cpi {
                break;
            }
            width += 1;
        }

        if 0 == 1 {
            vec.push(filter_codepoint('|', off + width));
            vec.push(filter_codepoint(' ', off + width));

            for i in 0..16 {
                if off + i >= last_off {
                    break;
                }

                let c: char = data[(off + i) as usize] as char;
                vec.push(filter_codepoint(c, off + i));
                if vec.len() == max_cpi {
                    break;
                }
            }
        }

        vec.push(filter_codepoint('\n', off));
        off += width;
    }

    // eof handling
    if last_off == max_offset {
        vec.push(CodepointInfo {
            cp: ' ',
            displayed_cp: '$',
            offset: last_off,
            is_selected: true,
        });
    }

    (vec, off)
}

// TODO return array of CodePointInfo  0x7f -> <ESC>
pub fn filter_codepoint(c: char, offset: u64) -> CodepointInfo {
    let displayed_cp: char = match c {
        '\r' | '\n' | '\t' => ' ',

        _ if c < ' ' => '�',

        _ if c == 0x7f as char => '�',

        _ => c,
    };

    CodepointInfo {
        cp: c,
        displayed_cp,
        offset,
        is_selected: false,
    }
}
<commit_msg>build_screen_layout : add TODOs<commit_after>// Copyright (c) Carl-Erwin Griffith
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

use crate::core::codec::text::utf8;
use crate::core::codepointinfo::CodepointInfo;
use crate::core::mark::Mark;
use crate::core::screen::Screen;
use crate::core::view::View;

pub fn get_lines_offsets<'a>(
    view: &View<'a>,
    start_offset: u64,
    end_offset: u64,
    screen_width: usize,
    screen_height: usize,
) -> Vec<(u64, u64)> {
    let mut v = Vec::<(u64, u64)>::new();

    let mut m = Mark::new(start_offset);

    let doc = view.document.as_ref().unwrap().borrow_mut();

    let screen_width = ::std::cmp::max(1, screen_width);
    let screen_height = ::std::cmp::max(4, screen_height);

    // get beginning of the line @offset
    m.move_to_beginning_of_line(&doc.buffer, utf8::get_prev_codepoint);

    // and build tmp screens until end_offset if found
    let mut screen = Screen::new(screen_width, screen_height);

    let max_offset = doc.buffer.size as u64;
    let max_size = (screen_width * screen_height * 4) as usize;

    loop {
        // fill screen
        let mut data = vec![];
        doc.buffer.read(m.offset, max_size, &mut data);

        let _ = build_screen_layout(&data, m.offset, max_offset, &mut screen);

        // push lines offsets
        // FIXME: find a better way to iterate over the used lines
        for i in 0..screen.current_line_index {
            if !v.is_empty() && i == 0 {
                // do not push line range twice
                continue;
            }

            let s = screen.line[i].get_first_cpi().unwrap().offset;
            let e = screen.line[i].get_last_cpi().unwrap().offset;

            v.push((s, e));

            if s >= end_offset || e == max_offset {
                return v;
            }
        }

        // eof reached ?
        // FIXME: the api is not yet READY
        // we must find a way to cover all filled lines
        if screen.current_line_index < screen.height {
            let s = screen.line[screen.current_line_index]
                .get_first_cpi()
                .unwrap()
                .offset;

            let e = screen.line[screen.current_line_index]
                .get_last_cpi()
                .unwrap()
                .offset;
            v.push((s, e));
            return v;
        }

        // TODO: activate only in debug builds
        if 0 == 1 {
            match screen.find_cpi_by_offset(m.offset) {
                (Some(cpi), x, y) => {
                    assert_eq!(x, 0);
                    assert_eq!(y, 0);
                    assert_eq!(cpi.offset, m.offset);
                }
                _ => panic!("implementation error"),
            }
        }

        if let Some(l) = screen.get_last_used_line() {
            if let Some(cpi) = l.get_first_cpi() {
                m.offset = cpi.offset; // update next screen start
            }
        }

        screen.clear(); // prepare next screen
    }
}

//////////////////////////////////
// This function will run the configured filters
// until the screen is full or eof is reached
// the filters will be configured per view to allow multiple interpretation of the same document
// data will be replaced by a "FileMMap"
pub fn build_screen_layout(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    screen: &mut Screen,
) -> u64 {
    let max_cpi = screen.width * screen.height;

    // utf8
    let (vec, _) = decode_slice_to_vec(data, base_offset, max_offset, max_cpi);

    // hexa
    //let (vec, _) = raw_slice_to_hex_vec(data, base_offset, max_offset, max_cpi);

    screen.first_offset = base_offset;
    let mut last_pushed_offset = base_offset;
    let mut prev_cp = ' ';
    let mut column_count = 0;
    for cpi in &vec {
        if prev_cp == '\r' || prev_cp == '\n' {
            column_count = 0;
        }

        let (ok, _) = match (prev_cp, cpi.cp) {
            // TODO: handle \r\n
            (_, '\t') => {
                prev_cp = cpi.cp;
                let mut filtered_cp = *cpi;
                filtered_cp.displayed_cp = ' ';

                let mut last = (false, 0);

                let tab_size = 8;

                let padding = tab_size - (column_count % tab_size);

                for _ in 0..padding {
                    last = screen.push(filtered_cp);
                    // TODO: how to handle errors ?
                    column_count += 1;
                }
                last
            }

            _ => {
                prev_cp = cpi.cp;

                let last = screen.push(*cpi);
                // TODO: how to handle errors ?
                column_count += 1;
                last
            }
        };

        if !ok {
            break;
        }

        last_pushed_offset = cpi.offset;
    }

    screen.doc_max_offset = max_offset;
    screen.last_offset = last_pushed_offset;
    last_pushed_offset
}

fn decode_slice_to_vec(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    max_cpi: usize,
) -> (Vec<CodepointInfo>, u64) {
    let mut vec = Vec::with_capacity(max_cpi);

    let mut off: u64 = 0;
    let last_off = data.len() as u64;

    while off != last_off {
        let (cp, _, size) = utf8::get_codepoint(data, off);
        vec.push(filter_codepoint(cp, base_offset + off));
        off += size as u64;
        if vec.len() == max_cpi {
            break;
        }
    }

    // eof handling
    if base_offset + last_off == max_offset {
        vec.push(CodepointInfo {
            cp: ' ',
            displayed_cp: '$',
            offset: base_offset + last_off,
            is_selected: true,
        });
    }

    (vec, base_offset + off)
}

//
fn _raw_slice_to_hex_vec(
    data: &[u8],
    base_offset: u64,
    max_offset: u64,
    max_cpi: usize,
) -> (Vec<CodepointInfo>, u64) {
    let mut vec = Vec::with_capacity(max_cpi);

    let mut off: u64 = base_offset;
    let last_off = data.len() as u64;

    let hexchars: [char; 16] = [
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
    ];

    while off < last_off {
        let mut width = 0;
        for i in 0..16 {
            if off + i >= last_off {
                break;
            }

            let hi: usize = (data[(off + i) as usize] >> 4) as usize;
            let low: usize = (data[(off + i) as usize] & 0x0f) as usize;

            let cp = hexchars[hi];
            vec.push(filter_codepoint(cp, off + i));
            let cp = hexchars[low];
            vec.push(filter_codepoint(cp, off + i));
            vec.push(filter_codepoint(' ', off + i));

            if vec.len() == max_cpi {
                break;
            }
            width += 1;
        }

        if 0 == 1 {
            vec.push(filter_codepoint('|', off + width));
            vec.push(filter_codepoint(' ', off + width));

            for i in 0..16 {
                if off + i >= last_off {
                    break;
                }

                let c: char = data[(off + i) as usize] as char;
                vec.push(filter_codepoint(c, off + i));
                if vec.len() == max_cpi {
                    break;
                }
            }
        }

        vec.push(filter_codepoint('\n', off));
        off += width;
    }

    // eof handling
    if last_off == max_offset {
        vec.push(CodepointInfo {
            cp: ' ',
            displayed_cp: '$',
            offset: last_off,
            is_selected: true,
        });
    }

    (vec, off)
}

// TODO return array of CodePointInfo  0x7f -> <ESC>
pub fn filter_codepoint(c: char, offset: u64) -> CodepointInfo {
    let displayed_cp: char = match c {
        '\r' | '\n' | '\t' => ' ',

        _ if c < ' ' => '�',

        _ if c == 0x7f as char => '�',

        _ => c,
    };

    CodepointInfo {
        cp: c,
        displayed_cp,
        offset,
        is_selected: false,
    }
}
<|endoftext|>


<commit_before>pub type clock_t = c_long;
pub type time_t = c_long;
pub type suseconds_t = c_long;
pub type ino_t = u64;
pub type off_t = i64;
pub type blkcnt_t = i64;

pub type blksize_t = c_long;
pub type fsblkcnt_t = ::c_ulonglong;
pub type fsfilcnt_t = ::c_ulonglong;
pub type rlim_t = ::c_ulonglong;

s! {
    pub struct sigaction {
        pub sa_sigaction: ::sighandler_t,
        pub sa_mask: ::sigset_t,
        pub sa_flags: ::c_int,
        _restorer: *mut ::c_void,
    }

    pub struct ipc_perm {
        pub __ipc_perm_key: ::key_t,
        pub uid: ::uid_t,
        pub gid: ::gid_t,
        pub cuid: ::uid_t,
        pub cgid: ::gid_t,
        pub mode: ::mode_t,
        pub __seq: ::c_int,
        __unused1: ::c_long,
        __unused2: ::c_long
    }

    pub struct termios {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; ::NCCS],
        pub __c_ispeed: ::speed_t,
        pub __c_ospeed: ::speed_t,
    }

    pub struct flock {
        pub l_type: ::c_short,
        pub l_whence: ::c_short,
        pub l_start: ::off_t,
        pub l_len: ::off_t,
        pub l_pid: ::pid_t,
    }

    pub struct sysinfo {
        pub uptime: ::c_ulong,
        pub loads: [::c_ulong; 3],
        pub totalram: ::c_ulong,
        pub freeram: ::c_ulong,
        pub sharedram: ::c_ulong,
        pub bufferram: ::c_ulong,
        pub totalswap: ::c_ulong,
        pub freeswap: ::c_ulong,
        pub procs: ::c_ushort,
        pub pad: ::c_ushort,
        pub totalhigh: ::c_ulong,
        pub freehigh: ::c_ulong,
        pub mem_unit: ::c_uint,
        pub __reserved: [::c_char; 256],
    }
}

pub const BUFSIZ: ::c_uint = 1024;
pub const TMP_MAX: ::c_uint = 10000;
pub const FOPEN_MAX: ::c_uint = 1000;
pub const O_ACCMODE: ::c_int = 0o10000003;
pub const O_NDELAY: ::c_int = O_NONBLOCK;
pub const NI_MAXHOST: ::socklen_t = 255;
pub const PTHREAD_STACK_MIN: ::size_t = 2048;
pub const POSIX_FADV_DONTNEED: ::c_int = 4;
pub const POSIX_FADV_NOREUSE: ::c_int = 5;

pub const POSIX_MADV_DONTNEED: ::c_int = 4;

pub const RLIM_INFINITY: ::rlim_t = !0;
pub const RLIMIT_RTTIME: ::c_int = 15;
pub const RLIMIT_NLIMITS: ::c_int = 16;

pub const MAP_ANONYMOUS: ::c_int = MAP_ANON;

pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15;
pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16;
pub const TCP_THIN_DUPACK: ::c_int = 17;
pub const TCP_USER_TIMEOUT: ::c_int = 18;
pub const TCP_REPAIR: ::c_int = 19;
pub const TCP_REPAIR_QUEUE: ::c_int = 20;
pub const TCP_QUEUE_SEQ: ::c_int = 21;
pub const TCP_REPAIR_OPTIONS: ::c_int = 22;
pub const TCP_FASTOPEN: ::c_int = 23;
pub const TCP_TIMESTAMP: ::c_int = 24;

pub const SIGUNUSED: ::c_int = ::SIGSYS;

pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01;
pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02;

pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;

pub const CPU_SETSIZE: ::c_int = 128;

pub const QFMT_VFS_V1: ::c_int = 4;

pub const PTRACE_TRACEME: ::c_int = 0;
pub const PTRACE_PEEKTEXT: ::c_int = 1;
pub const PTRACE_PEEKDATA: ::c_int = 2;
pub const PTRACE_PEEKUSER: ::c_int = 3;
pub const PTRACE_POKETEXT: ::c_int = 4;
pub const PTRACE_POKEDATA: ::c_int = 5;
pub const PTRACE_POKEUSER: ::c_int = 6;
pub const PTRACE_CONT: ::c_int = 7;
pub const PTRACE_KILL: ::c_int = 8;
pub const PTRACE_SINGLESTEP: ::c_int = 9;
pub const PTRACE_ATTACH: ::c_int = 16;
pub const PTRACE_DETACH: ::c_int = 17;
pub const PTRACE_SYSCALL: ::c_int = 24;
pub const PTRACE_SETOPTIONS: ::c_int = 0x4200;
pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201;
pub const PTRACE_GETSIGINFO: ::c_int = 0x4202;
pub const PTRACE_SETSIGINFO: ::c_int = 0x4203;
pub const PTRACE_GETREGSET: ::c_int = 0x4204;
pub const PTRACE_SETREGSET: ::c_int = 0x4205;
pub const PTRACE_SEIZE: ::c_int = 0x4206;
pub const PTRACE_INTERRUPT: ::c_int = 0x4207;
pub const PTRACE_LISTEN: ::c_int = 0x4208;
pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209;

pub const PTRACE_O_EXITKILL: ::c_int = 1048576;
pub const PTRACE_O_TRACECLONE: ::c_int = 8;
pub const PTRACE_O_TRACEEXEC: ::c_int = 16;
pub const PTRACE_O_TRACEEXIT: ::c_int = 64;
pub const PTRACE_O_TRACEFORK: ::c_int = 2;
pub const PTRACE_O_TRACESYSGOOD: ::c_int = 1;
pub const PTRACE_O_TRACEVFORK: ::c_int = 4;
pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 32;
pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 2097152;

pub const MADV_DODUMP: ::c_int = 17;
pub const MADV_DONTDUMP: ::c_int = 16;

pub const EPOLLWAKEUP: ::c_int = 0x20000000;

pub const POLLRDNORM: ::c_short = 0x040;
pub const POLLRDBAND: ::c_short = 0x080;

pub const MADV_HUGEPAGE: ::c_int = 14;
pub const MADV_NOHUGEPAGE: ::c_int = 15;

pub const PTRACE_GETFPREGS: ::c_uint = 14;
pub const PTRACE_SETFPREGS: ::c_uint = 15;
pub const PTRACE_GETFPXREGS: ::c_uint = 18;
pub const PTRACE_SETFPXREGS: ::c_uint = 19;
pub const PTRACE_GETREGS: ::c_uint = 12;
pub const PTRACE_SETREGS: ::c_uint = 13;

pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK;

pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK;

pub const TCSANOW: ::c_int = 0;
pub const TCSADRAIN: ::c_int = 1;
pub const TCSAFLUSH: ::c_int = 2;

pub const TIOCINQ: ::c_int = ::FIONREAD;

pub const RTLD_GLOBAL: ::c_int = 0x100;
pub const RTLD_NOLOAD: ::c_int = 0x4;

// TODO(#247) Temporarily musl-specific (available since musl 0.9.12 / Linux
// kernel 3.10).  See also notbsd/mod.rs
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;
pub const CLOCK_TAI: ::clockid_t = 11;

pub const MCL_CURRENT: ::c_int = 0x0001;
pub const MCL_FUTURE: ::c_int = 0x0002;

pub const SIGSTKSZ: ::size_t = 8192;
pub const CBAUD: ::tcflag_t = 0o0010017;
pub const TAB1: ::c_int = 0x00000800;
pub const TAB2: ::c_int = 0x00001000;
pub const TAB3: ::c_int = 0x00001800;
pub const CR1: ::c_int  = 0x00000200;
pub const CR2: ::c_int  = 0x00000400;
pub const CR3: ::c_int  = 0x00000600;
pub const FF1: ::c_int  = 0x00008000;
pub const BS1: ::c_int  = 0x00002000;
pub const VT1: ::c_int  = 0x00004000;
pub const VWERASE: usize = 14;
pub const VREPRINT: usize = 12;
pub const VSUSP: usize = 10;
pub const VSTART: usize = 8;
pub const VSTOP: usize = 9;
pub const VDISCARD: usize = 13;
pub const VTIME: usize = 5;
pub const IXON: ::tcflag_t = 0x00000400;
pub const IXOFF: ::tcflag_t = 0x00001000;
pub const ONLCR: ::tcflag_t = 0x4;
pub const CSIZE: ::tcflag_t = 0x00000030;
pub const CS6: ::tcflag_t = 0x00000010;
pub const CS7: ::tcflag_t = 0x00000020;
pub const CS8: ::tcflag_t = 0x00000030;
pub const CSTOPB: ::tcflag_t = 0x00000040;
pub const CREAD: ::tcflag_t = 0x00000080;
pub const PARENB: ::tcflag_t = 0x00000100;
pub const PARODD: ::tcflag_t = 0x00000200;
pub const HUPCL: ::tcflag_t = 0x00000400;
pub const CLOCAL: ::tcflag_t = 0x00000800;
pub const ECHOKE: ::tcflag_t = 0x00000800;
pub const ECHOE: ::tcflag_t = 0x00000010;
pub const ECHOK: ::tcflag_t = 0x00000020;
pub const ECHONL: ::tcflag_t = 0x00000040;
pub const ECHOPRT: ::tcflag_t = 0x00000400;
pub const ECHOCTL: ::tcflag_t = 0x00000200;
pub const ISIG: ::tcflag_t = 0x00000001;
pub const ICANON: ::tcflag_t = 0x00000002;
pub const PENDIN: ::tcflag_t = 0x00004000;
pub const NOFLSH: ::tcflag_t = 0x00000080;

extern {
    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
    pub fn ptrace(request: ::c_int, ...) -> ::c_long;
    pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
    pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
}

cfg_if! {
    if #[cfg(any(target_arch = "x86_64"))] {
        mod b64;
        pub use self::b64::*;
    } else if #[cfg(any(target_arch = "x86",
                        target_arch = "mips",
                        target_arch = "arm",
                        target_arch = "asmjs",
                        target_arch = "wasm32"))] {
        mod b32;
        pub use self::b32::*;
    } else { }
}
<commit_msg>Enable musl with aarch64<commit_after>pub type clock_t = c_long;
pub type time_t = c_long;
pub type suseconds_t = c_long;
pub type ino_t = u64;
pub type off_t = i64;
pub type blkcnt_t = i64;

pub type blksize_t = c_long;
pub type fsblkcnt_t = ::c_ulonglong;
pub type fsfilcnt_t = ::c_ulonglong;
pub type rlim_t = ::c_ulonglong;

s! {
    pub struct sigaction {
        pub sa_sigaction: ::sighandler_t,
        pub sa_mask: ::sigset_t,
        pub sa_flags: ::c_int,
        _restorer: *mut ::c_void,
    }

    pub struct ipc_perm {
        pub __ipc_perm_key: ::key_t,
        pub uid: ::uid_t,
        pub gid: ::gid_t,
        pub cuid: ::uid_t,
        pub cgid: ::gid_t,
        pub mode: ::mode_t,
        pub __seq: ::c_int,
        __unused1: ::c_long,
        __unused2: ::c_long
    }

    pub struct termios {
        pub c_iflag: ::tcflag_t,
        pub c_oflag: ::tcflag_t,
        pub c_cflag: ::tcflag_t,
        pub c_lflag: ::tcflag_t,
        pub c_line: ::cc_t,
        pub c_cc: [::cc_t; ::NCCS],
        pub __c_ispeed: ::speed_t,
        pub __c_ospeed: ::speed_t,
    }

    pub struct flock {
        pub l_type: ::c_short,
        pub l_whence: ::c_short,
        pub l_start: ::off_t,
        pub l_len: ::off_t,
        pub l_pid: ::pid_t,
    }

    pub struct sysinfo {
        pub uptime: ::c_ulong,
        pub loads: [::c_ulong; 3],
        pub totalram: ::c_ulong,
        pub freeram: ::c_ulong,
        pub sharedram: ::c_ulong,
        pub bufferram: ::c_ulong,
        pub totalswap: ::c_ulong,
        pub freeswap: ::c_ulong,
        pub procs: ::c_ushort,
        pub pad: ::c_ushort,
        pub totalhigh: ::c_ulong,
        pub freehigh: ::c_ulong,
        pub mem_unit: ::c_uint,
        pub __reserved: [::c_char; 256],
    }
}

pub const BUFSIZ: ::c_uint = 1024;
pub const TMP_MAX: ::c_uint = 10000;
pub const FOPEN_MAX: ::c_uint = 1000;
pub const O_ACCMODE: ::c_int = 0o10000003;
pub const O_NDELAY: ::c_int = O_NONBLOCK;
pub const NI_MAXHOST: ::socklen_t = 255;
pub const PTHREAD_STACK_MIN: ::size_t = 2048;
pub const POSIX_FADV_DONTNEED: ::c_int = 4;
pub const POSIX_FADV_NOREUSE: ::c_int = 5;

pub const POSIX_MADV_DONTNEED: ::c_int = 4;

pub const RLIM_INFINITY: ::rlim_t = !0;
pub const RLIMIT_RTTIME: ::c_int = 15;
pub const RLIMIT_NLIMITS: ::c_int = 16;

pub const MAP_ANONYMOUS: ::c_int = MAP_ANON;

pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15;
pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16;
pub const TCP_THIN_DUPACK: ::c_int = 17;
pub const TCP_USER_TIMEOUT: ::c_int = 18;
pub const TCP_REPAIR: ::c_int = 19;
pub const TCP_REPAIR_QUEUE: ::c_int = 20;
pub const TCP_QUEUE_SEQ: ::c_int = 21;
pub const TCP_REPAIR_OPTIONS: ::c_int = 22;
pub const TCP_FASTOPEN: ::c_int = 23;
pub const TCP_TIMESTAMP: ::c_int = 24;

pub const SIGUNUSED: ::c_int = ::SIGSYS;

pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01;
pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02;

pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;

pub const CPU_SETSIZE: ::c_int = 128;

pub const QFMT_VFS_V1: ::c_int = 4;

pub const PTRACE_TRACEME: ::c_int = 0;
pub const PTRACE_PEEKTEXT: ::c_int = 1;
pub const PTRACE_PEEKDATA: ::c_int = 2;
pub const PTRACE_PEEKUSER: ::c_int = 3;
pub const PTRACE_POKETEXT: ::c_int = 4;
pub const PTRACE_POKEDATA: ::c_int = 5;
pub const PTRACE_POKEUSER: ::c_int = 6;
pub const PTRACE_CONT: ::c_int = 7;
pub const PTRACE_KILL: ::c_int = 8;
pub const PTRACE_SINGLESTEP: ::c_int = 9;
pub const PTRACE_ATTACH: ::c_int = 16;
pub const PTRACE_DETACH: ::c_int = 17;
pub const PTRACE_SYSCALL: ::c_int = 24;
pub const PTRACE_SETOPTIONS: ::c_int = 0x4200;
pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201;
pub const PTRACE_GETSIGINFO: ::c_int = 0x4202;
pub const PTRACE_SETSIGINFO: ::c_int = 0x4203;
pub const PTRACE_GETREGSET: ::c_int = 0x4204;
pub const PTRACE_SETREGSET: ::c_int = 0x4205;
pub const PTRACE_SEIZE: ::c_int = 0x4206;
pub const PTRACE_INTERRUPT: ::c_int = 0x4207;
pub const PTRACE_LISTEN: ::c_int = 0x4208;
pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209;

pub const PTRACE_O_EXITKILL: ::c_int = 1048576;
pub const PTRACE_O_TRACECLONE: ::c_int = 8;
pub const PTRACE_O_TRACEEXEC: ::c_int = 16;
pub const PTRACE_O_TRACEEXIT: ::c_int = 64;
pub const PTRACE_O_TRACEFORK: ::c_int = 2;
pub const PTRACE_O_TRACESYSGOOD: ::c_int = 1;
pub const PTRACE_O_TRACEVFORK: ::c_int = 4;
pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 32;
pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 2097152;

pub const MADV_DODUMP: ::c_int = 17;
pub const MADV_DONTDUMP: ::c_int = 16;

pub const EPOLLWAKEUP: ::c_int = 0x20000000;

pub const POLLRDNORM: ::c_short = 0x040;
pub const POLLRDBAND: ::c_short = 0x080;

pub const MADV_HUGEPAGE: ::c_int = 14;
pub const MADV_NOHUGEPAGE: ::c_int = 15;

pub const PTRACE_GETFPREGS: ::c_uint = 14;
pub const PTRACE_SETFPREGS: ::c_uint = 15;
pub const PTRACE_GETFPXREGS: ::c_uint = 18;
pub const PTRACE_SETFPXREGS: ::c_uint = 19;
pub const PTRACE_GETREGS: ::c_uint = 12;
pub const PTRACE_SETREGS: ::c_uint = 13;

pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK;

pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK;

pub const TCSANOW: ::c_int = 0;
pub const TCSADRAIN: ::c_int = 1;
pub const TCSAFLUSH: ::c_int = 2;

pub const TIOCINQ: ::c_int = ::FIONREAD;

pub const RTLD_GLOBAL: ::c_int = 0x100;
pub const RTLD_NOLOAD: ::c_int = 0x4;

// TODO(#247) Temporarily musl-specific (available since musl 0.9.12 / Linux
// kernel 3.10).  See also notbsd/mod.rs
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;
pub const CLOCK_TAI: ::clockid_t = 11;

pub const MCL_CURRENT: ::c_int = 0x0001;
pub const MCL_FUTURE: ::c_int = 0x0002;

pub const SIGSTKSZ: ::size_t = 8192;
pub const CBAUD: ::tcflag_t = 0o0010017;
pub const TAB1: ::c_int = 0x00000800;
pub const TAB2: ::c_int = 0x00001000;
pub const TAB3: ::c_int = 0x00001800;
pub const CR1: ::c_int  = 0x00000200;
pub const CR2: ::c_int  = 0x00000400;
pub const CR3: ::c_int  = 0x00000600;
pub const FF1: ::c_int  = 0x00008000;
pub const BS1: ::c_int  = 0x00002000;
pub const VT1: ::c_int  = 0x00004000;
pub const VWERASE: usize = 14;
pub const VREPRINT: usize = 12;
pub const VSUSP: usize = 10;
pub const VSTART: usize = 8;
pub const VSTOP: usize = 9;
pub const VDISCARD: usize = 13;
pub const VTIME: usize = 5;
pub const IXON: ::tcflag_t = 0x00000400;
pub const IXOFF: ::tcflag_t = 0x00001000;
pub const ONLCR: ::tcflag_t = 0x4;
pub const CSIZE: ::tcflag_t = 0x00000030;
pub const CS6: ::tcflag_t = 0x00000010;
pub const CS7: ::tcflag_t = 0x00000020;
pub const CS8: ::tcflag_t = 0x00000030;
pub const CSTOPB: ::tcflag_t = 0x00000040;
pub const CREAD: ::tcflag_t = 0x00000080;
pub const PARENB: ::tcflag_t = 0x00000100;
pub const PARODD: ::tcflag_t = 0x00000200;
pub const HUPCL: ::tcflag_t = 0x00000400;
pub const CLOCAL: ::tcflag_t = 0x00000800;
pub const ECHOKE: ::tcflag_t = 0x00000800;
pub const ECHOE: ::tcflag_t = 0x00000010;
pub const ECHOK: ::tcflag_t = 0x00000020;
pub const ECHONL: ::tcflag_t = 0x00000040;
pub const ECHOPRT: ::tcflag_t = 0x00000400;
pub const ECHOCTL: ::tcflag_t = 0x00000200;
pub const ISIG: ::tcflag_t = 0x00000001;
pub const ICANON: ::tcflag_t = 0x00000002;
pub const PENDIN: ::tcflag_t = 0x00004000;
pub const NOFLSH: ::tcflag_t = 0x00000080;

extern {
    pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
    pub fn ptrace(request: ::c_int, ...) -> ::c_long;
    pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
    pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
}

cfg_if! {
    if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] {
        mod b64;
        pub use self::b64::*;
    } else if #[cfg(any(target_arch = "x86",
                        target_arch = "mips",
                        target_arch = "arm",
                        target_arch = "asmjs",
                        target_arch = "wasm32"))] {
        mod b32;
        pub use self::b32::*;
    } else { }
}
<|endoftext|>


<commit_before>use libc::{c_int, c_char, c_long};

#[derive(Debug)]
#[repr(C)]
pub struct JTM {
  pub tm_sec: c_int,       /* Seconds. (0-59) */
  pub tm_min: c_int,       /* Minutes. (0-59) */
  pub tm_hour: c_int,      /* Hours. (0-59) */
  pub tm_mday: c_int,      /* Day of the month. (1-31) */
  pub tm_mon: c_int,       /* Month. (0-11) */
  pub tm_year: c_int,      /* Year. */
  pub tm_wday: c_int,      /* Day of the week. (0-6) */
  pub tm_yday: c_int,      /* Day in the year. (0-365) */
  pub tm_isdst: c_int,     /* Daylight saving time is in effect. */
  pub tm_gmtoff: c_long,   /* Seconds east of UTC. */
  pub tm_zone: *const c_char,  /* Timezone abbreviation.  */
}

#[derive(Debug)]
#[repr(C)]
pub struct AB_JTM {
  pub ab_sec: c_int,
  pub ab_min: c_int,
  pub ab_hour: c_int,
  pub ab_days: c_int,
}

#[derive(Debug)]
#[repr(C)]
pub struct JYInfo {
  pub lf: c_int,          /* leap indicator flag */
  pub y: c_int,           /* year */
  pub r: c_int,           /* reamining years in grand cycle */
  pub p: c_int,           /* passed years from grand cycle*/
  pub rl: c_int,          /* remaining leap years in grand cycle */
  pub pl: c_int,          /* passed leap years in grand cycle */
  pub apl: c_int,         /* absolute passed leaps */
}
<commit_msg>write documentations for data_structs module<commit_after>//! This module holds definitions of data structures used in this library.

use libc::{c_int, c_char, c_long};

/// Broken-down jalali time
///
#[derive(Debug)]
#[repr(C)]
pub struct JTM {
  /// Seconds. (0-59)
  pub tm_sec: c_int,
  /// Minutes. (0-59)
  pub tm_min: c_int,
  /// Hours. (0-59)
  pub tm_hour: c_int,
  /// Day of the month. (1-31)
  pub tm_mday: c_int,
  /// Month. (0-11)
  pub tm_mon: c_int,
  /// Year.
  pub tm_year: c_int,
  /// Day of the week. (0-6)
  pub tm_wday: c_int,
  /// Day in the year. (0-365)
  pub tm_yday: c_int,
  /// Daylight saving time is in effect.
  pub tm_isdst: c_int,
  /// Seconds east of UTC.
  pub tm_gmtoff: c_long,
  /// Timezone abbreviation.
  pub tm_zone: *const c_char,
}

/// Information about passed days since Epoch
#[derive(Debug)]
#[repr(C)]
pub struct AB_JTM {
  pub ab_sec: c_int,
  pub ab_min: c_int,
  pub ab_hour: c_int,
  pub ab_days: c_int,
}

/// Information about a certain year in jalali system
///
#[derive(Debug)]
#[repr(C)]
pub struct JYInfo {
  /// leap indicator flag
  pub lf: c_int,
  /// year
  pub y: c_int,
  /// reamining years in grand cycle
  pub r: c_int,
  /// passed years from grand cycle
  pub p: c_int,
  /// remaining leap years in grand cycle
  pub rl: c_int,
  /// passed leap years in grand cycle
  pub pl: c_int,
  /// absolute passed leaps
  pub apl: c_int,
}
<|endoftext|>