<commit_before>#![allow(unsafe_code)]
/// We use this because we never use the weak count on the std
/// `Arc`, but we use a LOT of `Arc`'s, so the extra 8 bytes
/// turn into a huge overhead.
use std::{
    alloc::{alloc, dealloc, Layout},
    convert::TryFrom,
    fmt::{self, Debug},
    mem,
    ops::Deref,
    ptr,
    sync::atomic::{AtomicUsize, Ordering},
};

// we make this repr(C) because we do a raw
// write to the beginning where we expect
// the rc to be.
#[repr(C)]
struct ArcInner<T: ?Sized> {
    rc: AtomicUsize,
    inner: T,
}

pub struct Arc<T: ?Sized> {
    ptr: *mut ArcInner<T>,
}

unsafe impl<T: Send + Sync + ?Sized> Send for Arc<T> {}
unsafe impl<T: Send + Sync + ?Sized> Sync for Arc<T> {}

impl<T: Debug> Debug for Arc<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        f.debug_map().entry(&"inner", unsafe { &(*self.ptr).inner }).finish()
    }
}

impl<T> Arc<T> {
    pub fn new(inner: T) -> Arc<T> {
        let bx = Box::new(ArcInner { inner, rc: AtomicUsize::new(1) });
        let ptr = Box::into_raw(bx);
        Arc { ptr }
    }

    // See std::sync::arc::Arc::copy_from_slice,
    // "Unsafe because the caller must either take ownership or bind `T: Copy`"
    unsafe fn copy_from_slice(s: &[T]) -> Arc<[T]> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());
        let data_width = mem::size_of::<T>().checked_mul(s.len()).unwrap();

        let size = rc_width.checked_add(data_width).unwrap();

        let layout = Layout::from_size_align(size, align).unwrap();
        let layout = layout.pad_to_align();

        let ptr = alloc(layout);

        assert!(!ptr.is_null(), "failed to allocate Arc");
        #[allow(clippy::cast_ptr_alignment)]
        ptr::write(ptr as _, AtomicUsize::new(1));

        let data_ptr = ptr.add(rc_width);
        ptr::copy_nonoverlapping(s.as_ptr(), data_ptr as _, s.len());

        let fat_ptr: *const ArcInner<[T]> = Arc::fatten(ptr, s.len());

        Arc { ptr: fat_ptr as *mut _ }
    }

    /// <https://users.rust-lang.org/t/construct-fat-pointer-to-struct/29198/9>
    #[allow(trivial_casts)]
    fn fatten(data: *const u8, len: usize) -> *const ArcInner<[T]> {
        // Requirements of slice::from_raw_parts.
        assert!(!data.is_null());
        assert!(isize::try_from(len).is_ok());

        let slice =
            unsafe { core::slice::from_raw_parts(data as *const (), len) };
        slice as *const [()] as *const _
    }

    pub fn into_raw(arc: Arc<T>) -> *const T {
        let ptr = unsafe { &(*arc.ptr).inner };
        #[allow(clippy::mem_forget)]
        mem::forget(arc);
        ptr
    }

    pub unsafe fn from_raw(ptr: *const T) -> Arc<T> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());

        let sub_ptr = (ptr as *const u8).sub(rc_width) as *mut ArcInner<T>;

        Arc { ptr: sub_ptr }
    }
}

impl<T: ?Sized> Arc<T> {
    pub fn strong_count(arc: &Arc<T>) -> usize {
        unsafe { (*arc.ptr).rc.load(Ordering::Acquire) }
    }

    pub fn get_mut(arc: &mut Arc<T>) -> Option<&mut T> {
        if Arc::strong_count(arc) == 1 {
            Some(unsafe { &mut arc.ptr.as_mut().unwrap().inner })
        } else {
            None
        }
    }
}

impl<T: ?Sized + Clone> Arc<T> {
    pub fn make_mut(arc: &mut Arc<T>) -> &mut T {
        if Arc::strong_count(arc) != 1 {
            *arc = Arc::new((**arc).clone());
            assert_eq!(Arc::strong_count(arc), 1);
        }
        Arc::get_mut(arc).unwrap()
    }
}

impl<T: Default> Default for Arc<T> {
    fn default() -> Arc<T> {
        Arc::new(T::default())
    }
}

impl<T: ?Sized> Clone for Arc<T> {
    fn clone(&self) -> Arc<T> {
        // safe to use Relaxed ordering below because
        // of the required synchronization for passing
        // any objects to another thread.
        let last_count =
            unsafe { (*self.ptr).rc.fetch_add(1, Ordering::Relaxed) };

        if last_count == usize::max_value() {
            #[cold]
            std::process::abort();
        }

        Arc { ptr: self.ptr }
    }
}

impl<T: ?Sized> Drop for Arc<T> {
    fn drop(&mut self) {
        unsafe {
            let rc = (*self.ptr).rc.fetch_sub(1, Ordering::Release) - 1;
            if rc == 0 {
                std::sync::atomic::fence(Ordering::Acquire);
                Box::from_raw(self.ptr);
            }
        }
    }
}

impl<T: Copy> From<&[T]> for Arc<[T]> {
    #[inline]
    fn from(s: &[T]) -> Arc<[T]> {
        unsafe { Arc::copy_from_slice(s) }
    }
}

#[allow(clippy::fallible_impl_from)]
impl<T> From<Box<T>> for Arc<T> {
    #[inline]
    fn from(b: Box<T>) -> Arc<T> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());

        unsafe {
            let dst_layout = Layout::new::<ArcInner<T>>();
            let dst = alloc(dst_layout);
            assert!(!dst.is_null(), "failed to allocate Arc");

            let data_ptr = dst.add(rc_width);
            #[allow(clippy::cast_ptr_alignment)]
            ptr::write(dst as _, AtomicUsize::new(1));
            let src = Box::into_raw(b);
            ptr::copy(src, data_ptr as *mut T, 1);

            // free the old box memory without running Drop
            let src_layout = Layout::new::<T>();
            dealloc(src as *mut u8, src_layout);

            Arc { ptr: dst as *mut _ }
        }
    }
}

impl<T> From<Vec<T>> for Arc<[T]> {
    #[inline]
    fn from(mut v: Vec<T>) -> Arc<[T]> {
        unsafe {
            let arc = Arc::copy_from_slice(&v);

            // Allow the Vec to free its memory, but not destroy its contents
            v.set_len(0);

            arc
        }
    }
}

impl<T: ?Sized> Deref for Arc<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &(*self.ptr).inner }
    }
}

impl<T: ?Sized> std::borrow::Borrow<T> for Arc<T> {
    fn borrow(&self) -> &T {
        &**self
    }
}

impl<T: ?Sized> AsRef<T> for Arc<T> {
    fn as_ref(&self) -> &T {
        &**self
    }
}
<commit_msg>MSRV fix<commit_after>#![allow(unsafe_code)]
/// We use this because we never use the weak count on the std
/// `Arc`, but we use a LOT of `Arc`'s, so the extra 8 bytes
/// turn into a huge overhead.
use std::{
    alloc::{alloc, dealloc, Layout},
    convert::TryFrom,
    fmt::{self, Debug},
    mem,
    ops::Deref,
    ptr,
    sync::atomic::{AtomicUsize, Ordering},
};

// we make this repr(C) because we do a raw
// write to the beginning where we expect
// the rc to be.
#[repr(C)]
struct ArcInner<T: ?Sized> {
    rc: AtomicUsize,
    inner: T,
}

pub struct Arc<T: ?Sized> {
    ptr: *mut ArcInner<T>,
}

unsafe impl<T: Send + Sync + ?Sized> Send for Arc<T> {}
unsafe impl<T: Send + Sync + ?Sized> Sync for Arc<T> {}

impl<T: Debug> Debug for Arc<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        f.debug_map().entry(&"inner", unsafe { &(*self.ptr).inner }).finish()
    }
}

impl<T> Arc<T> {
    pub fn new(inner: T) -> Arc<T> {
        let bx = Box::new(ArcInner { inner, rc: AtomicUsize::new(1) });
        let ptr = Box::into_raw(bx);
        Arc { ptr }
    }

    // See std::sync::arc::Arc::copy_from_slice,
    // "Unsafe because the caller must either take ownership or bind `T: Copy`"
    unsafe fn copy_from_slice(s: &[T]) -> Arc<[T]> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());
        let data_width = mem::size_of::<T>().checked_mul(s.len()).unwrap();

        let size = rc_width.checked_add(data_width).unwrap();
        // Pad size out to alignment
        let size = (size + align - 1) & !(align - 1);

        let layout = Layout::from_size_align(size, align).unwrap();

        let ptr = alloc(layout);

        assert!(!ptr.is_null(), "failed to allocate Arc");
        #[allow(clippy::cast_ptr_alignment)]
        ptr::write(ptr as _, AtomicUsize::new(1));

        let data_ptr = ptr.add(rc_width);
        ptr::copy_nonoverlapping(s.as_ptr(), data_ptr as _, s.len());

        let fat_ptr: *const ArcInner<[T]> = Arc::fatten(ptr, s.len());

        Arc { ptr: fat_ptr as *mut _ }
    }

    /// <https://users.rust-lang.org/t/construct-fat-pointer-to-struct/29198/9>
    #[allow(trivial_casts)]
    fn fatten(data: *const u8, len: usize) -> *const ArcInner<[T]> {
        // Requirements of slice::from_raw_parts.
        assert!(!data.is_null());
        assert!(isize::try_from(len).is_ok());

        let slice =
            unsafe { core::slice::from_raw_parts(data as *const (), len) };
        slice as *const [()] as *const _
    }

    pub fn into_raw(arc: Arc<T>) -> *const T {
        let ptr = unsafe { &(*arc.ptr).inner };
        #[allow(clippy::mem_forget)]
        mem::forget(arc);
        ptr
    }

    pub unsafe fn from_raw(ptr: *const T) -> Arc<T> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());

        let sub_ptr = (ptr as *const u8).sub(rc_width) as *mut ArcInner<T>;

        Arc { ptr: sub_ptr }
    }
}

