<commit_before>use std::marker::PhantomData;
use std::ptr;

// We should use {u32,u64}::BYTES when they are stable;
const U32_BYTES: usize = 4;
const U64_BYTES: usize = 8;

macro_rules! number_stream(
    ($name:ident, $number_type:ty, $bytes_in_type:expr) => (
#[derive(Debug,Copy,Clone)]
pub struct $name<'a> {
    start: *const $number_type,
    end: *const $number_type,
    marker: PhantomData<&'a ()>
}

impl<'a> $name<'a> {
    fn new(bytes: &'a [u8]) -> ($name<'a>, &'a [u8]) {
        $name::with_stride(bytes, 1)
    }

    // Stride is a grouping of sequential numbers
    //
    // 0 1 2 3 4 5 6 7
    // -------------      We have 7 bytes
    // --- --- --- X      Each number takes 2 bytes
    // --- --- XXX X      With a stride of 2
    //
    // Only four bytes will be consumed, the rest returned
    fn with_stride(bytes: &'a [u8], stride: usize) -> ($name<'a>, &'a [u8]) {
        let n_numbers_in_bytes = bytes.len() / $bytes_in_type;
        let n_strides_in_numbers = n_numbers_in_bytes / stride;
        let total_numbers = n_strides_in_numbers * stride;

        let (mine, theirs) = bytes.split_at(total_numbers * $bytes_in_type);

        let start = mine.as_ptr() as *const $number_type;
        let end = unsafe { start.offset(total_numbers as isize) };

        let me = $name {
            start: start,
            end: end,
            marker: PhantomData,
        };

        (me, theirs)
    }
}

impl<'a> Iterator for $name<'a> {
    type Item = $number_type;

    fn next(&mut self) -> Option<$number_type> {
        if self.start >= self.end { return None }

        let v: $number_type = unsafe { ptr::read(self.start) };

        self.start = unsafe { self.start.offset(1) };
        Some(v)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let cnt = self.count();
        (cnt, Some(cnt))
    }

    fn count(self) -> usize() {
        let total_bytes = self.end as usize - self.start as usize;
        total_bytes / $bytes_in_type
    }
}
));

number_stream!(U32FromBytes, u32, U32_BYTES);
number_stream!(U64FromBytes, u64, U64_BYTES);

/// Converts a slice of bytes into an iterator of numbers.
///
/// The data is always treated as little endian. Only complete ranges
/// of bytes are parsed as the number, any left-over bytes are returned.
// FIXME: Probably doesn't work on big endian machines.
pub trait NumberStreams {
    /// Reads u32s from the bytes
    fn u32_stream(&self) -> (U32FromBytes, &[u8]);
    /// Reads u32s from the bytes, there will always be a multiple of `stride` numbers
    fn u32_stream_with_stride(&self, stride: usize) -> (U32FromBytes, &[u8]);
    /// Reads u64s from the bytes
    fn u64_stream(&self) -> (U64FromBytes, &[u8]);
    /// Reads u64s from the bytes, there will always be a multiple of `stride` numbers
    fn u64_stream_with_stride(&self, stride: usize) -> (U64FromBytes, &[u8]);
}

impl<'a> NumberStreams for [u8] {
    fn u32_stream(&self) -> (U32FromBytes, &[u8]) {
        U32FromBytes::new(self)
    }
    fn u32_stream_with_stride(&self, stride: usize) -> (U32FromBytes, &[u8]) {
        U32FromBytes::with_stride(self, stride)
    }
    fn u64_stream(&self) -> (U64FromBytes, &[u8]) {
        U64FromBytes::new(self)
    }
    fn u64_stream_with_stride(&self, stride: usize) -> (U64FromBytes, &[u8]) {
        U64FromBytes::with_stride(self, stride)
    }
}

#[cfg(test)]
mod test {
    use ::std::slice;
    use super::{U32_BYTES,U64_BYTES};
    use super::NumberStreams;

    fn u32_slice_as_u8(values: &[u32]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U32_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u32_from_bytes() {
        let orig_values: &[u32] = &[0,1];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u32_from_bytes_with_leftovers() {
        let orig_values: &[u32] = &[0,1];
        let mut as_u8: Vec<_> = u32_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = as_u8.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    #[test]
    fn can_read_u32_from_bytes_with_a_stride() {
        let orig_values: &[u32] = &[0,1,2];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u32_stream_with_stride(2);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..2]);

        let (iter, rest) = rest.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[2..]);
        assert!(rest.is_empty());
    }

    fn u64_slice_as_u8(values: &[u64]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U64_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u64_from_bytes() {
        let orig_values: &[u64] = &[0,1];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u64_from_bytes_with_leftovers() {
        let orig_values: &[u64] = &[0,1];
        let mut as_u8: Vec<_> = u64_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = as_u8.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    #[test]
    fn can_read_u64_from_bytes_with_a_stride() {
        let orig_values: &[u64] = &[0,1,2];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u64_stream_with_stride(2);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..2]);

        let (iter, rest) = rest.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[2..]);
        assert!(rest.is_empty());
    }
}
<commit_msg>Remove misplaced parenthesis<commit_after>use std::marker::PhantomData;
use std::ptr;

// We should use {u32,u64}::BYTES when they are stable;
const U32_BYTES: usize = 4;
const U64_BYTES: usize = 8;

macro_rules! number_stream(
    ($name:ident, $number_type:ty, $bytes_in_type:expr) => (
#[derive(Debug,Copy,Clone)]
pub struct $name<'a> {
    start: *const $number_type,
    end: *const $number_type,
    marker: PhantomData<&'a ()>
}

impl<'a> $name<'a> {
    fn new(bytes: &'a [u8]) -> ($name<'a>, &'a [u8]) {
        $name::with_stride(bytes, 1)
    }

    // Stride is a grouping of sequential numbers
    //
    // 0 1 2 3 4 5 6 7
    // -------------      We have 7 bytes
    // --- --- --- X      Each number takes 2 bytes
    // --- --- XXX X      With a stride of 2
    //
    // Only four bytes will be consumed, the rest returned
    fn with_stride(bytes: &'a [u8], stride: usize) -> ($name<'a>, &'a [u8]) {
        let n_numbers_in_bytes = bytes.len() / $bytes_in_type;
        let n_strides_in_numbers = n_numbers_in_bytes / stride;
        let total_numbers = n_strides_in_numbers * stride;

        let (mine, theirs) = bytes.split_at(total_numbers * $bytes_in_type);

        let start = mine.as_ptr() as *const $number_type;
        let end = unsafe { start.offset(total_numbers as isize) };

        let me = $name {
            start: start,
            end: end,
            marker: PhantomData,
        };

        (me, theirs)
    }
}

impl<'a> Iterator for $name<'a> {
    type Item = $number_type;

    fn next(&mut self) -> Option<$number_type> {
        if self.start >= self.end { return None }

        let v: $number_type = unsafe { ptr::read(self.start) };

        self.start = unsafe { self.start.offset(1) };
        Some(v)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let cnt = self.count();
        (cnt, Some(cnt))
    }

    fn count(self) -> usize {
        let total_bytes = self.end as usize - self.start as usize;
        total_bytes / $bytes_in_type
    }
}
));

number_stream!(U32FromBytes, u32, U32_BYTES);
number_stream!(U64FromBytes, u64, U64_BYTES);

/// Converts a slice of bytes into an iterator of numbers.
///
/// The data is always treated as little endian. Only complete ranges
/// of bytes are parsed as the number, any left-over bytes are returned.
// FIXME: Probably doesn't work on big endian machines.
pub trait NumberStreams {
    /// Reads u32s from the bytes
    fn u32_stream(&self) -> (U32FromBytes, &[u8]);
    /// Reads u32s from the bytes, there will always be a multiple of `stride` numbers
    fn u32_stream_with_stride(&self, stride: usize) -> (U32FromBytes, &[u8]);
    /// Reads u64s from the bytes
    fn u64_stream(&self) -> (U64FromBytes, &[u8]);
    /// Reads u64s from the bytes, there will always be a multiple of `stride` numbers
    fn u64_stream_with_stride(&self, stride: usize) -> (U64FromBytes, &[u8]);
}