impl<T: ?Sized> Arc<T> {
    pub fn strong_count(arc: &Arc<T>) -> usize {
        unsafe { (*arc.ptr).rc.load(Ordering::Acquire) }
    }

    pub fn get_mut(arc: &mut Arc<T>) -> Option<&mut T> {
        if Arc::strong_count(arc) == 1 {
            Some(unsafe { &mut arc.ptr.as_mut().unwrap().inner })
        } else {
            None
        }
    }
}

impl<T: ?Sized + Clone> Arc<T> {
    pub fn make_mut(arc: &mut Arc<T>) -> &mut T {
        if Arc::strong_count(arc) != 1 {
            *arc = Arc::new((**arc).clone());
            assert_eq!(Arc::strong_count(arc), 1);
        }
        Arc::get_mut(arc).unwrap()
    }
}

impl<T: Default> Default for Arc<T> {
    fn default() -> Arc<T> {
        Arc::new(T::default())
    }
}

impl<T: ?Sized> Clone for Arc<T> {
    fn clone(&self) -> Arc<T> {
        // safe to use Relaxed ordering below because
        // of the required synchronization for passing
        // any objects to another thread.
        let last_count =
            unsafe { (*self.ptr).rc.fetch_add(1, Ordering::Relaxed) };

        if last_count == usize::max_value() {
            #[cold]
            std::process::abort();
        }

        Arc { ptr: self.ptr }
    }
}

impl<T: ?Sized> Drop for Arc<T> {
    fn drop(&mut self) {
        unsafe {
            let rc = (*self.ptr).rc.fetch_sub(1, Ordering::Release) - 1;
            if rc == 0 {
                std::sync::atomic::fence(Ordering::Acquire);
                Box::from_raw(self.ptr);
            }
        }
    }
}

impl<T: Copy> From<&[T]> for Arc<[T]> {
    #[inline]
    fn from(s: &[T]) -> Arc<[T]> {
        unsafe { Arc::copy_from_slice(s) }
    }
}

#[allow(clippy::fallible_impl_from)]
impl<T> From<Box<T>> for Arc<T> {
    #[inline]
    fn from(b: Box<T>) -> Arc<T> {
        let align =
            std::cmp::max(mem::align_of::<T>(), mem::align_of::<AtomicUsize>());

        let rc_width = std::cmp::max(align, mem::size_of::<AtomicUsize>());

        unsafe {
            let dst_layout = Layout::new::<ArcInner<T>>();
            let dst = alloc(dst_layout);
            assert!(!dst.is_null(), "failed to allocate Arc");

            let data_ptr = dst.add(rc_width);
            #[allow(clippy::cast_ptr_alignment)]
            ptr::write(dst as _, AtomicUsize::new(1));
            let src = Box::into_raw(b);
            ptr::copy(src, data_ptr as *mut T, 1);

            // free the old box memory without running Drop
            let src_layout = Layout::new::<T>();
            dealloc(src as *mut u8, src_layout);

            Arc { ptr: dst as *mut _ }
        }
    }
}

impl<T> From<Vec<T>> for Arc<[T]> {
    #[inline]
    fn from(mut v: Vec<T>) -> Arc<[T]> {
        unsafe {
            let arc = Arc::copy_from_slice(&v);

            // Allow the Vec to free its memory, but not destroy its contents
            v.set_len(0);

            arc
        }
    }
}

impl<T: ?Sized> Deref for Arc<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &(*self.ptr).inner }
    }
}

impl<T: ?Sized> std::borrow::Borrow<T> for Arc<T> {
    fn borrow(&self) -> &T {
        &**self
    }
}

impl<T: ?Sized> AsRef<T> for Arc<T> {
    fn as_ref(&self) -> &T {
        &**self
    }
}
<|endoftext|>


<commit_before>use std::path::MAIN_SEPARATOR;
use std::process::Command;

use clap::{App, Arg, Error};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub signal: Option<String>,
    pub restart: bool,
    pub debug: bool,
    pub run_initially: bool,
    pub no_shell: bool,
    pub no_vcs_ignore: bool,
    pub once: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("clear").status();
}

#[allow(unknown_lints)]
#[allow(or_fun_call)]
pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debug")
                 .help("Print debugging messages to stderr")
                 .short("d")
                 .long("debug"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Forces polling mode")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String)
        .unwrap()
        .join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                               .filter(|ext| !ext.is_empty())
                               .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![format!("*{}.DS_Store", MAIN_SEPARATOR),
                               String::from("*.pyc"),
                               String::from("*.swp")];

    ignores.extend(default_ignores);
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        signal: signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debug: args.is_present("debug"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<commit_msg>add no-default-ignore option, fixes #45<commit_after>use std::path::MAIN_SEPARATOR;
use std::process::Command;

use clap::{App, Arg, Error};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub signal: Option<String>,
    pub restart: bool,
    pub debug: bool,
    pub run_initially: bool,
    pub no_shell: bool,
    pub no_vcs_ignore: bool,
    pub once: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("clear").status();
}

#[allow(unknown_lints)]
#[allow(or_fun_call)]
pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debug")
                 .help("Print debugging messages to stderr")
                 .short("d")
                 .long("debug"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Forces polling mode")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String)
        .unwrap()
        .join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                               .filter(|ext| !ext.is_empty())
                               .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![format!("*{}.DS_Store", MAIN_SEPARATOR),
                               String::from("*.pyc"),
                               String::from("*.swp")];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        signal: signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debug: args.is_present("debug"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<|endoftext|>


<commit_before>/// Creates Rust structure for new Ruby class
///
/// This macro does not define an actual Ruby class. It only creates structs for using
/// the class in Rust. To define the class in Ruby, use `Class` structure.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Class, RString, Object, VM};
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     fn anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     fn friendly_greeting(name: RString) -> RString {
///         let name = name
///             .map(|name| name.to_string())
///             .unwrap_or("Anonymous".to_string());
///
///         let greeting = format!("Hello dear {}!", name);
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter", None).define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     default_name = 'Anonymous'
///
///     name = defaut_name unless name.is_a?(String)
///
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        #[derive(Debug, PartialEq)]
        pub struct $class {
            value: $crate::types::Value,
        }

        impl From<$crate::types::Value> for $class {
            fn from(value: $crate::types::Value) -> Self {
                $class { value: value }
            }
        }

        impl $crate::Object for $class {
            #[inline]
            fn value(&self) -> $crate::types::Value {
                self.value
            }
        }
    }
}

/// Creates unsafe callbacks for Ruby methods
///
/// This macro is unsafe, because:
///
///  - it uses automatic unsafe conversions for arguments
///     (no guarantee that Ruby objects match the types which you expect);
///  - no bound checks for the array of provided arguments
///     (no guarantee that all the expected arguments are provided);
///
/// That is why creating callbacks in unsafe way may cause panics.
///
/// Due to the same reasons unsafe callbacks are faster.
///
/// Use it when:
///
///  - you own the Ruby code which passes arguments to callback;
///  - you are sure that all the object has correct type;
///  - you are sure that all the required arguments are provided;
///  - Ruby code has a good test coverage.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Boolean, Class, Fixnum, Object, RString, VM};
///
/// // Creates `string_length_equals` functions
/// unsafe_methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     fn string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! unsafe_methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ty $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            #[allow(unused_mut)]
            pub extern fn $method_name(argc: $crate::types::Argc,
                                       argv: *const $crate::AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let _arguments = $crate::VM::parse_arguments(argc, argv);
                let mut _i = 0;

                $(
                    let $arg_name = unsafe {
                        <$crate::AnyObject as $crate::Object>
                            ::to::<$arg_type>(&_arguments[_i])
                    };

                    _i += 1;
                )*

                $body
            }
        )*
    }
}

/// Creates callbacks for Ruby methods
///
/// Unlike `unsafe_methods!`, this macro is safe, because:
///
///  - it uses safe conversions of arguments (`Object::try_convert_to()`);
///  - it checks if arguments are present;
///
/// Each argument will have type `Result<Object, Error>`.
///
/// For example, if you declare `number: Fixnum` in the method definition, it will have actual
/// type `number: Result<Fixnum, Error>`.
///
/// See examples below and docs for `Object::try_convert_to()` for more information.
///
/// # Examples
///
/// To launch a server in Rust, you plan to write a simple `Server` class
///
/// ```ruby
/// class Server
///   def start(address)
///     # ...
///   end
/// end
/// ```
///
/// The `address` must be `Hash` with the following structure:
///
/// ```ruby
/// {
///   host: 'localhost',
///   port: 8080,
/// }
/// ```
///
/// You want to extract port from it. Default port is `8080` in case when:
///
///  - `address` is not a `Hash`
///  - `address[:port]` is not present
///  - `address[:port]` is not a `Fixnum`
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Class, Fixnum, Hash, NilClass, Object, Symbol, VM};
///
/// class!(Server);
///
/// methods!(
///     Server,
///     itself,
///
///     fn start(address: Hash) -> NilClass {
///         let default_port = 8080;
///
///         let port = address
///             .map(|hash| hash.at(Symbol::new("port")))
///             .and_then(|port| port.try_convert_to::<Fixnum>())
///             .map(|port| port.to_i64())
///             .unwrap_or(default_port);
///
///         // Start server...
///
///         NilClass::new()
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Server", None).define(|itself| {
///         itself.def("start", start);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Server
///   def start(address)
///     default_port = 8080
///
///     port =
///       if address.is_a?(Hash) && address[:port].is_a?(Fixnum)
///         address[:port]
///       else
///         default_port
///       end
///
///     # Start server...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            #[allow(unused_mut)]
            pub extern fn $method_name(argc: $crate::types::Argc,
                                       argv: *const $crate::AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let _arguments = $crate::VM::parse_arguments(argc, argv);
                let mut _i = 0;

                $(
                    let $arg_name =
                        _arguments
                            .get(_i)
                            .ok_or({
                                $crate::result::Error::ArgumentError(
                                    format!(
                                        "Argument '{}: {}' not found for method '{}'",
                                        stringify!($arg_name),
                                        stringify!($arg_type),
                                        stringify!($method_name)
                                    )
                                )
                            }).and_then(|argument| {
                                <$crate::AnyObject as $crate::Object>
                                    ::try_convert_to::<$arg_type>(argument)
                            });

                    _i += 1;
                )*

                $body
            }
        )*
    }
}

/// Makes a Rust struct wrappable for Ruby objects.
///
/// **Note:** Currently to be able to use `wrappable_struct!` macro, you should include
/// `lazy_static` crate to the crate you are working on.
///
/// `Cargo.toml`
///
/// ```toml
/// lazy_static = "0.2.1" # the version is not a strict requirement
/// ```
///
/// Crate root `lib.rs` or `main.rs`
///
/// ```ignore
/// #[macro_use]
/// extern crate lazy_static;
/// ```
///
/// # Arguments
///
///  - `$struct_name` is name of the actual Rust struct. This structure has to be public (`pub`).
///
///  - `$wrapper` is a name for the structcure which will be created to wrap the `$struct_name`.
///
///     The wrapper will be created automatically by the macro.
///
///  - `$static_name` is a name for a static variable which will contain the wrapper.
///
///     The static variable will be created automatically by the macro.
///
///     This variable has to be passed to `wrap_data()` and `get_data()` functions (see examples).
///
///     Also, these variables describe the structure in general, but not some specific object.
///     So you should pass the same wrapper static variable when wrapping/getting data of the same
///     kind for different ruby objects.
///
///     For example,
///
///     ```ignore
///     server1.get_data(&*SERVER_WRAPPER);
///     server2.get_data(&*SERVER_WRAPPER); // <-- the same `SERVER_WRAPPER`
///     ```
///
/// # Examples
///
/// Wrap `Server` structs to `RubyServer` objects
///
/// ```
/// #[macro_use] extern crate ruru;
/// #[macro_use] extern crate lazy_static;
///
/// use ruru::{AnyObject, Class, Fixnum, Object, RString, VM};
///
/// // The structure which we want to wrap
/// pub struct Server {
///     host: String,
///     port: u16,
/// }
///
/// impl Server {
///     fn new(host: String, port: u16) -> Self {
///         Server {
///             host: host,
///             port: port,
///         }
///     }
///
///     fn host(&self) -> &str {
///         &self.host
///     }
///
///     fn port(&self) -> u16 {
///         self.port
///     }
/// }
///
/// wrappable_struct!(Server, ServerWrapper, SERVER_WRAPPER);
///
/// class!(RubyServer);
///
/// methods!(
///     RubyServer,
///     itself,
///
///     fn ruby_server_new(host: RString, port: Fixnum) -> AnyObject {
///         let server = Server::new(host.unwrap().to_string(),
///                                  port.unwrap().to_i64() as u16);
///
///         Class::from_existing("RubyServer").wrap_data(server, &*SERVER_WRAPPER)
///     }
///
///     fn ruby_server_host() -> RString {
///         let host = itself.get_data(&*SERVER_WRAPPER).host();
///
///         RString::new(host)
///     }
///
///     fn ruby_server_port() -> Fixnum {
///         let port = itself.get_data(&*SERVER_WRAPPER).port();
///
///         Fixnum::new(port as i64)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("RubyServer", None).define(|itself| {
///         itself.def_self("new", ruby_server_new);
///
///         itself.def("host", ruby_server_host);
///         itself.def("port", ruby_server_port);
///     });
/// }
/// ```
///
/// To use the `RubyServer` class in Ruby:
///
/// ```ruby
/// server = RubyServer.new("127.0.0.1", 3000)
///
/// server.host == "127.0.0.1"
/// server.port == 3000
/// ```
#[macro_export]
macro_rules! wrappable_struct {
    ($struct_name: ty, $wrapper: ident, $static_name: ident) => {
        pub struct $wrapper<T> {
            data_type: $crate::types::DataType,
            _marker: ::std::marker::PhantomData<T>,
        }

        lazy_static! {
            pub static ref $static_name: $wrapper<$struct_name> = $wrapper::new();
        }

        impl<T> $wrapper<T> {
            fn new() -> $wrapper<T> {
                let name = concat!("Ruru/", stringify!($struct_name));
                let name = $crate::util::str_to_cstring(name);
                let reserved_bytes: [*mut $crate::types::c_void; 2] = [::std::ptr::null_mut(); 2];

                let data_type = $crate::types::DataType {
                    wrap_struct_name: name.into_raw(),
                    parent: ::std::ptr::null(),
                    data: ::std::ptr::null_mut(),
                    flags: $crate::types::Value::from(0),

                    function: $crate::types::DataTypeFunction {
                        dmark: None,
                        dfree: Some($crate::typed_data::free::<T>),
                        dsize: None,
                        reserved: reserved_bytes,
                    },
                };

                $wrapper {
                    data_type: data_type,
                    _marker: ::std::marker::PhantomData,
                }
            }
        }

        unsafe impl<T> Sync for $wrapper<T> {}

        // Set constraint to be able to wrap and get data only for type `T`
        impl<T> $crate::typed_data::DataTypeWrapper<T> for $wrapper<T> {
            fn data_type(&self) -> &$crate::types::DataType {
                &self.data_type
            }
        }
    }
}
<commit_msg>Add info about the result of wrappable_struct!<commit_after>/// Creates Rust structure for new Ruby class
///
/// This macro does not define an actual Ruby class. It only creates structs for using
/// the class in Rust. To define the class in Ruby, use `Class` structure.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Class, RString, Object, VM};
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     fn anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     fn friendly_greeting(name: RString) -> RString {
///         let name = name
///             .map(|name| name.to_string())
///             .unwrap_or("Anonymous".to_string());
///
///         let greeting = format!("Hello dear {}!", name);
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter", None).define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     default_name = 'Anonymous'
///
///     name = defaut_name unless name.is_a?(String)
///
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        #[derive(Debug, PartialEq)]
        pub struct $class {
            value: $crate::types::Value,
        }

        impl From<$crate::types::Value> for $class {
            fn from(value: $crate::types::Value) -> Self {
                $class { value: value }
            }
        }

        impl $crate::Object for $class {
            #[inline]
            fn value(&self) -> $crate::types::Value {
                self.value
            }
        }
    }
}

/// Creates unsafe callbacks for Ruby methods
///
/// This macro is unsafe, because:
///
///  - it uses automatic unsafe conversions for arguments
///     (no guarantee that Ruby objects match the types which you expect);
///  - no bound checks for the array of provided arguments
///     (no guarantee that all the expected arguments are provided);
///
/// That is why creating callbacks in unsafe way may cause panics.
///
/// Due to the same reasons unsafe callbacks are faster.
///
/// Use it when:
///
///  - you own the Ruby code which passes arguments to callback;
///  - you are sure that all the object has correct type;
///  - you are sure that all the required arguments are provided;
///  - Ruby code has a good test coverage.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Boolean, Class, Fixnum, Object, RString, VM};
///
/// // Creates `string_length_equals` functions
/// unsafe_methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     fn string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! unsafe_methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ty $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            #[allow(unused_mut)]
            pub extern fn $method_name(argc: $crate::types::Argc,
                                       argv: *const $crate::AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let _arguments = $crate::VM::parse_arguments(argc, argv);
                let mut _i = 0;

                $(
                    let $arg_name = unsafe {
                        <$crate::AnyObject as $crate::Object>
                            ::to::<$arg_type>(&_arguments[_i])
                    };

                    _i += 1;
                )*

                $body
            }
        )*
    }
}