impl<'a> NumberStreams for [u8] {
    fn u32_stream(&self) -> (U32FromBytes, &[u8]) {
        U32FromBytes::new(self)
    }
    fn u32_stream_with_stride(&self, stride: usize) -> (U32FromBytes, &[u8]) {
        U32FromBytes::with_stride(self, stride)
    }
    fn u64_stream(&self) -> (U64FromBytes, &[u8]) {
        U64FromBytes::new(self)
    }
    fn u64_stream_with_stride(&self, stride: usize) -> (U64FromBytes, &[u8]) {
        U64FromBytes::with_stride(self, stride)
    }
}

#[cfg(test)]
mod test {
    use ::std::slice;
    use super::{U32_BYTES,U64_BYTES};
    use super::NumberStreams;

    fn u32_slice_as_u8(values: &[u32]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U32_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u32_from_bytes() {
        let orig_values: &[u32] = &[0,1];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u32_from_bytes_with_leftovers() {
        let orig_values: &[u32] = &[0,1];
        let mut as_u8: Vec<_> = u32_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = as_u8.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    #[test]
    fn can_read_u32_from_bytes_with_a_stride() {
        let orig_values: &[u32] = &[0,1,2];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u32_stream_with_stride(2);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..2]);

        let (iter, rest) = rest.u32_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[2..]);
        assert!(rest.is_empty());
    }

    fn u64_slice_as_u8(values: &[u64]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U64_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u64_from_bytes() {
        let orig_values: &[u64] = &[0,1];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u64_from_bytes_with_leftovers() {
        let orig_values: &[u64] = &[0,1];
        let mut as_u8: Vec<_> = u64_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = as_u8.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    #[test]
    fn can_read_u64_from_bytes_with_a_stride() {
        let orig_values: &[u64] = &[0,1,2];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = as_u8.u64_stream_with_stride(2);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..2]);

        let (iter, rest) = rest.u64_stream();
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[2..]);
        assert!(rest.is_empty());
    }
}
<|endoftext|>


<commit_before>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            ::std::mem::transmute(&self.pointer)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<::std::io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(::std::io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_GetLastError() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError").unwrap();
    }
}

#[test]
fn works_GetLastError0() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError\0").unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<commit_msg>Try calling functions in windows tests<commit_after>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            ::std::mem::transmute(&self.pointer)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<::std::io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(::std::io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_getlasterror() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}

#[test]
fn works_getlasterror0() {
    let lib = Library::new("kernel32.dll").unwrap();
    let gle: Symbol<unsafe extern "system" fn() -> winapi::DWORD> = unsafe {
        lib.get(b"GetLastError\0").unwrap()
    };
    unsafe {
        kernel32::SetLastError(42);
        assert_eq!(kernel32::GetLastError(), gle())
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Joe Neeman.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{Debug, Formatter, Error as FmtError};
use std::u32;

pub type TableStateIdx = u32;

/// A DFA program implemented as a lookup table.
#[derive(Clone)]
pub struct TableInsts<Ret> {
    /// The log (rounded up) of the number of different equivalence classes of bytes.
    // We could save a bit more memory by storing the actual number instead of the log, because
    // then `table` could have length num_classes x num_instructions. However, then we need to
    // multiply (instead of just shifting) to look up the next state, and that slows us down by
    // 10-20%.
    pub log_num_classes: u32,
    /// A vec of length 256 mapping from bytes to their class indices.
    pub byte_class: Vec<u8>,
    /// A `(1 << log_num_classes) x num_instructions`-long table.
    ///
    /// For a given input byte `b` in state `state`, we look up the next state using
    /// `table[state << log_num_classes + b]`.
    pub table: Vec<TableStateIdx>,
    /// If `accept[st]` is not `None` then `st` is accepting, and `accept[st]` is the data
    /// to return.
    pub accept: Vec<Option<Ret>>,
    /// Same as `accept`, but applies only at the end of the input.
    pub accept_at_eoi: Vec<Option<Ret>>,
    /// If true, this program should only be used at the start of the input.
    pub is_anchored: bool,
}

impl<Ret: Debug> Debug for TableInsts<Ret> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        try!(f.write_fmt(format_args!("TableInsts ({} log_classes, {} instructions):\n",
                                      self.log_num_classes,
                                      self.accept.len())));
        try!(f.write_str("Byte classes: "));
        try!(f.debug_map()
            .entries((0..256).map(|b| (b, self.byte_class[b])))
            .finish());

        let num_classes = 1 << self.log_num_classes;
        for idx in 0..self.accept.len() {
            try!(f.write_fmt(format_args!("State {}:\n", idx)));
            try!(f.debug_map()
                .entries((0usize..num_classes)
                    .map(|c| (c, self.table[(idx << self.log_num_classes) + c]))
                    .filter(|x| x.1 != u32::MAX))
                .finish());
            try!(f.write_str("\n"));
        }

        try!(f.write_str("Accept: "));
        for idx in 0..self.accept.len() {
            if let Some(ref ret) = self.accept[idx] {
                try!(f.write_fmt(format_args!("{} -> {:?}, ", idx, ret)));
            }
        }

        try!(f.write_str("Accept_at_eoi: "));
        for idx in 0..self.accept_at_eoi.len() {
            if let Some(ref ret) = self.accept_at_eoi[idx] {
                try!(f.write_fmt(format_args!("{} -> {:?}, ", idx, ret)));
            }
        }
        Ok(())
    }
}

impl<Ret: Copy + Debug> TableInsts<Ret> {
    pub fn is_anchored(&self) -> bool {
        self.is_anchored
    }

    fn next_state(&self, state: usize, input: u8) -> Option<usize> {
        let class = self.byte_class[input as usize];
        let next_state = self.table[(state << self.log_num_classes) + class as usize];
        if next_state != u32::MAX {
            Some(next_state as usize)
        } else {
            None
        }
    }

    pub fn num_states(&self) -> usize {
        self.accept.len()
    }

    pub fn shortest_match_from(&self, input: &[u8], pos: usize, state: usize)
    -> Result<(usize, Ret), usize> {
        let mut state = state as u32;

        for pos in pos..input.len() {
            if let Some(ret) = self.accept[state as usize] {
                return Ok((pos, ret));
            }

            // We've manually inlined next_state here, for better performance (measurably better
            // than using #[inline(always)]).
            let class = self.byte_class[input[pos] as usize];
            state = self.table[((state as usize) << self.log_num_classes) + class as usize];
            if state == u32::MAX {
                return Err(pos);
            }
        }

        if let Some(ret) = self.accept_at_eoi[state as usize] {
            Ok((input.len(), ret))
        } else {
            Err(input.len())
        }
    }

    pub fn longest_backward_match_from(&self, input: &[u8], pos: usize, mut state: usize)
    -> Option<(usize, Ret)> {
        let mut ret = None;
        for pos in (0..pos).rev() {
            if let Some(next_ret) = self.accept[state] {
                ret = Some((pos + 1, next_ret));
            }
            if let Some(next_state) = self.next_state(state, input[pos]) {
                state = next_state;
            } else {
                return ret;
            }
        }

        if let Some(end_ret) = self.accept_at_eoi[state] {
            Some((0, end_ret))
        } else {
            ret
        }
    }

    pub fn is_empty(&self) -> bool {
        self.num_states() == 0
    }
}

<commit_msg>Add a TODO.<commit_after>// Copyright 2015-2016 Joe Neeman.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{Debug, Formatter, Error as FmtError};
use std::u32;

pub type TableStateIdx = u32;

/// A DFA program implemented as a lookup table.
#[derive(Clone)]
pub struct TableInsts<Ret> {
    /// The log (rounded up) of the number of different equivalence classes of bytes.
    // We could save a bit more memory by storing the actual number instead of the log, because
    // then `table` could have length num_classes x num_instructions. However, then we need to
    // multiply (instead of just shifting) to look up the next state, and that slows us down by
    // 10-20%.
    //
    // TODO: we can probably save more memory by splitting classes into ASCII/non-ASCII. Often,
    // many states share the same non-ASCII transitions, so those tables can be merged.
    pub log_num_classes: u32,
    /// A vec of length 256 mapping from bytes to their class indices.
    pub byte_class: Vec<u8>,
    /// A `(1 << log_num_classes) x num_instructions`-long table.
    ///
    /// For a given input byte `b` in state `state`, we look up the next state using
    /// `table[state << log_num_classes + b]`.
    pub table: Vec<TableStateIdx>,
    /// If `accept[st]` is not `None` then `st` is accepting, and `accept[st]` is the data
    /// to return.
    pub accept: Vec<Option<Ret>>,
    /// Same as `accept`, but applies only at the end of the input.
    pub accept_at_eoi: Vec<Option<Ret>>,
    /// If true, this program should only be used at the start of the input.
    pub is_anchored: bool,
}