/// Creates callbacks for Ruby methods
///
/// Unlike `unsafe_methods!`, this macro is safe, because:
///
///  - it uses safe conversions of arguments (`Object::try_convert_to()`);
///  - it checks if arguments are present;
///
/// Each argument will have type `Result<Object, Error>`.
///
/// For example, if you declare `number: Fixnum` in the method definition, it will have actual
/// type `number: Result<Fixnum, Error>`.
///
/// See examples below and docs for `Object::try_convert_to()` for more information.
///
/// # Examples
///
/// To launch a server in Rust, you plan to write a simple `Server` class
///
/// ```ruby
/// class Server
///   def start(address)
///     # ...
///   end
/// end
/// ```
///
/// The `address` must be `Hash` with the following structure:
///
/// ```ruby
/// {
///   host: 'localhost',
///   port: 8080,
/// }
/// ```
///
/// You want to extract port from it. Default port is `8080` in case when:
///
///  - `address` is not a `Hash`
///  - `address[:port]` is not present
///  - `address[:port]` is not a `Fixnum`
///
/// ```
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{Class, Fixnum, Hash, NilClass, Object, Symbol, VM};
///
/// class!(Server);
///
/// methods!(
///     Server,
///     itself,
///
///     fn start(address: Hash) -> NilClass {
///         let default_port = 8080;
///
///         let port = address
///             .map(|hash| hash.at(Symbol::new("port")))
///             .and_then(|port| port.try_convert_to::<Fixnum>())
///             .map(|port| port.to_i64())
///             .unwrap_or(default_port);
///
///         // Start server...
///
///         NilClass::new()
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Server", None).define(|itself| {
///         itself.def("start", start);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Server
///   def start(address)
///     default_port = 8080
///
///     port =
///       if address.is_a?(Hash) && address[:port].is_a?(Fixnum)
///         address[:port]
///       else
///         default_port
///       end
///
///     # Start server...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            #[allow(unused_mut)]
            pub extern fn $method_name(argc: $crate::types::Argc,
                                       argv: *const $crate::AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let _arguments = $crate::VM::parse_arguments(argc, argv);
                let mut _i = 0;

                $(
                    let $arg_name =
                        _arguments
                            .get(_i)
                            .ok_or({
                                $crate::result::Error::ArgumentError(
                                    format!(
                                        "Argument '{}: {}' not found for method '{}'",
                                        stringify!($arg_name),
                                        stringify!($arg_type),
                                        stringify!($method_name)
                                    )
                                )
                            }).and_then(|argument| {
                                <$crate::AnyObject as $crate::Object>
                                    ::try_convert_to::<$arg_type>(argument)
                            });

                    _i += 1;
                )*

                $body
            }
        )*
    }
}

/// Makes a Rust struct wrappable for Ruby objects.
///
/// **Note:** Currently to be able to use `wrappable_struct!` macro, you should include
/// `lazy_static` crate to the crate you are working on.
///
/// `Cargo.toml`
///
/// ```toml
/// lazy_static = "0.2.1" # the version is not a strict requirement
/// ```
///
/// Crate root `lib.rs` or `main.rs`
///
/// ```ignore
/// #[macro_use]
/// extern crate lazy_static;
/// ```
///
/// # Arguments
///
///  - `$struct_name` is name of the actual Rust struct. This structure has to be public (`pub`).
///
///  - `$wrapper` is a name for the structcure which will be created to wrap the `$struct_name`.
///
///     The wrapper will be created automatically by the macro.
///
///  - `$static_name` is a name for a static variable which will contain the wrapper.
///
///     The static variable will be created automatically by the macro.
///
///     This variable has to be passed to `wrap_data()` and `get_data()` functions (see examples).
///
///     Also, these variables describe the structure in general, but not some specific object.
///     So you should pass the same wrapper static variable when wrapping/getting data of the same
///     kind for different ruby objects.
///
///     For example,
///
///     ```ignore
///     server1.get_data(&*SERVER_WRAPPER);
///     server2.get_data(&*SERVER_WRAPPER); // <-- the same `SERVER_WRAPPER`
///     ```
///
/// The result of `wrappable_struct!` is:
///
/// ```ignore
/// wrappable_struct!(Server, ServerWrapper, SERVER_WRAPPER);
///
/// // produces
///
/// struct ServerWrapper {
///     // ...
/// }
///
/// pub static ref SERVER_WRAPPER: ServerWrapper<Server> = // ...
/// ```
///
/// # Examples
///
/// Wrap `Server` structs to `RubyServer` objects
///
/// ```
/// #[macro_use] extern crate ruru;
/// #[macro_use] extern crate lazy_static;
///
/// use ruru::{AnyObject, Class, Fixnum, Object, RString, VM};
///
/// // The structure which we want to wrap
/// pub struct Server {
///     host: String,
///     port: u16,
/// }
///
/// impl Server {
///     fn new(host: String, port: u16) -> Self {
///         Server {
///             host: host,
///             port: port,
///         }
///     }
///
///     fn host(&self) -> &str {
///         &self.host
///     }
///
///     fn port(&self) -> u16 {
///         self.port
///     }
/// }
///
/// wrappable_struct!(Server, ServerWrapper, SERVER_WRAPPER);
///
/// class!(RubyServer);
///
/// methods!(
///     RubyServer,
///     itself,
///
///     fn ruby_server_new(host: RString, port: Fixnum) -> AnyObject {
///         let server = Server::new(host.unwrap().to_string(),
///                                  port.unwrap().to_i64() as u16);
///
///         Class::from_existing("RubyServer").wrap_data(server, &*SERVER_WRAPPER)
///     }
///
///     fn ruby_server_host() -> RString {
///         let host = itself.get_data(&*SERVER_WRAPPER).host();
///
///         RString::new(host)
///     }
///
///     fn ruby_server_port() -> Fixnum {
///         let port = itself.get_data(&*SERVER_WRAPPER).port();
///
///         Fixnum::new(port as i64)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("RubyServer", None).define(|itself| {
///         itself.def_self("new", ruby_server_new);
///
///         itself.def("host", ruby_server_host);
///         itself.def("port", ruby_server_port);
///     });
/// }
/// ```
///
/// To use the `RubyServer` class in Ruby:
///
/// ```ruby
/// server = RubyServer.new("127.0.0.1", 3000)
///
/// server.host == "127.0.0.1"
/// server.port == 3000
/// ```
#[macro_export]
macro_rules! wrappable_struct {
    ($struct_name: ty, $wrapper: ident, $static_name: ident) => {
        pub struct $wrapper<T> {
            data_type: $crate::types::DataType,
            _marker: ::std::marker::PhantomData<T>,
        }

        lazy_static! {
            pub static ref $static_name: $wrapper<$struct_name> = $wrapper::new();
        }

        impl<T> $wrapper<T> {
            fn new() -> $wrapper<T> {
                let name = concat!("Ruru/", stringify!($struct_name));
                let name = $crate::util::str_to_cstring(name);
                let reserved_bytes: [*mut $crate::types::c_void; 2] = [::std::ptr::null_mut(); 2];

                let data_type = $crate::types::DataType {
                    wrap_struct_name: name.into_raw(),
                    parent: ::std::ptr::null(),
                    data: ::std::ptr::null_mut(),
                    flags: $crate::types::Value::from(0),

                    function: $crate::types::DataTypeFunction {
                        dmark: None,
                        dfree: Some($crate::typed_data::free::<T>),
                        dsize: None,
                        reserved: reserved_bytes,
                    },
                };

                $wrapper {
                    data_type: data_type,
                    _marker: ::std::marker::PhantomData,
                }
            }
        }

        unsafe impl<T> Sync for $wrapper<T> {}

        // Set constraint to be able to wrap and get data only for type `T`
        impl<T> $crate::typed_data::DataTypeWrapper<T> for $wrapper<T> {
            fn data_type(&self) -> &$crate::types::DataType {
                &self.data_type
            }
        }
    }
}
<|endoftext|>


<commit_before>//!  Decoding of GIF Images
//!
//!  GIF (Graphics Interchange Format) is an image format that supports lossless compression.
//!
//!  # Related Links
//!  * <http://www.w3.org/Graphics/GIF/spec-gif89a.txt> - The GIF Specification
//!
//! # Examples
//! ```rust,no_run
//! use image::gif::{GifDecoder, Encoder};
//! use image::{ImageDecoder, AnimationDecoder};
//! use std::fs::File;
//! # fn main() -> std::io::Result<()> {
//! // Decode a gif into frames
//! let file_in = File::open("foo.gif")?;
//! let mut decoder = GifDecoder::new(file_in).unwrap();
//! let frames = decoder.into_frames();
//! let frames = frames.collect_frames().expect("error decoding gif");
//!
//! // Encode frames into a gif and save to a file
//! let mut file_out = File::open("out.gif")?;
//! let mut encoder = Encoder::new(file_out);
//! encoder.encode_frames(frames.into_iter());
//! # Ok(())
//! # }
//! ```
#![allow(clippy::while_let_loop)]

extern crate gif;
extern crate num_rational;

use std::clone::Clone;
use std::cmp::min;
use std::convert::TryFrom;
use std::io::{self, Cursor, Read, Write};
use std::marker::PhantomData;
use std::mem;

use self::gif::{ColorOutput, SetParameter};
pub use self::gif::{DisposalMethod, Frame};

use animation;
use buffer::{ImageBuffer, Pixel};
use color::{self, Rgba};
use image::{self, AnimationDecoder, ImageDecoder, ImageError, ImageResult};
use num_rational::Ratio;

/// GIF decoder
pub struct GifDecoder<R: Read> {
    reader: gif::Reader<R>,
}

impl<R: Read> GifDecoder<R> {
    /// Creates a new decoder that decodes the input steam ```r```
    pub fn new(r: R) -> ImageResult<GifDecoder<R>> {
        let mut decoder = gif::Decoder::new(r);
        decoder.set(ColorOutput::RGBA);

        Ok(GifDecoder {
            reader: decoder.read_info()?,
        })
    }
}

/// Wrapper struct around a `Cursor<Vec<u8>>`
pub struct GifReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
impl<R> Read for GifReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        if self.0.position() == 0 && buf.is_empty() {
            mem::swap(buf, self.0.get_mut());
            Ok(buf.len())
        } else {
            self.0.read_to_end(buf)
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for GifDecoder<R> {
    type Reader = GifReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (u32::from(self.reader.width()), u32::from(self.reader.height()))
    }

    fn color_type(&self) -> color::ColorType {
        color::ColorType::Rgba8
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(GifReader(Cursor::new(image::decoder_to_vec(self)?), PhantomData))
    }

    fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));

        let (f_width, f_height, left, top);

        if let Some(frame) = self.reader.next_frame_info()? {
            left = u32::from(frame.left);
            top = u32::from(frame.top);
            f_width = u32::from(frame.width);
            f_height = u32::from(frame.height);
        } else {
            return Err(ImageError::ImageEnd);
        }

        self.reader.read_into_buffer(buf)?;

        let (width, height) = (u32::from(self.reader.width()), u32::from(self.reader.height()));
        if (left, top) != (0, 0) || (width, height) != (f_width, f_height) {
            // This is somewhat of an annoying case. The image we read into `buf` doesn't take up
            // the whole buffer and now we need to properly insert borders. For simplicity this code
            // currently takes advantage of the `ImageBuffer::from_fn` function to make a second
            // ImageBuffer that is properly positioned, and then copies it back into `buf`.
            //
            // TODO: Implement this without any allocation.

            // See the comments inside `<GifFrameIterator as Iterator>::next` about
            // the error handling of `from_raw`.
            let image = ImageBuffer::from_raw(f_width, f_height, &mut *buf).ok_or_else(
                || ImageError::UnsupportedError("Image dimensions are too large".into())
            )?;

            // Recover the full image
            let image_buffer = ImageBuffer::from_fn(width, height, |x, y| {
                let x = x.wrapping_sub(left);
                let y = y.wrapping_sub(top);
                if x < image.width() && y < image.height() {
                    *image.get_pixel(x, y)
                } else {
                    Rgba([0, 0, 0, 0])
                }
            });
            buf.copy_from_slice(&mut image_buffer.into_raw());
        }
        Ok(())
    }
}

struct GifFrameIterator<R: Read> {
    reader: gif::Reader<R>,

    width: u32,
    height: u32,

    non_disposed_frame: ImageBuffer<Rgba<u8>, Vec<u8>>,
}

impl<R: Read> GifFrameIterator<R> {
    fn new(decoder: GifDecoder<R>) -> GifFrameIterator<R> {
        let (width, height) = decoder.dimensions();

        // TODO: Avoid this cast
        let (width, height) = (width as u32, height as u32);

        // intentionally ignore the background color for web compatibility

        // create the first non disposed frame
        let non_disposed_frame = ImageBuffer::from_pixel(width, height, Rgba([0, 0, 0, 0]));

        GifFrameIterator {
            reader: decoder.reader,
            width,
            height,
            non_disposed_frame,
        }
    }
}

impl<R: Read> Iterator for GifFrameIterator<R> {
    type Item = ImageResult<animation::Frame>;

    fn next(&mut self) -> Option<ImageResult<animation::Frame>> {
        // begin looping over each frame
        let (left, top, delay, dispose, f_width, f_height);

        match self.reader.next_frame_info() {
            Ok(frame_info) => {
                if let Some(frame) = frame_info {
                    left = u32::from(frame.left);
                    top = u32::from(frame.top);
                    f_width = u32::from(frame.width);
                    f_height = u32::from(frame.height);

                    // frame.delay is in units of 10ms so frame.delay*10 is in ms
                    delay = Ratio::new(frame.delay * 10, 1);
                    dispose = frame.dispose;
                } else {
                    // no more frames
                    return None;
                }
            },
            Err(err) => return Some(Err(err.into())),
        }

        let mut vec = vec![0; self.reader.buffer_size()];
        if let Err(err) = self.reader.fill_buffer(&mut vec) {
            return Some(Err(err.into()));
        }

        // create the image buffer from the raw frame.
        // `buffer_size` uses wrapping arithmetics, thus might not report the
        // correct storage requirement if the result does not fit in `usize`.
        // on the other hand, `ImageBuffer::from_raw` detects overflow and
        // reports by returning `None`.
        let image_buffer_raw = match ImageBuffer::from_raw(f_width, f_height, vec) {
            Some(image_buffer_raw) => image_buffer_raw,
            None => {
                return Some(Err(ImageError::UnsupportedError(
                    "Image dimensions are too large".into(),
                )))
            }
        };

        // if `image_buffer_raw`'s frame exactly matches the entire image, then
        // use it directly.
        //
        // otherwise, `image_buffer_raw` represents a smaller image.
        // create a new image of the target size and place
        // `image_buffer_raw` within it. the outside region is filled with
        // transparent pixels.
        let mut image_buffer =
            full_image_from_frame(self.width, self.height, image_buffer_raw, left, top);

        // loop over all pixels, checking if any pixels from the non disposed
        // frame need to be used
        for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
            let previous_img_buffer = &self.non_disposed_frame;
            let adjusted_pixel: &mut Rgba<u8> = pixel;
            let previous_pixel: &Rgba<u8> = previous_img_buffer.get_pixel(x, y);

            let pixel_alpha = adjusted_pixel.channels()[3];

            // If a pixel is not visible then we show the non disposed frame pixel instead
            if pixel_alpha == 0 {
                adjusted_pixel.blend(previous_pixel);
            }
        }

        let frame = animation::Frame::from_parts(
            image_buffer.clone(), 0, 0, delay
        );

        match dispose {
            DisposalMethod::Any => {
                // do nothing
                // (completely replace this frame with the next)
            }
            DisposalMethod::Keep => {
                // do not dispose
                // (keep pixels from this frame)
                self.non_disposed_frame = image_buffer;
            }
            DisposalMethod::Background => {
                // restore to background color
                // (background shows through transparent pixels in the next frame)
                for y in top..min(top + f_height, self.height) {
                    for x in left..min(left + f_width, self.width) {
                        self.non_disposed_frame.put_pixel(x, y, Rgba([0, 0, 0, 0]));
                    }
                }
            }
            DisposalMethod::Previous => {
                // restore to previous
                // (dispose frames leaving the last none disposal frame)
            }
        };

        Some(Ok(frame))
    }
}

/// Given a frame subimage, construct a full image of size
/// `(screen_width, screen_height)` by placing it at the top-left coordinates
/// `(left, top)`. The remaining portion is filled with transparent pixels.
fn full_image_from_frame(
    screen_width: u32,
    screen_height: u32,
    image: crate::RgbaImage,
    left: u32,
    top: u32,
) -> crate::RgbaImage {
    if (left, top) == (0, 0) && (screen_width, screen_height) == (image.width(), image.height()) {
        image
    } else {
        ImageBuffer::from_fn(screen_width, screen_height, |x, y| {
            let x = x.wrapping_sub(left);
            let y = y.wrapping_sub(top);
            if x < image.width() && y < image.height() {
                *image.get_pixel(x, y)
            } else {
                Rgba([0, 0, 0, 0])
            }
        })
    }
}

impl<'a, R: Read + 'a> AnimationDecoder<'a> for GifDecoder<R> {
    fn into_frames(self) -> animation::Frames<'a> {
        animation::Frames::new(Box::new(GifFrameIterator::new(self)))
    }
}

/// GIF encoder.
pub struct Encoder<W: Write> {
    w: Option<W>,
    gif_encoder: Option<gif::Encoder<W>>,
}

impl<W: Write> Encoder<W> {
    /// Creates a new GIF encoder.
    pub fn new(w: W) -> Encoder<W> {
        Encoder {
            w: Some(w),
            gif_encoder: None,
        }
    }
    /// Encodes a frame.
    pub fn encode(&mut self, frame: &Frame) -> ImageResult<()> {
        let result;
        if let Some(ref mut encoder) = self.gif_encoder {
            result = encoder.write_frame(frame).map_err(|err| err.into());
        } else {
            let writer = self.w.take().unwrap();
            let mut encoder = gif::Encoder::new(writer, frame.width, frame.height, &[])?;
            result = encoder.write_frame(&frame).map_err(|err| err.into());
            self.gif_encoder = Some(encoder);
        }
        result
    }

    /// Encodes Frames.
    /// Consider using `try_encode_frames` instead to encode an `animation::Frames` like iterator.
    pub fn encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
    where
        F: IntoIterator<Item = animation::Frame>
    {
        for img_frame in frames {
            self.encode_single_frame(img_frame)?;
        }
        Ok(())
    }

    /// Try to encode a collection of `ImageResult<animation::Frame>` objects.
    /// Use this function to encode an `animation::Frames` like iterator.
    /// Whenever an `Err` item is encountered, that value is returned without further actions.
    pub fn try_encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
    where
        F: IntoIterator<Item = ImageResult<animation::Frame>>
    {
        for img_frame in frames {
            self.encode_single_frame(img_frame?)?;
        }
        Ok(())
    }

    fn encode_single_frame(&mut self, img_frame: animation::Frame) -> ImageResult<()> {
        // get the delay before converting img_frame
        let frame_delay = img_frame.delay().to_integer();
        // convert img_frame into RgbaImage
        let rbga_frame = img_frame.into_buffer();

        // Create the gif::Frame from the animation::Frame
        let mut frame = Frame::from_rgba(rbga_frame.width() as u16, rbga_frame.height() as u16, &mut rbga_frame.into_raw());
        frame.delay = frame_delay;

        // encode the gif::Frame
        self.encode(&frame)
    }
}