impl<Ret: Debug> Debug for TableInsts<Ret> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        try!(f.write_fmt(format_args!("TableInsts ({} log_classes, {} instructions):\n",
                                      self.log_num_classes,
                                      self.accept.len())));
        try!(f.write_str("Byte classes: "));
        try!(f.debug_map()
            .entries((0..256).map(|b| (b, self.byte_class[b])))
            .finish());

        let num_classes = 1 << self.log_num_classes;
        for idx in 0..self.accept.len() {
            try!(f.write_fmt(format_args!("State {}:\n", idx)));
            try!(f.debug_map()
                .entries((0usize..num_classes)
                    .map(|c| (c, self.table[(idx << self.log_num_classes) + c]))
                    .filter(|x| x.1 != u32::MAX))
                .finish());
            try!(f.write_str("\n"));
        }

        try!(f.write_str("Accept: "));
        for idx in 0..self.accept.len() {
            if let Some(ref ret) = self.accept[idx] {
                try!(f.write_fmt(format_args!("{} -> {:?}, ", idx, ret)));
            }
        }

        try!(f.write_str("Accept_at_eoi: "));
        for idx in 0..self.accept_at_eoi.len() {
            if let Some(ref ret) = self.accept_at_eoi[idx] {
                try!(f.write_fmt(format_args!("{} -> {:?}, ", idx, ret)));
            }
        }
        Ok(())
    }
}

impl<Ret: Copy + Debug> TableInsts<Ret> {
    pub fn is_anchored(&self) -> bool {
        self.is_anchored
    }

    fn next_state(&self, state: usize, input: u8) -> Option<usize> {
        let class = self.byte_class[input as usize];
        let next_state = self.table[(state << self.log_num_classes) + class as usize];
        if next_state != u32::MAX {
            Some(next_state as usize)
        } else {
            None
        }
    }

    pub fn num_states(&self) -> usize {
        self.accept.len()
    }

    pub fn shortest_match_from(&self, input: &[u8], pos: usize, state: usize)
    -> Result<(usize, Ret), usize> {
        let mut state = state as u32;

        for pos in pos..input.len() {
            if let Some(ret) = self.accept[state as usize] {
                return Ok((pos, ret));
            }

            // We've manually inlined next_state here, for better performance (measurably better
            // than using #[inline(always)]).
            let class = self.byte_class[input[pos] as usize];
            state = self.table[((state as usize) << self.log_num_classes) + class as usize];
            if state == u32::MAX {
                return Err(pos);
            }
        }

        if let Some(ret) = self.accept_at_eoi[state as usize] {
            Ok((input.len(), ret))
        } else {
            Err(input.len())
        }
    }

    pub fn longest_backward_match_from(&self, input: &[u8], pos: usize, mut state: usize)
    -> Option<(usize, Ret)> {
        let mut ret = None;
        for pos in (0..pos).rev() {
            if let Some(next_ret) = self.accept[state] {
                ret = Some((pos + 1, next_ret));
            }
            if let Some(next_state) = self.next_state(state, input[pos]) {
                state = next_state;
            } else {
                return ret;
            }
        }

        if let Some(end_ret) = self.accept_at_eoi[state] {
            Some((0, end_ret))
        } else {
            ret
        }
    }

    pub fn is_empty(&self) -> bool {
        self.num_states() == 0
    }
}

<|endoftext|>


<commit_before>extern crate regex;

use self::regex::Regex;

pub fn valid(num: &str) -> bool {
    let re = Regex::new("I").unwrap();
    re.is_match(num)
}

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

    #[test]
    fn i_is_valid() {
        assert!(valid("I"));
    }

    #[test]
    fn lower_i_is_invalid() {
        assert!(!valid("i"));
    }
}
<commit_msg>Get the anchors in the regex<commit_after>extern crate regex;

use self::regex::Regex;

pub fn valid(num: &str) -> bool {
    let re_text = concat!(
        "^",
        "I",
        "$");

    let re = Regex::new(re_text).unwrap();
    re.is_match(num)
}

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

    #[test]
    fn i_is_valid() {
        assert!(valid("I"));
    }

    #[test]
    fn lower_i_is_invalid() {
        assert!(!valid("i"));
    }

    #[test]
    fn prefixes_are_not_valid() {
        assert!(!valid(" I"));
    }

    #[test]
    fn suffixes_are_not_valid() {
        assert!(!valid("I "));
    }
}
<|endoftext|>


<commit_before>//!
//! A binding for the library `SDL2_image`
//!
//!
//! Note that you need to build with the
//! feature `image` for this module to be enabled,
//! like so:
//!
//! ```bash
//! $ cargo build --features "image"
//! ```
//!
//! If you want to use this with from inside your own
//! crate, you will need to add this in your Cargo.toml
//!
//! ```toml
//! [dependencies.sdl2]
//! version = ...
//! default-features = false
//! features = ["image"]
//! ```

use std::os::raw::{c_int, c_char};
use std::ffi::CString;
use std::path::Path;
use surface::Surface;
use render::{TextureCreator, Texture};
use rwops::RWops;
use version::Version;
use get_error;
use sys;
use sys::image;

/// InitFlags are passed to init() to control which subsystem
/// functionality to load.
bitflags! {
    pub struct InitFlag : u32 {
        const JPG  = image::IMG_InitFlags_IMG_INIT_JPG as u32;
        const PNG  = image::IMG_InitFlags_IMG_INIT_PNG as u32;
        const TIF  = image::IMG_InitFlags_IMG_INIT_TIF as u32;
        const WEBP = image::IMG_InitFlags_IMG_INIT_WEBP as u32;
    }
}

// This is used for error message for init
impl ::std::fmt::Display for InitFlag {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.contains(InitFlag::JPG) {
            f.write_str("INIT_JPG ")?;
        }
        if self.contains(InitFlag::PNG) {
            f.write_str("INIT_PNG ")?;
        }
        if self.contains(InitFlag::TIF) {
            f.write_str("INIT_TIF ")?;
        }
        if self.contains(InitFlag::WEBP) {
            f.write_str("INIT_WEBP ")?;
        }
        Ok(())
    }
}

/// Static method extensions for creating Surfaces
pub trait LoadSurface: Sized {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is Result<~Surface, String>.
    fn from_file<P: AsRef<Path>>(filename: P) -> Result<Self, String>;
    fn from_xpm_array(xpm: *const *const i8) -> Result<Self, String>;
}

/// Method extensions to Surface for saving to disk
pub trait SaveSurface {
    fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String>;
    fn save_rw(&self, dst: &mut RWops) -> Result<(), String>;
}

impl<'a> LoadSurface for Surface<'a> {
    fn from_file<P: AsRef<Path>>(filename: P) -> Result<Surface<'a>, String> {
        //! Loads an SDL Surface from a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let raw = image::IMG_Load(c_filename.as_ptr() as *const _);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw))
            }
        }
    }

    fn from_xpm_array(xpm: *const *const i8) -> Result<Surface<'a>, String> {
        //! Loads an SDL Surface from XPM data
        unsafe {
            let raw = image::IMG_ReadXPMFromArray(xpm as *mut *mut c_char);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw))
            }
        }
    }
}

impl<'a> SaveSurface for Surface<'a> {
    fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String> {
        //! Saves an SDL Surface to a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let status = image::IMG_SavePNG(self.raw(), c_filename.as_ptr() as *const _);
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }

    fn save_rw(&self, dst: &mut RWops) -> Result<(), String> {
        //! Saves an SDL Surface to an RWops
        unsafe {
            let status = image::IMG_SavePNG_RW(self.raw(), dst.raw(), 0);

            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

/// Method extensions for creating Textures from a `TextureCreator`
pub trait LoadTexture {
    fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String>;
}

impl<T> LoadTexture for TextureCreator<T> {
    fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String> {
        //! Loads an SDL Texture from a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let raw = image::IMG_LoadTexture(self.raw(), c_filename.as_ptr() as *const _);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(self.raw_create_texture(raw))
            }
        }
    }
}

/// Context manager for `sdl2_image` to manage quitting. Can't do much with it but
/// keep it alive while you are using it.
pub struct Sdl2ImageContext;

impl Drop for Sdl2ImageContext {
    fn drop(&mut self) {
        unsafe {
            image::IMG_Quit();
        }
    }
}

/// Initializes `SDL2_image` with `InitFlags`.
/// If not every flag is set it returns an error
pub fn init(flags: InitFlag) -> Result<Sdl2ImageContext, String> {
    let return_flags = unsafe {
        let used = image::IMG_Init(flags.bits() as c_int);
        InitFlag::from_bits_truncate(used as u32)
    };
    if !flags.intersects(return_flags) {
        // According to docs, error message text is not always set
        let mut error = get_error();
        if error.is_empty() {
            let un_init_flags = return_flags ^ flags;
            error = format!("Could not init: {}", un_init_flags);
            let _ = ::set_error(&error);
        }
        Err(error)
    } else {
        Ok(Sdl2ImageContext)
    }
}

/// Returns the version of the dynamically linked `SDL_image` library
pub fn get_linked_version() -> Version {
    unsafe { Version::from_ll(*image::IMG_Linked_Version()) }
}

#[inline]
fn to_surface_result<'a>(raw: *mut sys::SDL_Surface) -> Result<Surface<'a>, String> {
    if (raw as *mut ()).is_null() {
        Err(get_error())
    } else {
        unsafe { Ok(Surface::from_ll(raw)) }
    }
}

pub trait ImageRWops {
    /// load as a surface. except TGA
    fn load(&self) -> Result<Surface, String>;
    /// load as a surface. This can load all supported image formats.
    fn load_typed(&self, _type: &str) -> Result<Surface, String>;

    fn load_cur(&self) -> Result<Surface, String>;
    fn load_ico(&self) -> Result<Surface, String>;
    fn load_bmp(&self) -> Result<Surface, String>;
    fn load_pnm(&self) -> Result<Surface, String>;
    fn load_xpm(&self) -> Result<Surface, String>;
    fn load_xcf(&self) -> Result<Surface, String>;
    fn load_pcx(&self) -> Result<Surface, String>;
    fn load_gif(&self) -> Result<Surface, String>;
    fn load_jpg(&self) -> Result<Surface, String>;
    fn load_tif(&self) -> Result<Surface, String>;
    fn load_png(&self) -> Result<Surface, String>;
    fn load_tga(&self) -> Result<Surface, String>;
    fn load_lbm(&self) -> Result<Surface, String>;
    fn load_xv(&self) -> Result<Surface, String>;
    fn load_webp(&self) -> Result<Surface, String>;

    fn is_cur(&self) -> bool;
    fn is_ico(&self) -> bool;
    fn is_bmp(&self) -> bool;
    fn is_pnm(&self) -> bool;
    fn is_xpm(&self) -> bool;
    fn is_xcf(&self) -> bool;
    fn is_pcx(&self) -> bool;
    fn is_gif(&self) -> bool;
    fn is_jpg(&self) -> bool;
    fn is_tif(&self) -> bool;
    fn is_png(&self) -> bool;
    fn is_lbm(&self) -> bool;
    fn is_xv(&self) -> bool;
    fn is_webp(&self) -> bool;
}

impl<'a> ImageRWops for RWops<'a> {
    fn load(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_Load_RW(self.raw(), 0) };
        to_surface_result(raw)
    }
    fn load_typed(&self, _type: &str) -> Result<Surface, String> {
        let raw = unsafe {
            let c_type = CString::new(_type.as_bytes()).unwrap();
            image::IMG_LoadTyped_RW(self.raw(), 0, c_type.as_ptr() as *const _)
        };
        to_surface_result(raw)
    }