impl From<gif::DecodingError> for ImageError {
    fn from(err: gif::DecodingError) -> ImageError {
        use self::gif::DecodingError::*;
        match err {
            Format(desc) | Internal(desc) => ImageError::FormatError(desc.into()),
            Io(io_err) => ImageError::IoError(io_err),
        }
    }
}
<commit_msg>Fix borrow checker issue for old rustc versions<commit_after>//!  Decoding of GIF Images
//!
//!  GIF (Graphics Interchange Format) is an image format that supports lossless compression.
//!
//!  # Related Links
//!  * <http://www.w3.org/Graphics/GIF/spec-gif89a.txt> - The GIF Specification
//!
//! # Examples
//! ```rust,no_run
//! use image::gif::{GifDecoder, Encoder};
//! use image::{ImageDecoder, AnimationDecoder};
//! use std::fs::File;
//! # fn main() -> std::io::Result<()> {
//! // Decode a gif into frames
//! let file_in = File::open("foo.gif")?;
//! let mut decoder = GifDecoder::new(file_in).unwrap();
//! let frames = decoder.into_frames();
//! let frames = frames.collect_frames().expect("error decoding gif");
//!
//! // Encode frames into a gif and save to a file
//! let mut file_out = File::open("out.gif")?;
//! let mut encoder = Encoder::new(file_out);
//! encoder.encode_frames(frames.into_iter());
//! # Ok(())
//! # }
//! ```
#![allow(clippy::while_let_loop)]

extern crate gif;
extern crate num_rational;

use std::clone::Clone;
use std::cmp::min;
use std::convert::TryFrom;
use std::io::{self, Cursor, Read, Write};
use std::marker::PhantomData;
use std::mem;

use self::gif::{ColorOutput, SetParameter};
pub use self::gif::{DisposalMethod, Frame};

use animation;
use buffer::{ImageBuffer, Pixel};
use color::{self, Rgba};
use image::{self, AnimationDecoder, ImageDecoder, ImageError, ImageResult};
use num_rational::Ratio;

/// GIF decoder
pub struct GifDecoder<R: Read> {
    reader: gif::Reader<R>,
}

impl<R: Read> GifDecoder<R> {
    /// Creates a new decoder that decodes the input steam ```r```
    pub fn new(r: R) -> ImageResult<GifDecoder<R>> {
        let mut decoder = gif::Decoder::new(r);
        decoder.set(ColorOutput::RGBA);

        Ok(GifDecoder {
            reader: decoder.read_info()?,
        })
    }
}

/// Wrapper struct around a `Cursor<Vec<u8>>`
pub struct GifReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
impl<R> Read for GifReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        if self.0.position() == 0 && buf.is_empty() {
            mem::swap(buf, self.0.get_mut());
            Ok(buf.len())
        } else {
            self.0.read_to_end(buf)
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for GifDecoder<R> {
    type Reader = GifReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        (u32::from(self.reader.width()), u32::from(self.reader.height()))
    }

    fn color_type(&self) -> color::ColorType {
        color::ColorType::Rgba8
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(GifReader(Cursor::new(image::decoder_to_vec(self)?), PhantomData))
    }

    fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));

        let (f_width, f_height, left, top);

        if let Some(frame) = self.reader.next_frame_info()? {
            left = u32::from(frame.left);
            top = u32::from(frame.top);
            f_width = u32::from(frame.width);
            f_height = u32::from(frame.height);
        } else {
            return Err(ImageError::ImageEnd);
        }

        self.reader.read_into_buffer(buf)?;

        let (width, height) = (u32::from(self.reader.width()), u32::from(self.reader.height()));
        if (left, top) != (0, 0) || (width, height) != (f_width, f_height) {
            // This is somewhat of an annoying case. The image we read into `buf` doesn't take up
            // the whole buffer and now we need to properly insert borders. For simplicity this code
            // currently takes advantage of the `ImageBuffer::from_fn` function to make a second
            // ImageBuffer that is properly positioned, and then copies it back into `buf`.
            //
            // TODO: Implement this without any allocation.

            // Recover the full image
            let image_buffer = {
                // See the comments inside `<GifFrameIterator as Iterator>::next` about
                // the error handling of `from_raw`.
                let image = ImageBuffer::from_raw(f_width, f_height, &mut *buf).ok_or_else(
                    || ImageError::UnsupportedError("Image dimensions are too large".into())
                )?;

                ImageBuffer::from_fn(width, height, |x, y| {
                    let x = x.wrapping_sub(left);
                    let y = y.wrapping_sub(top);
                    if x < image.width() && y < image.height() {
                        *image.get_pixel(x, y)
                    } else {
                        Rgba([0, 0, 0, 0])
                    }
                })
            };
            buf.copy_from_slice(&mut image_buffer.into_raw());
        }
        Ok(())
    }
}

struct GifFrameIterator<R: Read> {
    reader: gif::Reader<R>,

    width: u32,
    height: u32,

    non_disposed_frame: ImageBuffer<Rgba<u8>, Vec<u8>>,
}

impl<R: Read> GifFrameIterator<R> {
    fn new(decoder: GifDecoder<R>) -> GifFrameIterator<R> {
        let (width, height) = decoder.dimensions();

        // TODO: Avoid this cast
        let (width, height) = (width as u32, height as u32);

        // intentionally ignore the background color for web compatibility

        // create the first non disposed frame
        let non_disposed_frame = ImageBuffer::from_pixel(width, height, Rgba([0, 0, 0, 0]));

        GifFrameIterator {
            reader: decoder.reader,
            width,
            height,
            non_disposed_frame,
        }
    }
}

impl<R: Read> Iterator for GifFrameIterator<R> {
    type Item = ImageResult<animation::Frame>;

    fn next(&mut self) -> Option<ImageResult<animation::Frame>> {
        // begin looping over each frame
        let (left, top, delay, dispose, f_width, f_height);

        match self.reader.next_frame_info() {
            Ok(frame_info) => {
                if let Some(frame) = frame_info {
                    left = u32::from(frame.left);
                    top = u32::from(frame.top);
                    f_width = u32::from(frame.width);
                    f_height = u32::from(frame.height);

                    // frame.delay is in units of 10ms so frame.delay*10 is in ms
                    delay = Ratio::new(frame.delay * 10, 1);
                    dispose = frame.dispose;
                } else {
                    // no more frames
                    return None;
                }
            },
            Err(err) => return Some(Err(err.into())),
        }

        let mut vec = vec![0; self.reader.buffer_size()];
        if let Err(err) = self.reader.fill_buffer(&mut vec) {
            return Some(Err(err.into()));
        }

        // create the image buffer from the raw frame.
        // `buffer_size` uses wrapping arithmetics, thus might not report the
        // correct storage requirement if the result does not fit in `usize`.
        // on the other hand, `ImageBuffer::from_raw` detects overflow and
        // reports by returning `None`.
        let image_buffer_raw = match ImageBuffer::from_raw(f_width, f_height, vec) {
            Some(image_buffer_raw) => image_buffer_raw,
            None => {
                return Some(Err(ImageError::UnsupportedError(
                    "Image dimensions are too large".into(),
                )))
            }
        };

        // if `image_buffer_raw`'s frame exactly matches the entire image, then
        // use it directly.
        //
        // otherwise, `image_buffer_raw` represents a smaller image.
        // create a new image of the target size and place
        // `image_buffer_raw` within it. the outside region is filled with
        // transparent pixels.
        let mut image_buffer =
            full_image_from_frame(self.width, self.height, image_buffer_raw, left, top);

        // loop over all pixels, checking if any pixels from the non disposed
        // frame need to be used
        for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
            let previous_img_buffer = &self.non_disposed_frame;
            let adjusted_pixel: &mut Rgba<u8> = pixel;
            let previous_pixel: &Rgba<u8> = previous_img_buffer.get_pixel(x, y);

            let pixel_alpha = adjusted_pixel.channels()[3];

            // If a pixel is not visible then we show the non disposed frame pixel instead
            if pixel_alpha == 0 {
                adjusted_pixel.blend(previous_pixel);
            }
        }

        let frame = animation::Frame::from_parts(
            image_buffer.clone(), 0, 0, delay
        );

        match dispose {
            DisposalMethod::Any => {
                // do nothing
                // (completely replace this frame with the next)
            }
            DisposalMethod::Keep => {
                // do not dispose
                // (keep pixels from this frame)
                self.non_disposed_frame = image_buffer;
            }
            DisposalMethod::Background => {
                // restore to background color
                // (background shows through transparent pixels in the next frame)
                for y in top..min(top + f_height, self.height) {
                    for x in left..min(left + f_width, self.width) {
                        self.non_disposed_frame.put_pixel(x, y, Rgba([0, 0, 0, 0]));
                    }
                }
            }
            DisposalMethod::Previous => {
                // restore to previous
                // (dispose frames leaving the last none disposal frame)
            }
        };

        Some(Ok(frame))
    }
}

/// Given a frame subimage, construct a full image of size
/// `(screen_width, screen_height)` by placing it at the top-left coordinates
/// `(left, top)`. The remaining portion is filled with transparent pixels.
fn full_image_from_frame(
    screen_width: u32,
    screen_height: u32,
    image: crate::RgbaImage,
    left: u32,
    top: u32,
) -> crate::RgbaImage {
    if (left, top) == (0, 0) && (screen_width, screen_height) == (image.width(), image.height()) {
        image
    } else {
        ImageBuffer::from_fn(screen_width, screen_height, |x, y| {
            let x = x.wrapping_sub(left);
            let y = y.wrapping_sub(top);
            if x < image.width() && y < image.height() {
                *image.get_pixel(x, y)
            } else {
                Rgba([0, 0, 0, 0])
            }
        })
    }
}

impl<'a, R: Read + 'a> AnimationDecoder<'a> for GifDecoder<R> {
    fn into_frames(self) -> animation::Frames<'a> {
        animation::Frames::new(Box::new(GifFrameIterator::new(self)))
    }
}

/// GIF encoder.
pub struct Encoder<W: Write> {
    w: Option<W>,
    gif_encoder: Option<gif::Encoder<W>>,
}

impl<W: Write> Encoder<W> {
    /// Creates a new GIF encoder.
    pub fn new(w: W) -> Encoder<W> {
        Encoder {
            w: Some(w),
            gif_encoder: None,
        }
    }
    /// Encodes a frame.
    pub fn encode(&mut self, frame: &Frame) -> ImageResult<()> {
        let result;
        if let Some(ref mut encoder) = self.gif_encoder {
            result = encoder.write_frame(frame).map_err(|err| err.into());
        } else {
            let writer = self.w.take().unwrap();
            let mut encoder = gif::Encoder::new(writer, frame.width, frame.height, &[])?;
            result = encoder.write_frame(&frame).map_err(|err| err.into());
            self.gif_encoder = Some(encoder);
        }
        result
    }

    /// Encodes Frames.
    /// Consider using `try_encode_frames` instead to encode an `animation::Frames` like iterator.
    pub fn encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
    where
        F: IntoIterator<Item = animation::Frame>
    {
        for img_frame in frames {
            self.encode_single_frame(img_frame)?;
        }
        Ok(())
    }

    /// Try to encode a collection of `ImageResult<animation::Frame>` objects.
    /// Use this function to encode an `animation::Frames` like iterator.
    /// Whenever an `Err` item is encountered, that value is returned without further actions.
    pub fn try_encode_frames<F>(&mut self, frames: F) -> ImageResult<()>
    where
        F: IntoIterator<Item = ImageResult<animation::Frame>>
    {
        for img_frame in frames {
            self.encode_single_frame(img_frame?)?;
        }
        Ok(())
    }

    fn encode_single_frame(&mut self, img_frame: animation::Frame) -> ImageResult<()> {
        // get the delay before converting img_frame
        let frame_delay = img_frame.delay().to_integer();
        // convert img_frame into RgbaImage
        let rbga_frame = img_frame.into_buffer();

        // Create the gif::Frame from the animation::Frame
        let mut frame = Frame::from_rgba(rbga_frame.width() as u16, rbga_frame.height() as u16, &mut rbga_frame.into_raw());
        frame.delay = frame_delay;

        // encode the gif::Frame
        self.encode(&frame)
    }
}

impl From<gif::DecodingError> for ImageError {
    fn from(err: gif::DecodingError) -> ImageError {
        use self::gif::DecodingError::*;
        match err {
            Format(desc) | Internal(desc) => ImageError::FormatError(desc.into()),
            Io(io_err) => ImageError::IoError(io_err),
        }
    }
}
<|endoftext|>


<commit_before>//! Tokenization of source code.

use std::result::Result::{Ok, Err};
use std::str::Chars;
use std::{error, result};
use token::Token;

/// Result of a lexer operation.
pub type Result = result::Result<Token, Error>;

/// Possible errors due to a lexer operation.
#[derive(PartialEq, Eq, Clone, Show)]
pub enum Error {
    UnknownToken,
    UnclosedComment,
    UnclosedString,
    MalformedInteger,
    Unknown,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnknownToken => "Unknown token",
            Error::UnclosedComment => "Unclosed comment",
            Error::UnclosedString => "Unclosed string",
            Error::MalformedInteger => "Malformed integer",
            Error::Unknown => "Unknown lexer error",
        }
    }
}

/// Yield chars while allowing one char to be "replaced" to be yielded again.
///
/// In the case that a char must be popped in order to determine
/// if it belongs in the current token, replace can be used to
/// remember it for the start of the next token. This works
/// as long as the lexer grammar needs only one char of lookahead.
struct ReplaceOneChars<'a> {
    chars: Chars<'a>,
    replaced: Option<char>,
}

impl<'a> ReplaceOneChars<'a> {
    pub fn new(chars: Chars<'a>) -> ReplaceOneChars<'a> {
        ReplaceOneChars {
            chars: chars,
            replaced: None,
        }
    }

    pub fn replace(&mut self, c: char) {
        self.replaced = Some(c);
    }
}

impl<'a> Iterator for ReplaceOneChars<'a> {
    type Item = char;

    fn next(&mut self) -> Option<char> {
        match self.replaced.take() {
            Some(c) => Some(c),
            None => self.chars.next(),
        }
    }
}

/// The lexer is a tokenizer implemented as an iterator over a string.
/// Iteration  proceeds until the source is successfully tokenized,
/// or an error is encountered.
pub struct Lexer<'a> {
    chars: ReplaceOneChars<'a>,
}

const DECIMAL: uint = 10u;