    fn load_cur(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadCUR_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_ico(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadICO_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_bmp(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadBMP_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pnm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPNM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xpm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXPM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xcf(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXCF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pcx(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPCX_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_gif(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadGIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_jpg(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadJPG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tif(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadTIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_png(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPNG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tga(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadTGA_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_lbm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadLBM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xv(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXV_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_webp(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadWEBP_RW(self.raw()) };
        to_surface_result(raw)
    }

    fn is_cur(&self) -> bool {
        unsafe { image::IMG_isCUR(self.raw()) == 1 }
    }
    fn is_ico(&self) -> bool {
        unsafe { image::IMG_isICO(self.raw()) == 1 }
    }
    fn is_bmp(&self) -> bool {
        unsafe { image::IMG_isBMP(self.raw()) == 1 }
    }
    fn is_pnm(&self) -> bool {
        unsafe { image::IMG_isPNM(self.raw()) == 1 }
    }
    fn is_xpm(&self) -> bool {
        unsafe { image::IMG_isXPM(self.raw()) == 1 }
    }
    fn is_xcf(&self) -> bool {
        unsafe { image::IMG_isXCF(self.raw()) == 1 }
    }
    fn is_pcx(&self) -> bool {
        unsafe { image::IMG_isPCX(self.raw()) == 1 }
    }
    fn is_gif(&self) -> bool {
        unsafe { image::IMG_isGIF(self.raw()) == 1 }
    }
    fn is_jpg(&self) -> bool {
        unsafe { image::IMG_isJPG(self.raw()) == 1 }
    }
    fn is_tif(&self) -> bool {
        unsafe { image::IMG_isTIF(self.raw()) == 1 }
    }
    fn is_png(&self) -> bool {
        unsafe { image::IMG_isPNG(self.raw()) == 1 }
    }
    fn is_lbm(&self) -> bool {
        unsafe { image::IMG_isLBM(self.raw()) == 1 }
    }
    fn is_xv(&self) -> bool {
        unsafe { image::IMG_isXV(self.raw()) == 1 }
    }
    fn is_webp(&self) -> bool {
        unsafe { image::IMG_isWEBP(self.raw()) == 1 }
    }
}
<commit_msg>Correctly place bitflags documentation<commit_after>//!
//! A binding for the library `SDL2_image`
//!
//!
//! Note that you need to build with the
//! feature `image` for this module to be enabled,
//! like so:
//!
//! ```bash
//! $ cargo build --features "image"
//! ```
//!
//! If you want to use this with from inside your own
//! crate, you will need to add this in your Cargo.toml
//!
//! ```toml
//! [dependencies.sdl2]
//! version = ...
//! default-features = false
//! features = ["image"]
//! ```

use std::os::raw::{c_int, c_char};
use std::ffi::CString;
use std::path::Path;
use surface::Surface;
use render::{TextureCreator, Texture};
use rwops::RWops;
use version::Version;
use get_error;
use sys;
use sys::image;

bitflags! {
    /// InitFlags are passed to init() to control which subsystem
    /// functionality to load.
    pub struct InitFlag : u32 {
        const JPG  = image::IMG_InitFlags_IMG_INIT_JPG as u32;
        const PNG  = image::IMG_InitFlags_IMG_INIT_PNG as u32;
        const TIF  = image::IMG_InitFlags_IMG_INIT_TIF as u32;
        const WEBP = image::IMG_InitFlags_IMG_INIT_WEBP as u32;
    }
}

// This is used for error message for init
impl ::std::fmt::Display for InitFlag {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        if self.contains(InitFlag::JPG) {
            f.write_str("INIT_JPG ")?;
        }
        if self.contains(InitFlag::PNG) {
            f.write_str("INIT_PNG ")?;
        }
        if self.contains(InitFlag::TIF) {
            f.write_str("INIT_TIF ")?;
        }
        if self.contains(InitFlag::WEBP) {
            f.write_str("INIT_WEBP ")?;
        }
        Ok(())
    }
}

/// Static method extensions for creating Surfaces
pub trait LoadSurface: Sized {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is Result<~Surface, String>.
    fn from_file<P: AsRef<Path>>(filename: P) -> Result<Self, String>;
    fn from_xpm_array(xpm: *const *const i8) -> Result<Self, String>;
}

/// Method extensions to Surface for saving to disk
pub trait SaveSurface {
    fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String>;
    fn save_rw(&self, dst: &mut RWops) -> Result<(), String>;
}

impl<'a> LoadSurface for Surface<'a> {
    fn from_file<P: AsRef<Path>>(filename: P) -> Result<Surface<'a>, String> {
        //! Loads an SDL Surface from a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let raw = image::IMG_Load(c_filename.as_ptr() as *const _);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw))
            }
        }
    }

    fn from_xpm_array(xpm: *const *const i8) -> Result<Surface<'a>, String> {
        //! Loads an SDL Surface from XPM data
        unsafe {
            let raw = image::IMG_ReadXPMFromArray(xpm as *mut *mut c_char);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(Surface::from_ll(raw))
            }
        }
    }
}

impl<'a> SaveSurface for Surface<'a> {
    fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String> {
        //! Saves an SDL Surface to a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let status = image::IMG_SavePNG(self.raw(), c_filename.as_ptr() as *const _);
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }

    fn save_rw(&self, dst: &mut RWops) -> Result<(), String> {
        //! Saves an SDL Surface to an RWops
        unsafe {
            let status = image::IMG_SavePNG_RW(self.raw(), dst.raw(), 0);

            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

/// Method extensions for creating Textures from a `TextureCreator`
pub trait LoadTexture {
    fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String>;
}

impl<T> LoadTexture for TextureCreator<T> {
    fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String> {
        //! Loads an SDL Texture from a file
        unsafe {
            let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
            let raw = image::IMG_LoadTexture(self.raw(), c_filename.as_ptr() as *const _);
            if (raw as *mut ()).is_null() {
                Err(get_error())
            } else {
                Ok(self.raw_create_texture(raw))
            }
        }
    }
}

/// Context manager for `sdl2_image` to manage quitting. Can't do much with it but
/// keep it alive while you are using it.
pub struct Sdl2ImageContext;

impl Drop for Sdl2ImageContext {
    fn drop(&mut self) {
        unsafe {
            image::IMG_Quit();
        }
    }
}

/// Initializes `SDL2_image` with `InitFlags`.
/// If not every flag is set it returns an error
pub fn init(flags: InitFlag) -> Result<Sdl2ImageContext, String> {
    let return_flags = unsafe {
        let used = image::IMG_Init(flags.bits() as c_int);
        InitFlag::from_bits_truncate(used as u32)
    };
    if !flags.intersects(return_flags) {
        // According to docs, error message text is not always set
        let mut error = get_error();
        if error.is_empty() {
            let un_init_flags = return_flags ^ flags;
            error = format!("Could not init: {}", un_init_flags);
            let _ = ::set_error(&error);
        }
        Err(error)
    } else {
        Ok(Sdl2ImageContext)
    }
}

/// Returns the version of the dynamically linked `SDL_image` library
pub fn get_linked_version() -> Version {
    unsafe { Version::from_ll(*image::IMG_Linked_Version()) }
}

#[inline]
fn to_surface_result<'a>(raw: *mut sys::SDL_Surface) -> Result<Surface<'a>, String> {
    if (raw as *mut ()).is_null() {
        Err(get_error())
    } else {
        unsafe { Ok(Surface::from_ll(raw)) }
    }
}

pub trait ImageRWops {
    /// load as a surface. except TGA
    fn load(&self) -> Result<Surface, String>;
    /// load as a surface. This can load all supported image formats.
    fn load_typed(&self, _type: &str) -> Result<Surface, String>;

    fn load_cur(&self) -> Result<Surface, String>;
    fn load_ico(&self) -> Result<Surface, String>;
    fn load_bmp(&self) -> Result<Surface, String>;
    fn load_pnm(&self) -> Result<Surface, String>;
    fn load_xpm(&self) -> Result<Surface, String>;
    fn load_xcf(&self) -> Result<Surface, String>;
    fn load_pcx(&self) -> Result<Surface, String>;
    fn load_gif(&self) -> Result<Surface, String>;
    fn load_jpg(&self) -> Result<Surface, String>;
    fn load_tif(&self) -> Result<Surface, String>;
    fn load_png(&self) -> Result<Surface, String>;
    fn load_tga(&self) -> Result<Surface, String>;
    fn load_lbm(&self) -> Result<Surface, String>;
    fn load_xv(&self) -> Result<Surface, String>;
    fn load_webp(&self) -> Result<Surface, String>;

    fn is_cur(&self) -> bool;
    fn is_ico(&self) -> bool;
    fn is_bmp(&self) -> bool;
    fn is_pnm(&self) -> bool;
    fn is_xpm(&self) -> bool;
    fn is_xcf(&self) -> bool;
    fn is_pcx(&self) -> bool;
    fn is_gif(&self) -> bool;
    fn is_jpg(&self) -> bool;
    fn is_tif(&self) -> bool;
    fn is_png(&self) -> bool;
    fn is_lbm(&self) -> bool;
    fn is_xv(&self) -> bool;
    fn is_webp(&self) -> bool;
}

impl<'a> ImageRWops for RWops<'a> {
    fn load(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_Load_RW(self.raw(), 0) };
        to_surface_result(raw)
    }
    fn load_typed(&self, _type: &str) -> Result<Surface, String> {
        let raw = unsafe {
            let c_type = CString::new(_type.as_bytes()).unwrap();
            image::IMG_LoadTyped_RW(self.raw(), 0, c_type.as_ptr() as *const _)
        };
        to_surface_result(raw)
    }

    fn load_cur(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadCUR_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_ico(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadICO_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_bmp(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadBMP_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pnm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPNM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xpm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXPM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xcf(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXCF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_pcx(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPCX_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_gif(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadGIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_jpg(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadJPG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tif(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadTIF_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_png(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadPNG_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_tga(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadTGA_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_lbm(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadLBM_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_xv(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadXV_RW(self.raw()) };
        to_surface_result(raw)
    }
    fn load_webp(&self) -> Result<Surface, String> {
        let raw = unsafe { image::IMG_LoadWEBP_RW(self.raw()) };
        to_surface_result(raw)
    }

    fn is_cur(&self) -> bool {
        unsafe { image::IMG_isCUR(self.raw()) == 1 }
    }
    fn is_ico(&self) -> bool {
        unsafe { image::IMG_isICO(self.raw()) == 1 }
    }
    fn is_bmp(&self) -> bool {
        unsafe { image::IMG_isBMP(self.raw()) == 1 }
    }
    fn is_pnm(&self) -> bool {
        unsafe { image::IMG_isPNM(self.raw()) == 1 }
    }
    fn is_xpm(&self) -> bool {
        unsafe { image::IMG_isXPM(self.raw()) == 1 }
    }
    fn is_xcf(&self) -> bool {
        unsafe { image::IMG_isXCF(self.raw()) == 1 }
    }
    fn is_pcx(&self) -> bool {
        unsafe { image::IMG_isPCX(self.raw()) == 1 }
    }
    fn is_gif(&self) -> bool {
        unsafe { image::IMG_isGIF(self.raw()) == 1 }
    }
    fn is_jpg(&self) -> bool {
        unsafe { image::IMG_isJPG(self.raw()) == 1 }
    }
    fn is_tif(&self) -> bool {
        unsafe { image::IMG_isTIF(self.raw()) == 1 }
    }
    fn is_png(&self) -> bool {
        unsafe { image::IMG_isPNG(self.raw()) == 1 }
    }
    fn is_lbm(&self) -> bool {
        unsafe { image::IMG_isLBM(self.raw()) == 1 }
    }
    fn is_xv(&self) -> bool {
        unsafe { image::IMG_isXV(self.raw()) == 1 }
    }
    fn is_webp(&self) -> bool {
        unsafe { image::IMG_isWEBP(self.raw()) == 1 }
    }
}
<|endoftext|>


<commit_before>extern crate filecheck;

use filecheck::{CheckerBuilder, NO_VARIABLES, Error as FcError};

fn e2s(e: FcError) -> String {
    e.to_string()
}

#[test]
fn empty() {
    let c = CheckerBuilder::new().finish();
    assert!(c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn no_directives() {
    let c = CheckerBuilder::new().text("nothing here").unwrap().finish();
    assert!(c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn no_matches() {
    let c = CheckerBuilder::new().text("regex: FOO=bar").unwrap().finish();
    assert!(!c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn simple() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        check: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "
        zero
        and a half
        two
        one
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn sameln() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        sameln: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn nextln() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        nextln: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "
        zero
        one two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn leading_nextln() {
    // A leading nextln directive should match from line 2.
    // This is somewhat arbitrary, but consistent with a preceeding 'check: $()' directive.
    let c = CheckerBuilder::new()
        .text("
        nextln: one
        nextln: two
        ")
        .unwrap()
        .finish();

    let t = "zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn leading_sameln() {
    // A leading sameln directive should match from line 1.
    let c = CheckerBuilder::new()
        .text("
        sameln: one
        sameln: two
        ")
        .unwrap()
        .finish();

    let t = "zero
        one two three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "zero one two three";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "zero one
        two three";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn not() {
    let c = CheckerBuilder::new()
        .text("
        check: one$()
        not: $()eat$()
        check: $()two
        ")
        .unwrap()
        .finish();

    let t = "onetwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one eat two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneeattwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneatwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn notnot() {
    let c = CheckerBuilder::new()
        .text("
        check: one$()
        not: $()eat$()
        not: half
        check: $()two
        ")
        .unwrap()
        .finish();

    let t = "onetwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one eat two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "one half two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneeattwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    // The `not: half` pattern only matches whole words, but the bracketing matches are considered
    // word boundaries, so it does match in this case.
    let t = "onehalftwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneatwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn unordered() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        unordered: two
        unordered: three
        check: four
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s), Ok(false));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn leading_unordered() {
    let c = CheckerBuilder::new()
        .text("
        unordered: two
        unordered: three
        check: four
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s), Ok(false));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn trailing_unordered() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        unordered: two
        unordered: three
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES).map_err(e2s), Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s), Ok(true));
}
<commit_msg>Run rustfmt on lib/filecheck/tests/basic.rs<commit_after>extern crate filecheck;

use filecheck::{CheckerBuilder, NO_VARIABLES, Error as FcError};

fn e2s(e: FcError) -> String {
    e.to_string()
}

#[test]
fn empty() {
    let c = CheckerBuilder::new().finish();
    assert!(c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn no_directives() {
    let c = CheckerBuilder::new().text("nothing here").unwrap().finish();
    assert!(c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn no_matches() {
    let c = CheckerBuilder::new()
        .text("regex: FOO=bar")
        .unwrap()
        .finish();
    assert!(!c.is_empty());

    // An empty checker matches anything.
    assert_eq!(c.check("", NO_VARIABLES).map_err(e2s), Ok(true));
    assert_eq!(c.check("hello", NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn simple() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        check: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "
        zero
        and a half
        two
        one
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn sameln() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        sameln: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn nextln() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        nextln: two
        ")
        .unwrap()
        .finish();

    let t = "
        zero
        one
        and a half
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "
        zero
        one two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "
        zero
        one
        two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn leading_nextln() {
    // A leading nextln directive should match from line 2.
    // This is somewhat arbitrary, but consistent with a preceeding 'check: $()' directive.
    let c = CheckerBuilder::new()
        .text("
        nextln: one
        nextln: two
        ")
        .unwrap()
        .finish();

    let t = "zero
        one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one
        two
        three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn leading_sameln() {
    // A leading sameln directive should match from line 1.
    let c = CheckerBuilder::new()
        .text("
        sameln: one
        sameln: two
        ")
        .unwrap()
        .finish();

    let t = "zero
        one two three
        ";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "zero one two three";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "zero one
        two three";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));
}

#[test]
fn not() {
    let c = CheckerBuilder::new()
        .text("
        check: one$()
        not: $()eat$()
        check: $()two
        ")
        .unwrap()
        .finish();

    let t = "onetwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one eat two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneeattwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneatwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn notnot() {
    let c = CheckerBuilder::new()
        .text("
        check: one$()
        not: $()eat$()
        not: half
        check: $()two
        ")
        .unwrap()
        .finish();

    let t = "onetwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));

    let t = "one eat two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "one half two";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneeattwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    // The `not: half` pattern only matches whole words, but the bracketing matches are considered
    // word boundaries, so it does match in this case.
    let t = "onehalftwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(false));

    let t = "oneatwo";
    assert_eq!(c.check(t, NO_VARIABLES).map_err(e2s), Ok(true));
}

#[test]
fn unordered() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        unordered: two
        unordered: three
        check: four
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s),
               Ok(false));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s),
               Ok(false));
}

#[test]
fn leading_unordered() {
    let c = CheckerBuilder::new()
        .text("
        unordered: two
        unordered: three
        check: four
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s),
               Ok(false));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s),
               Ok(false));
}

#[test]
fn trailing_unordered() {
    let c = CheckerBuilder::new()
        .text("
        check: one
        unordered: two
        unordered: three
        ")
        .unwrap()
        .finish();

    assert_eq!(c.check("one two three four", NO_VARIABLES).map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three two four", NO_VARIABLES).map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three four two four", NO_VARIABLES)
                   .map_err(e2s),
               Ok(true));

    assert_eq!(c.check("one two four three", NO_VARIABLES).map_err(e2s),
               Ok(true));
    assert_eq!(c.check("one three four two", NO_VARIABLES).map_err(e2s),
               Ok(true));
}
<|endoftext|>


<commit_before>extern crate arguments;
extern crate flate2;
extern crate md5;

use flate2::read::GzDecoder;

use std::env;
use std::fs::{self, File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::Path;

macro_rules! ok(($result:expr) => ($result.unwrap()));

fn main() {
    let arguments = ok!(arguments::parse(env::args()));
    let input = ok!(arguments.get::<String>("input"));
    let split = arguments.get::<String>("split").unwrap_or(" ".to_string());
    let group = ok!(arguments.get::<usize>("group"));
    let select = ok!(arguments.get::<String>("select")).split(&split)
                                                       .map(|i| ok!(i.parse::<usize>()))
                                                       .collect::<Vec<_>>();
    let output = ok!(arguments.get::<String>("output"));
    let output = Path::new(&output);
    let mut input = ok!(File::open(input));
    let mut decoder = ok!(GzDecoder::new(&mut input));
    let reader = BufReader::new(&mut decoder);
    for line in reader.lines() {
        let line = ok!(line);
        let chunks = line.split(&split).collect::<Vec<_>>();
        let digest = format!("{:x}", md5::compute(chunks[group].as_bytes()));
        let directory = output.join(&digest[..2]);
        ok!(fs::create_dir_all(&directory));
        let output = directory.join(chunks[group]).with_extension("csv");
        let mut output = ok!(OpenOptions::new().append(true).create(true).open(output));
        for (i, &j) in select.iter().enumerate() {
            if i > 0 {
                ok!(output.write_all(split.as_bytes()));
            }
            ok!(output.write_all(chunks[j].as_bytes()));
        }
        ok!(output.write_all("\n".as_bytes()));
    }
}
<commit_msg>Fix a bug in distribute<commit_after>extern crate arguments;
extern crate flate2;
extern crate md5;

use flate2::read::GzDecoder;

use std::env;
use std::fs::{self, File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::Path;

macro_rules! ok(($result:expr) => ($result.unwrap()));

fn main() {
    let arguments = ok!(arguments::parse(env::args()));
    let input = ok!(arguments.get::<String>("input"));
    let split = arguments.get::<String>("split").unwrap_or(",".to_string());
    let group = ok!(arguments.get::<usize>("group"));
    let select = ok!(arguments.get::<String>("select")).split(" ")
                                                       .map(|i| ok!(i.parse::<usize>()))
                                                       .collect::<Vec<_>>();
    let output = ok!(arguments.get::<String>("output"));
    let output = Path::new(&output);
    let mut input = ok!(File::open(input));
    let mut decoder = ok!(GzDecoder::new(&mut input));
    let reader = BufReader::new(&mut decoder);
    for line in reader.lines() {
        let line = ok!(line);
        let chunks = line.split(&split).collect::<Vec<_>>();
        let digest = format!("{:x}", md5::compute(chunks[group].as_bytes()));
        let directory = output.join(&digest[..2]);
        ok!(fs::create_dir_all(&directory));
        let output = directory.join(chunks[group]).with_extension("csv");
        let mut output = ok!(OpenOptions::new().append(true).create(true).open(output));
        for (i, &j) in select.iter().enumerate() {
            if i > 0 {
                ok!(output.write_all(split.as_bytes()));
            }
            ok!(output.write_all(chunks[j].as_bytes()));
        }
        ok!(output.write_all("\n".as_bytes()));
    }
}
<|endoftext|>


<commit_before>use filetime::{self, FileTime};
use lazy_static::lazy_static;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

static CARGO_INTEGRATION_TEST_DIR: &str = "cit";

lazy_static! {
    // TODO: Use `SyncOnceCell` when stable
    static ref GLOBAL_ROOT: Mutex<Option<PathBuf>> = Mutex::new(None);

    static ref TEST_ROOTS: Mutex<HashMap<String, PathBuf>> = Default::default();
}

/// This is used when running cargo is pre-CARGO_TARGET_TMPDIR
/// TODO: Remove when CARGO_TARGET_TMPDIR grows old enough.
fn global_root_legacy() -> PathBuf {
    let mut path = t!(env::current_exe());
    path.pop(); // chop off exe name
    path.pop(); // chop off "deps"
    path.push("tmp");
    path.mkdir_p();
    path
}

fn set_global_root(tmp_dir: Option<&'static str>) {
    let mut lock = GLOBAL_ROOT.lock().unwrap();
    if lock.is_none() {
        let mut root = match tmp_dir {
            Some(tmp_dir) => PathBuf::from(tmp_dir),
            None => global_root_legacy(),
        };

        root.push(CARGO_INTEGRATION_TEST_DIR);
        *lock = Some(root);
    }
}

pub fn global_root() -> PathBuf {
    let lock = GLOBAL_ROOT.lock().unwrap();
    match lock.as_ref() {
        Some(p) => p.clone(),
        None => unreachable!("GLOBAL_ROOT not set yet"),
    }
}

// We need to give each test a unique id. The test name could serve this
// purpose, but the `test` crate doesn't have a way to obtain the current test
// name.[*] Instead, we used the `cargo-test-macro` crate to automatically
// insert an init function for each test that sets the test name in a thread
// local variable.
//
// [*] It does set the thread name, but only when running concurrently. If not
// running concurrently, all tests are run on the main thread.
thread_local! {
    static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
}

pub struct TestIdGuard {
    _private: (),
}

pub fn init_root(tmp_dir: Option<&'static str>) -> TestIdGuard {
    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);

    let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
    TEST_ID.with(|n| *n.borrow_mut() = Some(id));

    let guard = TestIdGuard { _private: () };

    set_global_root(tmp_dir);
    let r = root();
    r.rm_rf();
    r.mkdir_p();

    guard
}

impl Drop for TestIdGuard {
    fn drop(&mut self) {
        TEST_ID.with(|n| *n.borrow_mut() = None);
    }
}

pub fn root() -> PathBuf {
    let id = TEST_ID.with(|n| {
        n.borrow().expect(
            "Tests must use the `#[cargo_test]` attribute in \
             order to be able to use the crate root.",
        )
    });

    let mut root = global_root();
    root.push(&format!("t{}", id));
    root
}

pub fn home() -> PathBuf {
    let mut path = root();
    path.push("home");
    path.mkdir_p();
    path
}

pub trait CargoPathExt {
    fn rm_rf(&self);
    fn mkdir_p(&self);

    fn move_into_the_past(&self) {
        self.move_in_time(|sec, nsec| (sec - 3600, nsec))
    }

    fn move_into_the_future(&self) {
        self.move_in_time(|sec, nsec| (sec + 3600, nsec))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32);
}

impl CargoPathExt for Path {
    fn rm_rf(&self) {
        let meta = match self.symlink_metadata() {
            Ok(meta) => meta,
            Err(e) => {
                if e.kind() == ErrorKind::NotFound {
                    return;
                }
                panic!("failed to remove {:?}, could not read: {:?}", self, e);
            }
        };
        // There is a race condition between fetching the metadata and
        // actually performing the removal, but we don't care all that much
        // for our tests.
        if meta.is_dir() {
            if let Err(e) = remove_dir_all::remove_dir_all(self) {
                panic!("failed to remove {:?}: {:?}", self, e)
            }
        } else if let Err(e) = fs::remove_file(self) {
            panic!("failed to remove {:?}: {:?}", self, e)
        }
    }

    fn mkdir_p(&self) {
        fs::create_dir_all(self)
            .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32),
    {
        if self.is_file() {
            time_travel(self, &travel_amount);
        } else {
            recurse(self, &self.join("target"), &travel_amount);
        }

        fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            if p.is_file() {
                time_travel(p, travel_amount)
            } else if !p.starts_with(bad) {
                for f in t!(fs::read_dir(p)) {
                    let f = t!(f).path();
                    recurse(&f, bad, travel_amount);
                }
            }
        }

        fn time_travel<F>(path: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            let stat = t!(path.symlink_metadata());

            let mtime = FileTime::from_last_modification_time(&stat);

            let (sec, nsec) = travel_amount(mtime.unix_seconds(), mtime.nanoseconds());
            let newtime = FileTime::from_unix_time(sec, nsec);

            // Sadly change_file_times has a failure mode where a readonly file
            // cannot have its times changed on windows.
            do_op(path, "set file times", |path| {
                filetime::set_file_times(path, newtime, newtime)
            });
        }
    }
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));

            // Unix also requires the parent to not be readonly for example when
            // removing files
            let parent = path.parent().unwrap();
            let mut p = t!(parent.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(parent, p));

            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}

/// Get the filename for a library.
///
/// `kind` should be one of: "lib", "rlib", "staticlib", "dylib", "proc-macro"
///
/// For example, dynamic library named "foo" would return:
/// - macOS: "libfoo.dylib"
/// - Windows: "foo.dll"
/// - Unix: "libfoo.so"
pub fn get_lib_filename(name: &str, kind: &str) -> String {
    let prefix = get_lib_prefix(kind);
    let extension = get_lib_extension(kind);
    format!("{}{}.{}", prefix, name, extension)
}

pub fn get_lib_prefix(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "lib",
        "staticlib" | "dylib" | "proc-macro" => {
            if cfg!(windows) {
                ""
            } else {
                "lib"
            }
        }
        _ => unreachable!(),
    }
}

pub fn get_lib_extension(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "rlib",
        "staticlib" => {
            if cfg!(windows) {
                "lib"
            } else {
                "a"
            }
        }
        "dylib" | "proc-macro" => {
            if cfg!(windows) {
                "dll"
            } else if cfg!(target_os = "macos") {
                "dylib"
            } else {
                "so"
            }
        }
        _ => unreachable!(),
    }
}

/// Returns the sysroot as queried from rustc.
pub fn sysroot() -> String {
    let output = Command::new("rustc")
        .arg("--print=sysroot")
        .output()
        .expect("rustc to run");
    assert!(output.status.success());
    let sysroot = String::from_utf8(output.stdout).unwrap();
    sysroot.trim().to_string()
}

/// Returns true if names such as aux.* are allowed.
///
/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved`
/// for a list). More recent versions of Windows have relaxed this restriction. This test
/// determines whether we are running in a mode that allows Windows reserved names.
#[cfg(windows)]
pub fn windows_reserved_names_are_allowed() -> bool {
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;
    use std::ptr;
    use winapi::um::fileapi::GetFullPathNameW;

    let test_file_name: Vec<_> = OsStr::new("aux.rs").encode_wide().collect();

    let buffer_length =
        unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) };

    if buffer_length == 0 {
        // This means the call failed, so we'll conservatively assume reserved names are not allowed.
        return false;
    }

    let mut buffer = vec![0u16; buffer_length as usize];

    let result = unsafe {
        GetFullPathNameW(
            test_file_name.as_ptr(),
            buffer_length,
            buffer.as_mut_ptr(),
            ptr::null_mut(),
        )
    };

    if result == 0 {
        // Once again, conservatively assume reserved names are not allowed if the
        // GetFullPathNameW call failed.
        return false;
    }

    // Under the old rules, a file name like aux.rs would get converted into \\.\aux, so
    // we detect this case by checking if the string starts with \\.\
    //
    // Otherwise, the filename will be something like C:\Users\Foo\Documents\aux.rs
    let prefix: Vec<_> = OsStr::new("\\\\.\\").encode_wide().collect();
    if buffer.starts_with(&prefix) {
        false
    } else {
        true
    }
}
<commit_msg>Use old Windows path handling on CI<commit_after>use filetime::{self, FileTime};
use lazy_static::lazy_static;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

static CARGO_INTEGRATION_TEST_DIR: &str = "cit";

lazy_static! {
    // TODO: Use `SyncOnceCell` when stable
    static ref GLOBAL_ROOT: Mutex<Option<PathBuf>> = Mutex::new(None);

    static ref TEST_ROOTS: Mutex<HashMap<String, PathBuf>> = Default::default();
}

/// This is used when running cargo is pre-CARGO_TARGET_TMPDIR
/// TODO: Remove when CARGO_TARGET_TMPDIR grows old enough.
fn global_root_legacy() -> PathBuf {
    let mut path = t!(env::current_exe());
    path.pop(); // chop off exe name
    path.pop(); // chop off "deps"
    path.push("tmp");
    path.mkdir_p();
    path
}

fn set_global_root(tmp_dir: Option<&'static str>) {
    let mut lock = GLOBAL_ROOT.lock().unwrap();
    if lock.is_none() {
        let mut root = match tmp_dir {
            Some(tmp_dir) => PathBuf::from(tmp_dir),
            None => global_root_legacy(),
        };

        root.push(CARGO_INTEGRATION_TEST_DIR);
        *lock = Some(root);
    }
}

pub fn global_root() -> PathBuf {
    let lock = GLOBAL_ROOT.lock().unwrap();
    match lock.as_ref() {
        Some(p) => p.clone(),
        None => unreachable!("GLOBAL_ROOT not set yet"),
    }
}

// We need to give each test a unique id. The test name could serve this
// purpose, but the `test` crate doesn't have a way to obtain the current test
// name.[*] Instead, we used the `cargo-test-macro` crate to automatically
// insert an init function for each test that sets the test name in a thread
// local variable.
//
// [*] It does set the thread name, but only when running concurrently. If not
// running concurrently, all tests are run on the main thread.
thread_local! {
    static TEST_ID: RefCell<Option<usize>> = RefCell::new(None);
}

pub struct TestIdGuard {
    _private: (),
}

pub fn init_root(tmp_dir: Option<&'static str>) -> TestIdGuard {
    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);

    let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
    TEST_ID.with(|n| *n.borrow_mut() = Some(id));

    let guard = TestIdGuard { _private: () };

    set_global_root(tmp_dir);
    let r = root();
    r.rm_rf();
    r.mkdir_p();

    guard
}

impl Drop for TestIdGuard {
    fn drop(&mut self) {
        TEST_ID.with(|n| *n.borrow_mut() = None);
    }
}

pub fn root() -> PathBuf {
    let id = TEST_ID.with(|n| {
        n.borrow().expect(
            "Tests must use the `#[cargo_test]` attribute in \
             order to be able to use the crate root.",
        )
    });

    let mut root = global_root();
    root.push(&format!("t{}", id));
    root
}

pub fn home() -> PathBuf {
    let mut path = root();
    path.push("home");
    path.mkdir_p();
    path
}

pub trait CargoPathExt {
    fn rm_rf(&self);
    fn mkdir_p(&self);

    fn move_into_the_past(&self) {
        self.move_in_time(|sec, nsec| (sec - 3600, nsec))
    }

    fn move_into_the_future(&self) {
        self.move_in_time(|sec, nsec| (sec + 3600, nsec))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32);
}

impl CargoPathExt for Path {
    fn rm_rf(&self) {
        let meta = match self.symlink_metadata() {
            Ok(meta) => meta,
            Err(e) => {
                if e.kind() == ErrorKind::NotFound {
                    return;
                }
                panic!("failed to remove {:?}, could not read: {:?}", self, e);
            }
        };
        // There is a race condition between fetching the metadata and
        // actually performing the removal, but we don't care all that much
        // for our tests.
        if meta.is_dir() {
            if let Err(e) = remove_dir_all::remove_dir_all(self) {
                panic!("failed to remove {:?}: {:?}", self, e)
            }
        } else if let Err(e) = fs::remove_file(self) {
            panic!("failed to remove {:?}: {:?}", self, e)
        }
    }

    fn mkdir_p(&self) {
        fs::create_dir_all(self)
            .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
    }

    fn move_in_time<F>(&self, travel_amount: F)
    where
        F: Fn(i64, u32) -> (i64, u32),
    {
        if self.is_file() {
            time_travel(self, &travel_amount);
        } else {
            recurse(self, &self.join("target"), &travel_amount);
        }

        fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            if p.is_file() {
                time_travel(p, travel_amount)
            } else if !p.starts_with(bad) {
                for f in t!(fs::read_dir(p)) {
                    let f = t!(f).path();
                    recurse(&f, bad, travel_amount);
                }
            }
        }

        fn time_travel<F>(path: &Path, travel_amount: &F)
        where
            F: Fn(i64, u32) -> (i64, u32),
        {
            let stat = t!(path.symlink_metadata());

            let mtime = FileTime::from_last_modification_time(&stat);

            let (sec, nsec) = travel_amount(mtime.unix_seconds(), mtime.nanoseconds());
            let newtime = FileTime::from_unix_time(sec, nsec);

            // Sadly change_file_times has a failure mode where a readonly file
            // cannot have its times changed on windows.
            do_op(path, "set file times", |path| {
                filetime::set_file_times(path, newtime, newtime)
            });
        }
    }
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));

            // Unix also requires the parent to not be readonly for example when
            // removing files
            let parent = path.parent().unwrap();
            let mut p = t!(parent.metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(parent, p));

            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}

/// Get the filename for a library.
///
/// `kind` should be one of: "lib", "rlib", "staticlib", "dylib", "proc-macro"
///
/// For example, dynamic library named "foo" would return:
/// - macOS: "libfoo.dylib"
/// - Windows: "foo.dll"
/// - Unix: "libfoo.so"
pub fn get_lib_filename(name: &str, kind: &str) -> String {
    let prefix = get_lib_prefix(kind);
    let extension = get_lib_extension(kind);
    format!("{}{}.{}", prefix, name, extension)
}

pub fn get_lib_prefix(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "lib",
        "staticlib" | "dylib" | "proc-macro" => {
            if cfg!(windows) {
                ""
            } else {
                "lib"
            }
        }
        _ => unreachable!(),
    }
}

pub fn get_lib_extension(kind: &str) -> &str {
    match kind {
        "lib" | "rlib" => "rlib",
        "staticlib" => {
            if cfg!(windows) {
                "lib"
            } else {
                "a"
            }
        }
        "dylib" | "proc-macro" => {
            if cfg!(windows) {
                "dll"
            } else if cfg!(target_os = "macos") {
                "dylib"
            } else {
                "so"
            }
        }
        _ => unreachable!(),
    }
}

/// Returns the sysroot as queried from rustc.
pub fn sysroot() -> String {
    let output = Command::new("rustc")
        .arg("--print=sysroot")
        .output()
        .expect("rustc to run");
    assert!(output.status.success());
    let sysroot = String::from_utf8(output.stdout).unwrap();
    sysroot.trim().to_string()
}

/// Returns true if names such as aux.* are allowed.
///
/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved`
/// for a list). More recent versions of Windows have relaxed this restriction. This test
/// determines whether we are running in a mode that allows Windows reserved names.
#[cfg(windows)]
pub fn windows_reserved_names_are_allowed() -> bool {
    use cargo_util::is_ci;

    // Ensure tests still run in CI until we need to migrate.
    if is_ci() {
        return false;
    }

    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;
    use std::ptr;
    use winapi::um::fileapi::GetFullPathNameW;

    let test_file_name: Vec<_> = OsStr::new("aux.rs").encode_wide().collect();

    let buffer_length =
        unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) };

    if buffer_length == 0 {
        // This means the call failed, so we'll conservatively assume reserved names are not allowed.
        return false;
    }

    let mut buffer = vec![0u16; buffer_length as usize];

    let result = unsafe {
        GetFullPathNameW(
            test_file_name.as_ptr(),
            buffer_length,
            buffer.as_mut_ptr(),
            ptr::null_mut(),
        )
    };

    if result == 0 {
        // Once again, conservatively assume reserved names are not allowed if the
        // GetFullPathNameW call failed.
        return false;
    }

    // Under the old rules, a file name like aux.rs would get converted into \\.\aux, so
    // we detect this case by checking if the string starts with \\.\
    //
    // Otherwise, the filename will be something like C:\Users\Foo\Documents\aux.rs
    let prefix: Vec<_> = OsStr::new("\\\\.\\").encode_wide().collect();
    if buffer.starts_with(&prefix) {
        false
    } else {
        true
    }
}
<|endoftext|>