impl<'a> Lexer<'a> {
    /// Create a new lexer over the provided source code.
    pub fn new(src: &'a str) -> Lexer<'a> {
        Lexer {
            chars: ReplaceOneChars::new(src.chars()),
        }
    }

    /// Consume any remaining chars in underlying source and return error.
    fn error(&mut self, err: Error) -> Result {
        for _ in self.chars { }
        Err(err)
    }

    fn whitespace(&mut self) -> Result {
        loop {
            match self.chars.next() {
                Some(c) => if !c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Whitespace);
                },
                None => return Ok(Token::Whitespace),
            }
        }
    }

    fn integer(&mut self) -> Result {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c.is_digit(DECIMAL) {
                    s.push(c);
                } else if c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Integer(s));
                } else {
                    return self.error(Error::MalformedInteger);
                },
                None => return Ok(Token::Integer(s)),
            }
        }
    }

    fn comment(&mut self) -> Result {
        loop {
            match self.chars.next() {
                Some(c) => if c == ')' {
                    return Ok(Token::Comment);
                },
                None => return self.error(Error::UnclosedComment),
            }
        }
    }

    fn string(&mut self) -> Result {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c == '"' {
                    return Ok(Token::String(s));
                } else {
                    s.push(c);
                },
                None => return self.error(Error::UnclosedString),
            }
        }
    }

    fn call(&mut self) -> Result {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c.is_whitespace() {
                    return Ok(Token::Call(s));
                } else {
                    s.push(c);
                },
                None => return Ok(Token::Call(s)),
            }
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result;

    fn next(&mut self) -> Option<Result> {
        loop {
            let c = match self.chars.next() {
                Some(c) => c,
                None => return None,
            };
            return Some(if c.is_whitespace() {
                self.whitespace()
            } else if c.is_digit(DECIMAL) {
                self.chars.replace(c);
                self.integer()
            } else if c == '(' {
                self.comment()
            } else if c == '"' {
                self.string()
            } else if c == '{' {
                Ok(Token::OpenBrace)
            } else if c == '}' {
                Ok(Token::CloseBrace)
            } else {
                self.chars.replace(c);
                self.call()
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Error};
    use token::Token;

    #[test]
    fn test_empty_string_is_none() {
        assert_eq!(Lexer::new("").next(), None);
    }

    #[test]
    fn test_whitespace() {
        assert_eq!(Lexer::new(" ").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
        assert_eq!(Lexer::new("  \t\t\n\n").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
    }

    #[test]
    fn test_integer() {
        assert_eq!(Lexer::new("0").collect::<Vec<_>>(),
            vec![Ok(Token::Integer("0".to_string()))]);
        assert_eq!(Lexer::new("1.0").collect::<Vec<_>>(),
            vec![Err(Error::MalformedInteger)]);
    }

    #[test]
    fn test_comment() {
        assert_eq!(Lexer::new("(this is a comment)").collect::<Vec<_>>(),
            vec![Ok(Token::Comment)]);
        assert_eq!(Lexer::new("(this is an unclosed comment")
                   .collect::<Vec<_>>(),
            vec![Err(Error::UnclosedComment)]);
    }
    #[test]
    fn test_string() {
        assert_eq!(Lexer::new("\"this is a string\"").collect::<Vec<_>>(),
            vec![Ok(Token::String("this is a string".to_string()))]);
        assert_eq!(Lexer::new("\"this is an unclosed string").collect::<Vec<_>>(),
            vec![Err(Error::UnclosedString)]);
    }

    #[test]
    fn test_call() {
        assert_eq!(Lexer::new("this-is-a-call").collect::<Vec<_>>(),
            vec![Ok(Token::Call("this-is-a-call".to_string()))]);
    }
}
<commit_msg>Add character escapes in strings<commit_after>//! Tokenization of source code.

use std::result::Result::{Ok, Err};
use std::str::Chars;
use std::{error, result};
use token::Token;

/// Result of a lexer operation.
pub type Result<T> = result::Result<T, Error>;

/// Possible errors due to a lexer operation.
#[derive(PartialEq, Eq, Clone, Show)]
pub enum Error {
    UnknownEscape,
    IncompleteEscape,
    UnknownToken,
    UnclosedComment,
    UnclosedString,
    MalformedInteger,
    Unknown,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnknownEscape => "Unknown character escape",
            Error::IncompleteEscape => "Incomplete character escape",
            Error::UnknownToken => "Unknown token",
            Error::UnclosedComment => "Unclosed comment",
            Error::UnclosedString => "Unclosed string",
            Error::MalformedInteger => "Malformed integer",
            Error::Unknown => "Unknown lexer error",
        }
    }
}

/// Yield chars while allowing one char to be "replaced" to be yielded again.
///
/// In the case that a char must be popped in order to determine
/// if it belongs in the current token, replace can be used to
/// remember it for the start of the next token. This works
/// as long as the lexer grammar needs only one char of lookahead.
struct ReplaceOneChars<'a> {
    chars: Chars<'a>,
    replaced: Option<char>,
}

impl<'a> ReplaceOneChars<'a> {
    pub fn new(chars: Chars<'a>) -> ReplaceOneChars<'a> {
        ReplaceOneChars {
            chars: chars,
            replaced: None,
        }
    }

    pub fn replace(&mut self, c: char) {
        self.replaced = Some(c);
    }
}

impl<'a> Iterator for ReplaceOneChars<'a> {
    type Item = char;

    fn next(&mut self) -> Option<char> {
        match self.replaced.take() {
            Some(c) => Some(c),
            None => self.chars.next(),
        }
    }
}

/// The lexer is a tokenizer implemented as an iterator over a string.
/// Iteration  proceeds until the source is successfully tokenized,
/// or an error is encountered.
pub struct Lexer<'a> {
    chars: ReplaceOneChars<'a>,
}

const DECIMAL: uint = 10u;

impl<'a> Lexer<'a> {
    /// Create a new lexer over the provided source code.
    pub fn new(src: &'a str) -> Lexer<'a> {
        Lexer {
            chars: ReplaceOneChars::new(src.chars()),
        }
    }

    /// Consume any remaining chars in underlying source.
    fn consume(&mut self) {
        for _ in self.chars { }
    }

    fn whitespace(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if !c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Whitespace);
                },
                None => return Ok(Token::Whitespace),
            }
        }
    }

    fn integer(&mut self) -> Result<Token> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c.is_digit(DECIMAL) {
                    s.push(c);
                } else if c.is_whitespace() {
                    self.chars.replace(c);
                    return Ok(Token::Integer(s));
                } else {
                    return Err(Error::MalformedInteger);
                },
                None => return Ok(Token::Integer(s)),
            }
        }
    }

    fn comment(&mut self) -> Result<Token> {
        loop {
            match self.chars.next() {
                Some(c) => if c == ')' {
                    return Ok(Token::Comment);
                },
                None => return Err(Error::UnclosedComment),
            }
        }
    }

    fn escape(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => match c {
                '"' => return Ok('"'),
                _ => return Err(Error::UnknownEscape),
            },
            None => return Err(Error::IncompleteEscape),
        }
    }

    fn string(&mut self) -> Result<Token> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c == '\\' {
                    s.push(try!(self.escape()));
                } else if c == '"' {
                    return Ok(Token::String(s));
                } else {
                    s.push(c);
                },
                None => return Err(Error::UnclosedString),
            }
        }
    }

    fn call(&mut self) -> Result<Token> {
        let mut s = String::new();
        loop {
            match self.chars.next() {
                Some(c) => if c.is_whitespace() {
                    return Ok(Token::Call(s));
                } else {
                    s.push(c);
                },
                None => return Ok(Token::Call(s)),
            }
        }
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Result<Token>;

    fn next(&mut self) -> Option<Result<Token>> {
        loop {
            let c = match self.chars.next() {
                Some(c) => c,
                None => return None,
            };
            let result = if c.is_whitespace() {
                self.whitespace()
            } else if c.is_digit(DECIMAL) {
                self.chars.replace(c);
                self.integer()
            } else if c == '(' {
                self.comment()
            } else if c == '"' {
                self.string()
            } else if c == '{' {
                Ok(Token::OpenBrace)
            } else if c == '}' {
                Ok(Token::CloseBrace)
            } else {
                self.chars.replace(c);
                self.call()
            };
            // If we have errored, the rest of the source is invalid.
            if result.is_err() {
                self.consume();
            }
            return Some(result);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Lexer, Error};
    use token::Token;

    #[test]
    fn test_empty_string_is_none() {
        assert_eq!(Lexer::new("").next(), None);
    }

    #[test]
    fn test_whitespace() {
        assert_eq!(Lexer::new(" ").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
        assert_eq!(Lexer::new("  \t\t\n\n").collect::<Vec<_>>(),
            vec![Ok(Token::Whitespace)]);
    }

    #[test]
    fn test_integer() {
        assert_eq!(Lexer::new("0").collect::<Vec<_>>(),
            vec![Ok(Token::Integer("0".to_string()))]);
        assert_eq!(Lexer::new("1.0").collect::<Vec<_>>(),
            vec![Err(Error::MalformedInteger)]);
    }

    #[test]
    fn test_comment() {
        assert_eq!(Lexer::new("(this is a comment)").collect::<Vec<_>>(),
            vec![Ok(Token::Comment)]);
        assert_eq!(Lexer::new("(this is an unclosed comment")
                   .collect::<Vec<_>>(),
            vec![Err(Error::UnclosedComment)]);
    }
    #[test]
    fn test_string() {
        assert_eq!(Lexer::new("\"this is a string\"").collect::<Vec<_>>(),
            vec![Ok(Token::String("this is a string".to_string()))]);
        assert_eq!(Lexer::new("\"this is an unclosed string").collect::<Vec<_>>(),
            vec![Err(Error::UnclosedString)]);
    }

    #[test]
    fn test_call() {
        assert_eq!(Lexer::new("this-is-a-call").collect::<Vec<_>>(),
            vec![Ok(Token::Call("this-is-a-call".to_string()))]);
    }
}
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is() {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt() {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// returns true if this is a tty
#[cfg(unix)]
pub fn is() -> bool {
  let r = unsafe { libc::isatty(libc::STDOUT_FILENO) };
  r != 0
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is() -> bool {
    extern crate kernel32;
    extern crate winapi;
    use winapi::{self, HANDLE, INVALID_HANDLE_VALUE};
    use std::ptr;
    let handle: HANDLE = unsafe {
        kernel32::CreateFileA(
            b"CONOUT$\0".as_ptr() as *const i8,
            winapi::GENERIC_READ | winapi::GENERIC_WRITE,
            winapi::FILE_SHARE_WRITE,
            ptr::null_mut(),
            winapi::OPEN_EXISTING,
            0,
            ptr::null_mut(),
            )
    };
    if handle == INVALID_HANDLE_VALUE {
        println!("handle was invalid");
    }
    let mut out = 0;
    kernel32::GetConsoleMode(handle, &mut out) != 0
}

/// returns true if this is _not_ a tty
pub fn isnt() -> bool {
  !is()
}

#[cfg(test)]
mod tests {
    use super::is;

    #[test]
    fn is_test() {
        assert!(is())
    }
}
<commit_msg>qualify winapi<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is() {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt() {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// returns true if this is a tty
#[cfg(unix)]
pub fn is() -> bool {
  let r = unsafe { libc::isatty(libc::STDOUT_FILENO) };
  r != 0
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is() -> bool {
    extern crate kernel32;
    extern crate winapi;
    use self::winapi::{self, HANDLE, INVALID_HANDLE_VALUE};
    use std::ptr;
    let handle: HANDLE = unsafe {
        kernel32::CreateFileA(
            b"CONOUT$\0".as_ptr() as *const i8,
            winapi::GENERIC_READ | winapi::GENERIC_WRITE,
            winapi::FILE_SHARE_WRITE,
            ptr::null_mut(),
            winapi::OPEN_EXISTING,
            0,
            ptr::null_mut(),
            )
    };
    if handle == INVALID_HANDLE_VALUE {
        println!("handle was invalid");
    }
    let mut out = 0;
    kernel32::GetConsoleMode(handle, &mut out) != 0
}

/// returns true if this is _not_ a tty
pub fn isnt() -> bool {
  !is()
}

#[cfg(test)]
mod tests {
    use super::is;

    #[test]
    fn is_test() {
        assert!(is())
    }
}
<|endoftext|>


<commit_before>//extern crate json;

pub struct PhoneticParser {
    //patterns: json::Object,
    vowel: String,
    consonant: String,
    numbers: String,
    case_sensitive: String,
}

impl PhoneticParser {
    fn is_vowel(&self, string: &str) -> bool {
        self.vowel.contains(string)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>implement fix_string() function<commit_after>extern crate json;

pub struct PhoneticParser {
    patterns: json::JsonValue,
    vowel: String,
    consonant: String,
    numbers: String,
    case_sensitive: String,
}

impl PhoneticParser {
    fn fix_string(&self, string: String) -> String {
        let mut fixed = String::new();
        for character in string.chars() {
            if self.is_case_sensitive(character) {
                fixed.push(character);
            } else {
                fixed.push_str(&character.to_lowercase().to_string());
            }
        }
        fixed
    }

    fn is_vowel(&self, string: char) -> bool {
        self.vowel.contains(string)
    }

    fn is_consonant(&self, string: char) -> bool {
        self.consonant.contains(string)
    }

    fn is_case_sensitive(&self, character: char) -> bool {
        self.case_sensitive.contains(&character.to_lowercase().to_string())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>