<commit_before>use std::ffi::CStr;
use std::ptr;
use kernel32::{GlobalAlloc, GlobalLock, GlobalUnlock};
use user32::{CloseClipboard, EmptyClipboard, GetClipboardData, OpenClipboard, SetClipboardData};
use winapi::minwindef::{FALSE, HGLOBAL, UINT};
use {Clipboard, Item, Result};

bitflags! {
    pub flags GlobalAllocFlags: UINT {
        const GHND = GMEM_MOVEABLE | GMEM_ZEROINIT,
        const GMEM_FIXED = 0x0000,
        const GMEM_MOVEABLE = 0x0002,
        const GMEM_ZEROINIT = 0x0040,
        const GPTR = GMEM_FIXED | GMEM_ZEROINIT
    }
}

#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ClipboardFormats {
    CF_BITMAP = 0x0002,
    CF_DIB = 0x0008,
    CF_DIBV5 = 0x0011,
    CF_DIF = 0x0005,
    CF_DSPBITMAP = 0x0082,
    CF_DSPENHMETAFILE = 0x008E,
    CF_DSPMETAFILEPICT = 0x0083,
    CF_DSPTEXT = 0x0081,
    CF_ENHMETAFILE = 0x0E,
    CF_GDIOBJFIRST = 0x0300,
    CF_GDIOBJLAST = 0x03FF,
    CF_HDROP = 0x000F,
    CF_LOCALE = 0x0010,
    CF_METAFILEPICT = 0x0003,
    CF_OEMTEXT = 0x0007,
    CF_OWNERDISPLAY = 0x0080,
    CF_PALETTE = 0x0009,
    CF_PENDATA = 0x000A,
    CF_PRIVATEFIRST = 0x0200,
    CF_PRIVATELAST = 0x02FF,
    CF_RIFF = 0x000B,
    CF_SYLK = 0x0004,
    CF_TEXT = 0x0001,
    CF_TIFF = 0x0006,
    CF_UNICODETEXT = 0x000C,
    CF_WAVE = 0x000D
}

pub trait ClipboardExt: Clipboard { }

#[derive(Debug)]
pub struct WindowsClipboard {
    _priv: ()
}

struct ClipboardGuard;
impl Default for ClipboardGuard {
    fn default() -> Self {
        let result = OpenClipboard(ptr::null_mut());
        assert!(result != FALSE);
        ClipboardGuard
    }
}

impl Drop for ClipboardGuard {
    fn drop(&mut self) {
        CloseClipboard();
    }
}

struct GlobalLockGuard {
    data: HANDLE,
    ptr: *mut u8
}

impl GlobalLockGuard {
    fn new(data: HANDLE) -> Self {
        assert!(data != ptr::null_mut());
        let ptr = GlobalLock(data) as *mut u8;
        assert!(ptr != ptr::null_mut());
        GlobalLockGuard {
            data: data,
            ptr: ptr
        }
    }

    fn get(&self) -> *mut u8 {
        self.ptr
    }
}

impl Drop for GlobalLockGuard {
    fn drop(&mut self) {
        GlobalUnlock(self.data);
        self.ptr = ptr::null_mut();
    }
}

impl Clipboard for WindowsClipboard {
    fn get() -> Result<Self, Box<Error + Send + Sync>> {
        Ok(WindowsClipboard {
            _priv: ()
        })
    }

    fn copy(&mut self, item: &Item) -> Result<(), Box<Error + Send + Sync>> {
        unsafe {
            let text = match *item {
                Item::Text(ref t) => t,
                _ => return Ok(())
            };
            let _guard = ClipboardGuard::default();

            let clip_buf = GlobalLockHandle::new(GlobalAlloc(GMEM_MOVEABLE, text.len()));
            ptr::copy_nonoverlapping(text.as_ptr(), clip_buf.get(), text.len());

            let empty_result = EmptyClipboard();
            assert!(empty_result != FALSE);
            SetClipboardData(ClipboardFormats::CF_UNICODETEXT as UINT, clip_buf);
            Ok(())
        }
    }

    fn copy_items(&mut self, items: &[Item]) -> Result<()> {
        unimplemented!();
    }

    fn get_paste_text(&self) -> Result<&str, Box<Error + Send + Sync>> {
        use std::slice;
        unsafe {
            let _guard = ClipboardGuard::default();
            let clip_buf = GlobalLockGuard::new(GetClipboardData(CF_UNICODETEXT));

            Ok(CStr::from_ptr(clip_buf.get()).to_str().unwrap_or(""))
        }
    }

    fn get_items(&self) -> &[Item] {
        unimplemented!();
    }
}

impl ClipboardExt for WindowsClipboard { }
<commit_msg>Move some `assert!` to `assert_ne!`<commit_after>use std::ffi::CStr;
use std::ptr;
use kernel32::{GlobalAlloc, GlobalLock, GlobalUnlock};
use user32::{CloseClipboard, EmptyClipboard, GetClipboardData, OpenClipboard, SetClipboardData};
use winapi::minwindef::{FALSE, HGLOBAL, UINT};
use {Clipboard, Item, Result};

bitflags! {
    pub flags GlobalAllocFlags: UINT {
        const GHND = GMEM_MOVEABLE | GMEM_ZEROINIT,
        const GMEM_FIXED = 0x0000,
        const GMEM_MOVEABLE = 0x0002,
        const GMEM_ZEROINIT = 0x0040,
        const GPTR = GMEM_FIXED | GMEM_ZEROINIT
    }
}

#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ClipboardFormats {
    CF_BITMAP = 0x0002,
    CF_DIB = 0x0008,
    CF_DIBV5 = 0x0011,
    CF_DIF = 0x0005,
    CF_DSPBITMAP = 0x0082,
    CF_DSPENHMETAFILE = 0x008E,
    CF_DSPMETAFILEPICT = 0x0083,
    CF_DSPTEXT = 0x0081,
    CF_ENHMETAFILE = 0x0E,
    CF_GDIOBJFIRST = 0x0300,
    CF_GDIOBJLAST = 0x03FF,
    CF_HDROP = 0x000F,
    CF_LOCALE = 0x0010,
    CF_METAFILEPICT = 0x0003,
    CF_OEMTEXT = 0x0007,
    CF_OWNERDISPLAY = 0x0080,
    CF_PALETTE = 0x0009,
    CF_PENDATA = 0x000A,
    CF_PRIVATEFIRST = 0x0200,
    CF_PRIVATELAST = 0x02FF,
    CF_RIFF = 0x000B,
    CF_SYLK = 0x0004,
    CF_TEXT = 0x0001,
    CF_TIFF = 0x0006,
    CF_UNICODETEXT = 0x000C,
    CF_WAVE = 0x000D
}

pub trait ClipboardExt: Clipboard { }

#[derive(Debug)]
pub struct WindowsClipboard {
    _priv: ()
}

struct ClipboardGuard;
impl Default for ClipboardGuard {
    fn default() -> Self {
        let result = OpenClipboard(ptr::null_mut());
        assert_ne!(result, FALSE);
        ClipboardGuard
    }
}

impl Drop for ClipboardGuard {
    fn drop(&mut self) {
        CloseClipboard();
    }
}

struct GlobalLockGuard {
    data: HANDLE,
    ptr: *mut u8
}

impl GlobalLockGuard {
    fn new(data: HANDLE) -> Self {
        assert_ne!(data, ptr::null_mut());
        let ptr = GlobalLock(data) as *mut u8;
        assert_ne!(ptr, ptr::null_mut());
        GlobalLockGuard {
            data: data,
            ptr: ptr
        }
    }

    fn get(&self) -> *mut u8 {
        self.ptr
    }
}

impl Drop for GlobalLockGuard {
    fn drop(&mut self) {
        GlobalUnlock(self.data);
        self.ptr = ptr::null_mut();
    }
}

impl Clipboard for WindowsClipboard {
    fn get() -> Result<Self, Box<Error + Send + Sync>> {
        Ok(WindowsClipboard {
            _priv: ()
        })
    }

    fn copy(&mut self, item: &Item) -> Result<(), Box<Error + Send + Sync>> {
        unsafe {
            let text = match *item {
                Item::Text(ref t) => t,
                _ => return Ok(())
            };
            let _guard = ClipboardGuard::default();

            let clip_buf = GlobalLockHandle::new(GlobalAlloc(GMEM_MOVEABLE, text.len()));
            ptr::copy_nonoverlapping(text.as_ptr(), clip_buf.get(), text.len());

            let empty_result = EmptyClipboard();
            assert_ne!(empty_result, FALSE);
            SetClipboardData(ClipboardFormats::CF_UNICODETEXT as UINT, clip_buf);
            Ok(())
        }
    }

    fn copy_items(&mut self, items: &[Item]) -> Result<()> {
        unimplemented!();
    }

    fn get_paste_text(&self) -> Result<&str, Box<Error + Send + Sync>> {
        use std::slice;
        unsafe {
            let _guard = ClipboardGuard::default();
            let clip_buf = GlobalLockGuard::new(GetClipboardData(CF_UNICODETEXT));

            Ok(CStr::from_ptr(clip_buf.get()).to_str().unwrap_or(""))
        }
    }

    fn get_items(&self) -> &[Item] {
        unimplemented!();
    }
}

impl ClipboardExt for WindowsClipboard { }
<|endoftext|>


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

use std::error::Error;
use std::fs::{self, Metadata};
use std::io::{stderr, Write};
use std::time::SystemTime;
use walkdir::DirEntry;

use super::{ComparableValue, Matcher, MatcherIO};

const SECONDS_PER_DAY: i64 = 60 * 60 * 24;

/// This matcher checks whether a file is newer than the file the matcher is initialized with.
pub struct NewerMatcher {
    given_modification_time: SystemTime,
}

impl NewerMatcher {
    pub fn new(path_to_file: &str) -> Result<NewerMatcher, Box<dyn Error>> {
        let metadata = fs::metadata(path_to_file)?;
        Ok(NewerMatcher {
            given_modification_time: metadata.modified()?,
        })
    }

    pub fn new_box(path_to_file: &str) -> Result<Box<dyn Matcher>, Box<dyn Error>> {
        Ok(Box::new(NewerMatcher::new(path_to_file)?))
    }

    /// Implementation of matches that returns a result, allowing use to use try!
    /// to deal with the errors.
    fn matches_impl(&self, file_info: &DirEntry) -> Result<bool, Box<dyn Error>> {
        let this_time = file_info.metadata()?.modified()?;
        // duration_since returns an Ok duration if this_time <= given_modification_time
        // and returns an Err (with a duration) otherwise. So if this_time >
        // given_modification_time (in which case we want to return true) then
        // duration_since will return an error.
        Ok(self
            .given_modification_time
            .duration_since(this_time)
            .is_err())
    }
}

impl Matcher for NewerMatcher {
    fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
        match self.matches_impl(file_info) {
            Err(e) => {
                writeln!(
                    &mut stderr(),
                    "Error getting modification time for {}: {}",
                    file_info.path().to_string_lossy(),
                    e
                )
                .unwrap();
                false
            }
            Ok(t) => t,
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub enum FileTimeType {
    Accessed,
    Created,
    Modified,
}

impl FileTimeType {
    fn get_file_time(self, metadata: Metadata) -> std::io::Result<SystemTime> {
        match self {
            FileTimeType::Accessed => metadata.accessed(),
            FileTimeType::Created => metadata.created(),
            FileTimeType::Modified => metadata.modified(),
        }
    }
}

/// This matcher checks whether a file's accessed|creation|modification time is
/// {less than | exactly | more than} N days old.
pub struct FileTimeMatcher {
    days: ComparableValue,
    file_time_type: FileTimeType,
}

impl Matcher for FileTimeMatcher {
    fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
        match self.matches_impl(file_info, matcher_io.now()) {
            Err(e) => {
                writeln!(
                    &mut stderr(),
                    "Error getting {:?} time for {}: {}",
                    self.file_time_type,
                    file_info.path().to_string_lossy(),
                    e
                )
                .unwrap();
                false
            }
            Ok(t) => t,
        }
    }
}

impl FileTimeMatcher {
    /// Implementation of matches that returns a result, allowing use to use try!
    /// to deal with the errors.
    fn matches_impl(&self, file_info: &DirEntry, now: SystemTime) -> Result<bool, Box<dyn Error>> {
        let this_time = self.file_time_type.get_file_time(file_info.metadata()?)?;
        let mut is_negative = false;
        // durations can't be negative. So duration_since returns a duration
        // wrapped in an error if now < this_time.
        let age = match now.duration_since(this_time) {
            Ok(duration) => duration,
            Err(e) => {
                is_negative = true;
                e.duration()
            }
        };
        let age_in_seconds: i64 = age.as_secs() as i64 * if is_negative { -1 } else { 1 };
        // rust division truncates towards zero (see
        // https://github.com/rust-lang/rust/blob/master/src/libcore/ops.rs#L580 )
        // so a simple age_in_seconds / SECONDS_PER_DAY gives the wrong answer
        // for negative ages: a file whose age is 1 second in the future needs to
        // count as -1 day old, not 0.
        let age_in_days = age_in_seconds / SECONDS_PER_DAY + if is_negative { -1 } else { 0 };
        Ok(self.days.imatches(age_in_days))
    }

    pub fn new(file_time_type: FileTimeType, days: ComparableValue) -> FileTimeMatcher {
        FileTimeMatcher {
            file_time_type,
            days,
        }
    }

    pub fn new_box(file_time_type: FileTimeType, days: ComparableValue) -> Box<dyn Matcher> {
        Box::new(FileTimeMatcher::new(file_time_type, days))
    }
}

#[cfg(test)]
mod tests {
    use std::fs::{File, OpenOptions};
    use std::io::{Read, Write};
    use std::thread;
    use std::time::{Duration, SystemTime};
    use tempdir::TempDir;
    use walkdir::DirEntry;

    use super::*;
    use crate::find::matchers::tests::get_dir_entry_for;
    use crate::find::matchers::{ComparableValue, Matcher};
    use crate::find::tests::FakeDependencies;

    #[test]
    fn newer_matcher() {
        // this file should already exist
        let old_file = get_dir_entry_for("test_data", "simple");

        let temp_dir = TempDir::new("newer_matcher").unwrap();
        let temp_dir_path = temp_dir.path().to_string_lossy();
        // this has just been created, so should be newer
        let new_file_name = "newFile";
        File::create(temp_dir.path().join(new_file_name)).expect("create temp file");

        let new_file = get_dir_entry_for(&temp_dir_path, &new_file_name);

        let matcher_for_new =
            NewerMatcher::new(&temp_dir.path().join(new_file_name).to_string_lossy()).unwrap();
        let matcher_for_old = NewerMatcher::new(&old_file.path().to_string_lossy()).unwrap();
        let deps = FakeDependencies::new();

        assert!(
            !matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()),
            "old_file shouldn't be newer than new_dir"
        );
        assert!(
            matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()),
            "new_file should be newer than old_dir"
        );
        assert!(
            !matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()),
            "old_file shouldn't be newer than itself"
        );
    }

    #[test]
    fn file_time_matcher() {
        // this file should already exist
        let file = get_dir_entry_for("test_data", "simple");

        let files_mtime = file.metadata().unwrap().modified().unwrap();

        let exactly_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(1));
        let more_than_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::MoreThan(1));
        let less_than_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::LessThan(1));
        let zero_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(0));

        // set "now" to 2 days after the file was modified.
        let mut deps = FakeDependencies::new();
        deps.set_time(files_mtime + Duration::new(2 * super::SECONDS_PER_DAY as u64, 0));
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match exactly 1 day old"
        );
        assert!(
            more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file should match more than 1 day old"
        );
        assert!(
            !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match exactly 0 days old"
        );

        // set "now" to 1 day after the file was modified.
        deps.set_time(files_mtime + Duration::new((3 * super::SECONDS_PER_DAY / 2) as u64, 0));
        assert!(
            exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file should match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match more than 1 day old"
        );
        assert!(
            !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match exactly 0 days old"
        );

        // set "now" to exactly the same time file was modified.
        deps.set_time(files_mtime);
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file shouldn't match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file shouldn't match more than 1 day old"
        );
        assert!(
            less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file should match less than 1 day old"
        );
        assert!(
            zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file should match exactly 0 days old"
        );

        // set "now" to a second before the file was modified (e.g. the file was
        // modified after find started running
        deps.set_time(files_mtime - Duration::new(1 as u64, 0));
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn'1 match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn't match more than 1 day old"
        );
        assert!(
            less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file should match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn't match exactly 0 days old"
        );
    }

    #[test]
    fn file_time_matcher_modified_created_accessed() {
        let temp_dir = TempDir::new("file_time_matcher_modified_created_accessed").unwrap();

        // No easy way to independently set file times. So create it - setting creation time
        let foo_path = temp_dir.path().join("foo");
        {
            File::create(&foo_path).expect("create temp file");
        }

        thread::sleep(Duration::from_secs(2));
        // read the file - potentially changing accessed time
        let mut buffer = [0; 10];
        {
            let mut f = File::open(&foo_path).expect("open temp file");
            let _ = f.read(&mut buffer);
        }

        thread::sleep(Duration::from_secs(2));
        // write to the file - changing the modification and potentially the accessed time
        let mut buffer = [0; 10];
        {
            let mut f = OpenOptions::new()
                .read(true)
                .write(true)
                .open(&foo_path)
                .expect("open temp file");
            let _ = f.write(&mut buffer);
        }

        thread::sleep(Duration::from_secs(2));
        // read the file agaion - potentially changing accessed time
        {
            let mut f = File::open(&foo_path).expect("open temp file");
            let _ = f.read(&mut buffer);
        }

        // OK our modification time and creation time should definitely be different
        // and depending on our platform and file system, our accessed time migh be
        // different too.

        let file_info = get_dir_entry_for(&temp_dir.path().to_string_lossy(), "foo");
        let metadata = file_info.metadata().unwrap();

        // metadata can return errors like StringError("creation time is not available on this platform currently")
        // so skip tests that won't pass due to shortcomings in std:;fs.
        if let Ok(accessed_time) = metadata.accessed() {
            test_matcher_for_file_time_type(&file_info, accessed_time, FileTimeType::Accessed);
        }

        if let Ok(creation_time) = metadata.created() {
            test_matcher_for_file_time_type(&file_info, creation_time, FileTimeType::Created);
        }

        if let Ok(modified_time) = metadata.modified() {
            test_matcher_for_file_time_type(&file_info, modified_time, FileTimeType::Modified);
        }
    }

    /// helper function for file_time_matcher_modified_created_accessed
    fn test_matcher_for_file_time_type(
        file_info: &DirEntry,
        file_time: SystemTime,
        file_time_type: FileTimeType,
    ) {
        {
            let matcher = FileTimeMatcher::new(file_time_type, ComparableValue::EqualTo(0));

            let mut deps = FakeDependencies::new();
            deps.set_time(file_time);
            assert!(
                matcher.matches(&file_info, &mut deps.new_matcher_io()),
                "{:?} time matcher should match",
                file_time_type
            );

            deps.set_time(file_time - Duration::from_secs(1));
            assert!(
                !matcher.matches(&file_info, &mut deps.new_matcher_io()),
                "{:?} time matcher shouldn't match a second before",
                file_time_type
            );
        }
    }
}
<commit_msg>Fix a clippy warning `struct constructor field order is inconsistent with struct definition field order`<commit_after>// Copyright 2017 Google Inc.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use std::error::Error;
use std::fs::{self, Metadata};
use std::io::{stderr, Write};
use std::time::SystemTime;
use walkdir::DirEntry;

use super::{ComparableValue, Matcher, MatcherIO};

const SECONDS_PER_DAY: i64 = 60 * 60 * 24;

/// This matcher checks whether a file is newer than the file the matcher is initialized with.
pub struct NewerMatcher {
    given_modification_time: SystemTime,
}

impl NewerMatcher {
    pub fn new(path_to_file: &str) -> Result<NewerMatcher, Box<dyn Error>> {
        let metadata = fs::metadata(path_to_file)?;
        Ok(NewerMatcher {
            given_modification_time: metadata.modified()?,
        })
    }

    pub fn new_box(path_to_file: &str) -> Result<Box<dyn Matcher>, Box<dyn Error>> {
        Ok(Box::new(NewerMatcher::new(path_to_file)?))
    }

    /// Implementation of matches that returns a result, allowing use to use try!
    /// to deal with the errors.
    fn matches_impl(&self, file_info: &DirEntry) -> Result<bool, Box<dyn Error>> {
        let this_time = file_info.metadata()?.modified()?;
        // duration_since returns an Ok duration if this_time <= given_modification_time
        // and returns an Err (with a duration) otherwise. So if this_time >
        // given_modification_time (in which case we want to return true) then
        // duration_since will return an error.
        Ok(self
            .given_modification_time
            .duration_since(this_time)
            .is_err())
    }
}

impl Matcher for NewerMatcher {
    fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
        match self.matches_impl(file_info) {
            Err(e) => {
                writeln!(
                    &mut stderr(),
                    "Error getting modification time for {}: {}",
                    file_info.path().to_string_lossy(),
                    e
                )
                .unwrap();
                false
            }
            Ok(t) => t,
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub enum FileTimeType {
    Accessed,
    Created,
    Modified,
}

impl FileTimeType {
    fn get_file_time(self, metadata: Metadata) -> std::io::Result<SystemTime> {
        match self {
            FileTimeType::Accessed => metadata.accessed(),
            FileTimeType::Created => metadata.created(),
            FileTimeType::Modified => metadata.modified(),
        }
    }
}

/// This matcher checks whether a file's accessed|creation|modification time is
/// {less than | exactly | more than} N days old.
pub struct FileTimeMatcher {
    days: ComparableValue,
    file_time_type: FileTimeType,
}

impl Matcher for FileTimeMatcher {
    fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
        match self.matches_impl(file_info, matcher_io.now()) {
            Err(e) => {
                writeln!(
                    &mut stderr(),
                    "Error getting {:?} time for {}: {}",
                    self.file_time_type,
                    file_info.path().to_string_lossy(),
                    e
                )
                .unwrap();
                false
            }
            Ok(t) => t,
        }
    }
}

impl FileTimeMatcher {
    /// Implementation of matches that returns a result, allowing use to use try!
    /// to deal with the errors.
    fn matches_impl(&self, file_info: &DirEntry, now: SystemTime) -> Result<bool, Box<dyn Error>> {
        let this_time = self.file_time_type.get_file_time(file_info.metadata()?)?;
        let mut is_negative = false;
        // durations can't be negative. So duration_since returns a duration
        // wrapped in an error if now < this_time.
        let age = match now.duration_since(this_time) {
            Ok(duration) => duration,
            Err(e) => {
                is_negative = true;
                e.duration()
            }
        };
        let age_in_seconds: i64 = age.as_secs() as i64 * if is_negative { -1 } else { 1 };
        // rust division truncates towards zero (see
        // https://github.com/rust-lang/rust/blob/master/src/libcore/ops.rs#L580 )
        // so a simple age_in_seconds / SECONDS_PER_DAY gives the wrong answer
        // for negative ages: a file whose age is 1 second in the future needs to
        // count as -1 day old, not 0.
        let age_in_days = age_in_seconds / SECONDS_PER_DAY + if is_negative { -1 } else { 0 };
        Ok(self.days.imatches(age_in_days))
    }

    pub fn new(file_time_type: FileTimeType, days: ComparableValue) -> FileTimeMatcher {
        FileTimeMatcher {
            days,
            file_time_type,
        }
    }

    pub fn new_box(file_time_type: FileTimeType, days: ComparableValue) -> Box<dyn Matcher> {
        Box::new(FileTimeMatcher::new(file_time_type, days))
    }
}

#[cfg(test)]
mod tests {
    use std::fs::{File, OpenOptions};
    use std::io::{Read, Write};
    use std::thread;
    use std::time::{Duration, SystemTime};
    use tempdir::TempDir;
    use walkdir::DirEntry;

    use super::*;
    use crate::find::matchers::tests::get_dir_entry_for;
    use crate::find::matchers::{ComparableValue, Matcher};
    use crate::find::tests::FakeDependencies;

    #[test]
    fn newer_matcher() {
        // this file should already exist
        let old_file = get_dir_entry_for("test_data", "simple");

        let temp_dir = TempDir::new("newer_matcher").unwrap();
        let temp_dir_path = temp_dir.path().to_string_lossy();
        // this has just been created, so should be newer
        let new_file_name = "newFile";
        File::create(temp_dir.path().join(new_file_name)).expect("create temp file");

        let new_file = get_dir_entry_for(&temp_dir_path, &new_file_name);

        let matcher_for_new =
            NewerMatcher::new(&temp_dir.path().join(new_file_name).to_string_lossy()).unwrap();
        let matcher_for_old = NewerMatcher::new(&old_file.path().to_string_lossy()).unwrap();
        let deps = FakeDependencies::new();

        assert!(
            !matcher_for_new.matches(&old_file, &mut deps.new_matcher_io()),
            "old_file shouldn't be newer than new_dir"
        );
        assert!(
            matcher_for_old.matches(&new_file, &mut deps.new_matcher_io()),
            "new_file should be newer than old_dir"
        );
        assert!(
            !matcher_for_old.matches(&old_file, &mut deps.new_matcher_io()),
            "old_file shouldn't be newer than itself"
        );
    }

    #[test]
    fn file_time_matcher() {
        // this file should already exist
        let file = get_dir_entry_for("test_data", "simple");

        let files_mtime = file.metadata().unwrap().modified().unwrap();

        let exactly_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(1));
        let more_than_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::MoreThan(1));
        let less_than_one_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::LessThan(1));
        let zero_day_matcher =
            FileTimeMatcher::new(FileTimeType::Modified, ComparableValue::EqualTo(0));

        // set "now" to 2 days after the file was modified.
        let mut deps = FakeDependencies::new();
        deps.set_time(files_mtime + Duration::new(2 * super::SECONDS_PER_DAY as u64, 0));
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match exactly 1 day old"
        );
        assert!(
            more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file should match more than 1 day old"
        );
        assert!(
            !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "2 day old file shouldn't match exactly 0 days old"
        );

        // set "now" to 1 day after the file was modified.
        deps.set_time(files_mtime + Duration::new((3 * super::SECONDS_PER_DAY / 2) as u64, 0));
        assert!(
            exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file should match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match more than 1 day old"
        );
        assert!(
            !less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "1 day old file shouldn't match exactly 0 days old"
        );

        // set "now" to exactly the same time file was modified.
        deps.set_time(files_mtime);
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file shouldn't match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file shouldn't match more than 1 day old"
        );
        assert!(
            less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file should match less than 1 day old"
        );
        assert!(
            zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "0 day old file should match exactly 0 days old"
        );

        // set "now" to a second before the file was modified (e.g. the file was
        // modified after find started running
        deps.set_time(files_mtime - Duration::new(1 as u64, 0));
        assert!(
            !exactly_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn'1 match exactly 1 day old"
        );
        assert!(
            !more_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn't match more than 1 day old"
        );
        assert!(
            less_than_one_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file should match less than 1 day old"
        );
        assert!(
            !zero_day_matcher.matches(&file, &mut deps.new_matcher_io()),
            "future-modified file shouldn't match exactly 0 days old"
        );
    }

    #[test]
    fn file_time_matcher_modified_created_accessed() {
        let temp_dir = TempDir::new("file_time_matcher_modified_created_accessed").unwrap();

        // No easy way to independently set file times. So create it - setting creation time
        let foo_path = temp_dir.path().join("foo");
        {
            File::create(&foo_path).expect("create temp file");
        }

        thread::sleep(Duration::from_secs(2));
        // read the file - potentially changing accessed time
        let mut buffer = [0; 10];
        {
            let mut f = File::open(&foo_path).expect("open temp file");
            let _ = f.read(&mut buffer);
        }

        thread::sleep(Duration::from_secs(2));
        // write to the file - changing the modification and potentially the accessed time
        let mut buffer = [0; 10];
        {
            let mut f = OpenOptions::new()
                .read(true)
                .write(true)
                .open(&foo_path)
                .expect("open temp file");
            let _ = f.write(&mut buffer);
        }

        thread::sleep(Duration::from_secs(2));
        // read the file agaion - potentially changing accessed time
        {
            let mut f = File::open(&foo_path).expect("open temp file");
            let _ = f.read(&mut buffer);
        }

        // OK our modification time and creation time should definitely be different
        // and depending on our platform and file system, our accessed time migh be
        // different too.

        let file_info = get_dir_entry_for(&temp_dir.path().to_string_lossy(), "foo");
        let metadata = file_info.metadata().unwrap();

        // metadata can return errors like StringError("creation time is not available on this platform currently")
        // so skip tests that won't pass due to shortcomings in std:;fs.
        if let Ok(accessed_time) = metadata.accessed() {
            test_matcher_for_file_time_type(&file_info, accessed_time, FileTimeType::Accessed);
        }

        if let Ok(creation_time) = metadata.created() {
            test_matcher_for_file_time_type(&file_info, creation_time, FileTimeType::Created);
        }

        if let Ok(modified_time) = metadata.modified() {
            test_matcher_for_file_time_type(&file_info, modified_time, FileTimeType::Modified);
        }
    }

    /// helper function for file_time_matcher_modified_created_accessed
    fn test_matcher_for_file_time_type(
        file_info: &DirEntry,
        file_time: SystemTime,
        file_time_type: FileTimeType,
    ) {
        {
            let matcher = FileTimeMatcher::new(file_time_type, ComparableValue::EqualTo(0));

            let mut deps = FakeDependencies::new();
            deps.set_time(file_time);
            assert!(
                matcher.matches(&file_info, &mut deps.new_matcher_io()),
                "{:?} time matcher should match",
                file_time_type
            );

            deps.set_time(file_time - Duration::from_secs(1));
            assert!(
                !matcher.matches(&file_info, &mut deps.new_matcher_io()),
                "{:?} time matcher shouldn't match a second before",
                file_time_type
            );
        }
    }
}
<|endoftext|>


<commit_before>fn all_factors(num: usize) -> Vec<usize> {
    let ceiling = (num as f64).sqrt() as usize;
    let mut factors = Vec::new();
    for curr in 1..num+1 {
        if num % curr == 0 {
            let div = num / curr;
            if div > curr {
                factors.push(curr);
                factors.push(div);
            } else if curr == div {
                factors.push(curr);
            } else {
                break;
            }
        }
        if curr > ceiling {
            break;
        }
    }
    factors.sort();
    factors
}

#[test]
fn test_factors() {
    assert_eq!(all_factors(1), vec!(1));
    assert_eq!(all_factors(2), vec!(1, 2));
    assert_eq!(all_factors(3), vec!(1, 3));
    assert_eq!(all_factors(4), vec!(1, 2, 4));
    assert_eq!(all_factors(5), vec!(1, 5));
    assert_eq!(all_factors(6), vec!(1, 2, 3, 6));
    assert_eq!(all_factors(7), vec!(1, 7));
    assert_eq!(all_factors(8), vec!(1, 2, 4, 8));
    assert_eq!(all_factors(9), vec!(1, 3, 9));
    assert_eq!(all_factors(10), vec!(1, 2, 5, 10));
}

fn count(num: usize) -> usize {
    all_factors(num).iter().fold(0, |acc, x| acc+x*10)
}

fn main() {
    let target = 33100000;
    let mut i = 1;
    let mut last = 0;
    loop {
        last = count(i);
        if i % 10000 == 0 {
            println!("{} = {}", i, last);
        }
        if last >= target {
            break;
        }
        i += 1;
    }
    println!("{} = {}", i, last);
}
<commit_msg>working 20 part 2<commit_after>fn all_factors(num: usize) -> Vec<usize> {
    let ceiling = (num as f64).sqrt() as usize;
    let mut factors = Vec::new();
    for curr in 1..num + 1 {
        if num % curr == 0 {
            let div = num / curr;
            if div > curr {
                factors.push(curr);
                factors.push(div);
            } else if curr == div {
                factors.push(curr);
            } else {
                break;
            }
        }
        if curr > ceiling {
            break;
        }
    }
    factors.sort();
    factors
}

#[test]
fn test_factors() {
    assert_eq!(all_factors(1), vec![1]);
    assert_eq!(all_factors(2), vec![1, 2]);
    assert_eq!(all_factors(3), vec![1, 3]);
    assert_eq!(all_factors(4), vec![1, 2, 4]);
    assert_eq!(all_factors(5), vec![1, 5]);
    assert_eq!(all_factors(6), vec![1, 2, 3, 6]);
    assert_eq!(all_factors(7), vec![1, 7]);
    assert_eq!(all_factors(8), vec![1, 2, 4, 8]);
    assert_eq!(all_factors(9), vec![1, 3, 9]);
    assert_eq!(all_factors(10), vec![1, 2, 5, 10]);
}

fn count_inf(num: usize) -> usize {
    all_factors(num).iter().fold(0, |acc, x| acc + x * 10)
}

const MAX_HOUSES: usize = 50;

fn count_max(num: usize) -> usize {
    all_factors(num).iter().filter(|x| *x * MAX_HOUSES >= num).fold(0, |acc, x| acc + x * 11)
}

fn main() {
    let target = 33100000;
    let mut i = 1;
    let mut last = 0;
    loop {
        last = count_inf(i);
        if last >= target {
            break;
        }
        i += 1;
    }
    println!("Part 1 {} = {}", i, last);

    let mut i = 1;
    let mut last = 0;
    loop {
        last = count_max(i);
        if last >= target {
            break;
        }
        i += 1;
    }
    println!("Part 2 {} = {}", i, last);
}
<|endoftext|>


<commit_before>extern crate lalrpop_util;
extern crate toml;

pub mod json;

#[test]
fn json() {
    use lalrpop_util::ParseError;

    assert!(json::parse_json(r#"{"circle-radius": {"stops": [1, 0]}}"#).is_ok());
    assert!(json::parse_json(r#"{"circle-radius": {"property": "temperature","stops": [[{"zoom": 0, "value": 0}, 0],[{"zoom": 20, "value": 5}, 20]]}}"#).is_ok());
    assert!(json::parse_json(r#"{"string": "\u12345\\\"\r"}"#).is_ok());
    assert_eq!(json::parse_json(r#"{zoom: 0}"#), Err(ParseError::InvalidToken { location: 1 }));
}

#[test]
fn value_to_toml() {
    assert_eq!(json::parse_value("-1"), Ok(toml::Value::Integer(-1)));
    assert_eq!(json::parse_value("3.5"), Ok(toml::Value::Float(3.5)));
    assert_eq!(json::parse_value("2.5e10"), Ok(toml::Value::Float(2.5e10)));
    assert_eq!(json::parse_value("2e-10"), Ok(toml::Value::Float(2e-10)));
    assert_eq!(json::parse_value("true"), Ok(toml::Value::Boolean(true)));
    assert_eq!(json::parse_value("false"), Ok(toml::Value::Boolean(false)));
}

#[test]
fn json_to_toml() {
    let json = r#"{"circle-radius": {"stops": [-1, 3.5, 2e10]}}"#;
    assert_eq!(format!("{:?}", json::parse_json(json)),
        r#"Ok(Table({"circle-radius": Table({"stops": Array([Integer(-1), Float(3.5), Float(20000000000)])})}))"#
    );

    let toml = r#"[circle-radius]
stops = [-1, 3.5, 20000000000.0]
"#;
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);

    let json = r#"[1,2,3]"#;
    let toml = "json = [1, 2, 3]\n";
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    let json = r##"
        {
          "id": "water",
          "source": "mapbox-streets",
          "source-layer": "water",
          "type": "fill",
          "paint": {
            "fill-color": "#00ffff"
          }
        }"##;
    let toml = r##"id = "water"
source = "mapbox-streets"
source-layer = "water"
type = "fill"

[paint]
fill-color = "#00ffff"
"##;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    //top-level array shall be embedded in a table
    let json = r##"[
        {
          "id": "water",
          "source": "mapbox-streets",
          "source-layer": "water",
          "type": "fill",
          "paint": {
            "fill-color": "#00ffff"
          }
        }
    ]"##;
    let toml = r##"[[json]]
id = "water"
source = "mapbox-streets"
source-layer = "water"
type = "fill"

[json.paint]
fill-color = "#00ffff"
"##;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    let json = r#"{"circle-radius": {"property": "temperature","stops": [[{"zoom": 0, "value": 0}, 0],[{"zoom": 20, "value": 5}, 20]]}}"#;
    let toml = r#"[circle-radius]
property = "temperature"
stops = [[value = 0
zoom = 0
, 0], [value = 5
zoom = 20
, 20]]
"#;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    // Resulting TOML is invalid:
    assert_eq!(toml::Parser::new(toml).parse(), None);
}

#[test]
fn json_file_to_toml() {
    use std::io::prelude::*;
    use std::fs::File;

    let mut file = File::open("testdata/bright-v9-cdn.json").unwrap();
    let mut json = String::new();
    let _ = file.read_to_string(&mut json);
    let toml = format!("{}", json::parse_json(&json).unwrap());
    println!("{}", toml);
    assert!(toml.contains(r##"[[layers]]
id = "background"
interactive = true
type = "background"

[layers.paint]
background-color = "#f8f4f0"

[[layers]]
filter = ["==", "class", "national_park"]
id = "landuse_overlay_national_park"
interactive = true
source = "mapbox"
source-layer = "landuse_overlay"
type = "fill"

[layers.metadata]
"mapbox:group" = "1444849388993.3071"

[layers.paint]
fill-color = "#d8e8c8"
fill-opacity = 0.75

[[layers]]
filter = ["==", "class", "park"]
id = "landuse_park"
interactive = true
source = "mapbox"
source-layer = "landuse"
type = "fill"
"##));

    assert!(toml.contains(r##"[[layers]]
filter = ["==", "scalerank", 1]
id = "country_label_1"
interactive = true
source = "mapbox"
source-layer = "country_label"
type = "symbol"

[layers.layout]
text-field = "{name_en}"
text-font = ["Open Sans Bold"]
text-max-width = 6.25
text-transform = "uppercase"

[layers.layout.text-size]
stops = [[1, 11], [4, 17]]

[layers.metadata]
"mapbox:group" = "1444849242106.713"

[layers.paint]
text-color = "#334"
text-halo-blur = 1
text-halo-color = "rgba(255,255,255,0.8)"
text-halo-width = 2
"##));
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>Minimal main()<commit_after>extern crate lalrpop_util;
extern crate toml;

pub mod json;
use std::io::prelude::*;
use std::fs::File;
use std::env;

fn json_file_to_toml(fname: &str) -> String {
    let mut file = File::open(fname).unwrap();
    let mut json = String::new();
    let _ = file.read_to_string(&mut json);
    format!("{}", json::parse_json(&json).unwrap())
}

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() != 2 {
println!("usage:
glstyleconv <jsonfilename>");
    } else {
        println!("{}", json_file_to_toml(&args[1]));
    }
}

#[test]
fn json() {
    use lalrpop_util::ParseError;

    assert!(json::parse_json(r#"{"circle-radius": {"stops": [1, 0]}}"#).is_ok());
    assert!(json::parse_json(r#"{"circle-radius": {"property": "temperature","stops": [[{"zoom": 0, "value": 0}, 0],[{"zoom": 20, "value": 5}, 20]]}}"#).is_ok());
    assert!(json::parse_json(r#"{"string": "\u12345\\\"\r"}"#).is_ok());
    assert_eq!(json::parse_json(r#"{zoom: 0}"#), Err(ParseError::InvalidToken { location: 1 }));
}

#[test]
fn value_to_toml() {
    assert_eq!(json::parse_value("-1"), Ok(toml::Value::Integer(-1)));
    assert_eq!(json::parse_value("3.5"), Ok(toml::Value::Float(3.5)));
    assert_eq!(json::parse_value("2.5e10"), Ok(toml::Value::Float(2.5e10)));
    assert_eq!(json::parse_value("2e-10"), Ok(toml::Value::Float(2e-10)));
    assert_eq!(json::parse_value("true"), Ok(toml::Value::Boolean(true)));
    assert_eq!(json::parse_value("false"), Ok(toml::Value::Boolean(false)));
}

#[test]
fn mbstudio_to_toml() {
    let json = r#"{"circle-radius": {"stops": [-1, 3.5, 2e10]}}"#;
    assert_eq!(format!("{:?}", json::parse_json(json)),
        r#"Ok(Table({"circle-radius": Table({"stops": Array([Integer(-1), Float(3.5), Float(20000000000)])})}))"#
    );

    let toml = r#"[circle-radius]
stops = [-1, 3.5, 20000000000.0]
"#;
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);

    let json = r#"[1,2,3]"#;
    let toml = "json = [1, 2, 3]\n";
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    let json = r##"
        {
          "id": "water",
          "source": "mapbox-streets",
          "source-layer": "water",
          "type": "fill",
          "paint": {
            "fill-color": "#00ffff"
          }
        }"##;
    let toml = r##"id = "water"
source = "mapbox-streets"
source-layer = "water"
type = "fill"

[paint]
fill-color = "#00ffff"
"##;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    //top-level array shall be embedded in a table
    let json = r##"[
        {
          "id": "water",
          "source": "mapbox-streets",
          "source-layer": "water",
          "type": "fill",
          "paint": {
            "fill-color": "#00ffff"
          }
        }
    ]"##;
    let toml = r##"[[json]]
id = "water"
source = "mapbox-streets"
source-layer = "water"
type = "fill"

[json.paint]
fill-color = "#00ffff"
"##;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    assert!(toml::Parser::new(toml).parse().is_some());

    let json = r#"{"circle-radius": {"property": "temperature","stops": [[{"zoom": 0, "value": 0}, 0],[{"zoom": 20, "value": 5}, 20]]}}"#;
    let toml = r#"[circle-radius]
property = "temperature"
stops = [[value = 0
zoom = 0
, 0], [value = 5
zoom = 20
, 20]]
"#;
    println!("{}", json::parse_json(json).unwrap());
    assert_eq!(format!("{}", json::parse_json(json).unwrap()), toml);
    // Resulting TOML is invalid:
    assert_eq!(toml::Parser::new(toml).parse(), None);
}

#[test]
fn file_to_toml() {
    let toml = json_file_to_toml("testdata/bright-v9-cdn.json");
    println!("{}", toml);
    assert!(toml.contains(r##"[[layers]]
id = "background"
interactive = true
type = "background"

[layers.paint]
background-color = "#f8f4f0"

[[layers]]
filter = ["==", "class", "national_park"]
id = "landuse_overlay_national_park"
interactive = true
source = "mapbox"
source-layer = "landuse_overlay"
type = "fill"

[layers.metadata]
"mapbox:group" = "1444849388993.3071"

[layers.paint]
fill-color = "#d8e8c8"
fill-opacity = 0.75

[[layers]]
filter = ["==", "class", "park"]
id = "landuse_park"
interactive = true
source = "mapbox"
source-layer = "landuse"
type = "fill"
"##));

    assert!(toml.contains(r##"[[layers]]
filter = ["==", "scalerank", 1]
id = "country_label_1"
interactive = true
source = "mapbox"
source-layer = "country_label"
type = "symbol"

[layers.layout]
text-field = "{name_en}"
text-font = ["Open Sans Bold"]
text-max-width = 6.25
text-transform = "uppercase"

[layers.layout.text-size]
stops = [[1, 11], [4, 17]]

[layers.metadata]
"mapbox:group" = "1444849242106.713"

[layers.paint]
text-color = "#334"
text-halo-blur = 1
text-halo-color = "rgba(255,255,255,0.8)"
text-halo-width = 2
"##));
}
<|endoftext|>


<commit_before>extern crate inkwell;

use self::inkwell::OptimizationLevel::Aggressive;
use self::inkwell::context::Context;
use self::inkwell::passes::{PassManagerBuilder, PassManager, PassRegistry};

#[test]
fn test_init_all_passes_for_module() {
    let context = Context::create();
    let module = context.create_module("my_module");
    let pass_manager = PassManager::create(());

    pass_manager.add_argument_promotion_pass();
    pass_manager.add_constant_merge_pass();
    #[cfg(any(feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0"))]
    pass_manager.add_merge_functions_pass();
    pass_manager.add_dead_arg_elimination_pass();
    pass_manager.add_function_attrs_pass();
    pass_manager.add_function_inlining_pass();
    pass_manager.add_always_inliner_pass();
    pass_manager.add_global_dce_pass();
    pass_manager.add_global_optimizer_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_ip_constant_propagation_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_internalize_pass(true);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    #[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    #[cfg(not(feature = "llvm3-6"))]
    pass_manager.add_bit_tracking_dce_pass();
    pass_manager.add_alignment_from_assumptions_pass();
    pass_manager.add_cfg_simplification_pass();
    pass_manager.add_dead_store_elimination_pass();
    pass_manager.add_scalarizer_pass();
    pass_manager.add_merged_load_store_motion_pass();
    pass_manager.add_gvn_pass();
    pass_manager.add_ind_var_simplify_pass();
    pass_manager.add_instruction_combining_pass();
    pass_manager.add_jump_threading_pass();
    pass_manager.add_licm_pass();
    pass_manager.add_loop_deletion_pass();
    pass_manager.add_loop_idiom_pass();
    pass_manager.add_loop_rotate_pass();
    pass_manager.add_loop_reroll_pass();
    pass_manager.add_loop_unroll_pass();
    pass_manager.add_loop_unswitch_pass();
    pass_manager.add_memcpy_optimize_pass();
    pass_manager.add_partially_inline_lib_calls_pass();
    pass_manager.add_lower_switch_pass();
    pass_manager.add_promote_memory_to_register_pass();
    pass_manager.add_reassociate_pass();
    pass_manager.add_sccp_pass();
    pass_manager.add_scalar_repl_aggregates_pass();
    pass_manager.add_scalar_repl_aggregates_pass_ssa();
    pass_manager.add_scalar_repl_aggregates_pass_with_threshold(1);
    pass_manager.add_simplify_lib_calls_pass();
    pass_manager.add_tail_call_elimination_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_constant_propagation_pass();
    #[cfg(feature = "llvm12-0")]
    pass_manager.add_instruction_simplify_pass();
    pass_manager.add_demote_memory_to_register_pass();
    pass_manager.add_verifier_pass();
    pass_manager.add_correlated_value_propagation_pass();
    pass_manager.add_early_cse_pass();
    pass_manager.add_lower_expect_intrinsic_pass();
    pass_manager.add_type_based_alias_analysis_pass();
    pass_manager.add_scoped_no_alias_aa_pass();
    pass_manager.add_basic_alias_analysis_pass();

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
    {
        pass_manager.add_early_cse_mem_ssa_pass();
        pass_manager.add_new_gvn_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    {
        pass_manager.add_aggressive_inst_combiner_pass();
        pass_manager.add_loop_unroll_and_jam_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))]
    {
        pass_manager.add_coroutine_early_pass();
        pass_manager.add_coroutine_split_pass();
        pass_manager.add_coroutine_elide_pass();
        pass_manager.add_coroutine_cleanup_pass();
    }

    pass_manager.run_on(&module);
}

#[test]
fn test_pass_manager_builder() {
    let pass_manager_builder = PassManagerBuilder::create();

    pass_manager_builder.set_optimization_level(Aggressive);
    pass_manager_builder.set_size_level(2);
    pass_manager_builder.set_inliner_with_threshold(42);
    pass_manager_builder.set_disable_unit_at_a_time(true);
    pass_manager_builder.set_disable_unroll_loops(true);
    pass_manager_builder.set_disable_simplify_lib_calls(true);

    let context = Context::create();
    let module = context.create_module("my_module");

    let fn_pass_manager = PassManager::create(&module);

    pass_manager_builder.populate_function_pass_manager(&fn_pass_manager);

    let void_type = context.void_type();
    let fn_type = void_type.fn_type(&[], false);
    let fn_value = module.add_function("my_fn", fn_type, None);
    let builder = context.create_builder();
    let entry = context.append_basic_block(fn_value, "entry");

    builder.position_at_end(entry);
    builder.build_return(None);

    #[cfg(not(feature = "llvm3-7"))]
    assert!(!fn_pass_manager.initialize());
    #[cfg(feature = "llvm3-7")]
    fn_pass_manager.initialize();

    // TODO: Test with actual changes? Would be true in that case
    // REVIEW: Segfaults in 4.0
    #[cfg(not(feature = "llvm4-0"))]
    assert!(!fn_pass_manager.run_on(&fn_value));

    assert!(!fn_pass_manager.finalize());

    let module_pass_manager = PassManager::create(());

    pass_manager_builder.populate_module_pass_manager(&module_pass_manager);

    let module2 = module.clone();

    // TODOC: In 3.6, 3.8, & 3.9 it returns false. Seems like a LLVM bug?
    #[cfg(not(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0")))]
    assert!(!module_pass_manager.run_on(&module));
    #[cfg(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0"))]
    assert!(module_pass_manager.run_on(&module));

    let lto_pass_manager = PassManager::create(());

    pass_manager_builder.populate_lto_pass_manager(&lto_pass_manager, false, false);

    assert!(lto_pass_manager.run_on(&module2));
}

#[test]
fn test_pass_registry() {
    let pass_registry = PassRegistry::get_global();

    pass_registry.initialize_core();
    pass_registry.initialize_transform_utils();
    pass_registry.initialize_scalar_opts();
    pass_registry.initialize_obj_carc_opts();
    pass_registry.initialize_vectorization();
    pass_registry.initialize_inst_combine();
    pass_registry.initialize_ipo();
    pass_registry.initialize_instrumentation();
    pass_registry.initialize_analysis();
    pass_registry.initialize_ipa();
    pass_registry.initialize_codegen();
    pass_registry.initialize_target();
    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    pass_registry.initialize_aggressive_inst_combiner();
}
<commit_msg>Update test config filter to enumerate excludes<commit_after>extern crate inkwell;

use self::inkwell::OptimizationLevel::Aggressive;
use self::inkwell::context::Context;
use self::inkwell::passes::{PassManagerBuilder, PassManager, PassRegistry};

#[test]
fn test_init_all_passes_for_module() {
    let context = Context::create();
    let module = context.create_module("my_module");
    let pass_manager = PassManager::create(());

    pass_manager.add_argument_promotion_pass();
    pass_manager.add_constant_merge_pass();
    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0",
                  feature = "llvm8-0", feature = "llvm9-0")))]
    pass_manager.add_merge_functions_pass();
    pass_manager.add_dead_arg_elimination_pass();
    pass_manager.add_function_attrs_pass();
    pass_manager.add_function_inlining_pass();
    pass_manager.add_always_inliner_pass();
    pass_manager.add_global_dce_pass();
    pass_manager.add_global_optimizer_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_ip_constant_propagation_pass();
    pass_manager.add_prune_eh_pass();
    pass_manager.add_ipsccp_pass();
    pass_manager.add_internalize_pass(true);
    pass_manager.add_strip_dead_prototypes_pass();
    pass_manager.add_strip_symbol_pass();
    #[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
    pass_manager.add_bb_vectorize_pass();
    pass_manager.add_loop_vectorize_pass();
    pass_manager.add_slp_vectorize_pass();
    pass_manager.add_aggressive_dce_pass();
    #[cfg(not(feature = "llvm3-6"))]
    pass_manager.add_bit_tracking_dce_pass();
    pass_manager.add_alignment_from_assumptions_pass();
    pass_manager.add_cfg_simplification_pass();
    pass_manager.add_dead_store_elimination_pass();
    pass_manager.add_scalarizer_pass();
    pass_manager.add_merged_load_store_motion_pass();
    pass_manager.add_gvn_pass();
    pass_manager.add_ind_var_simplify_pass();
    pass_manager.add_instruction_combining_pass();
    pass_manager.add_jump_threading_pass();
    pass_manager.add_licm_pass();
    pass_manager.add_loop_deletion_pass();
    pass_manager.add_loop_idiom_pass();
    pass_manager.add_loop_rotate_pass();
    pass_manager.add_loop_reroll_pass();
    pass_manager.add_loop_unroll_pass();
    pass_manager.add_loop_unswitch_pass();
    pass_manager.add_memcpy_optimize_pass();
    pass_manager.add_partially_inline_lib_calls_pass();
    pass_manager.add_lower_switch_pass();
    pass_manager.add_promote_memory_to_register_pass();
    pass_manager.add_reassociate_pass();
    pass_manager.add_sccp_pass();
    pass_manager.add_scalar_repl_aggregates_pass();
    pass_manager.add_scalar_repl_aggregates_pass_ssa();
    pass_manager.add_scalar_repl_aggregates_pass_with_threshold(1);
    pass_manager.add_simplify_lib_calls_pass();
    pass_manager.add_tail_call_elimination_pass();
    #[cfg(not(feature = "llvm12-0"))]
    pass_manager.add_constant_propagation_pass();
    #[cfg(feature = "llvm12-0")]
    pass_manager.add_instruction_simplify_pass();
    pass_manager.add_demote_memory_to_register_pass();
    pass_manager.add_verifier_pass();
    pass_manager.add_correlated_value_propagation_pass();
    pass_manager.add_early_cse_pass();
    pass_manager.add_lower_expect_intrinsic_pass();
    pass_manager.add_type_based_alias_analysis_pass();
    pass_manager.add_scoped_no_alias_aa_pass();
    pass_manager.add_basic_alias_analysis_pass();

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
    {
        pass_manager.add_early_cse_mem_ssa_pass();
        pass_manager.add_new_gvn_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    {
        pass_manager.add_aggressive_inst_combiner_pass();
        pass_manager.add_loop_unroll_and_jam_pass();
    }

    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0", feature = "llvm7-0")))]
    {
        pass_manager.add_coroutine_early_pass();
        pass_manager.add_coroutine_split_pass();
        pass_manager.add_coroutine_elide_pass();
        pass_manager.add_coroutine_cleanup_pass();
    }

    pass_manager.run_on(&module);
}

#[test]
fn test_pass_manager_builder() {
    let pass_manager_builder = PassManagerBuilder::create();

    pass_manager_builder.set_optimization_level(Aggressive);
    pass_manager_builder.set_size_level(2);
    pass_manager_builder.set_inliner_with_threshold(42);
    pass_manager_builder.set_disable_unit_at_a_time(true);
    pass_manager_builder.set_disable_unroll_loops(true);
    pass_manager_builder.set_disable_simplify_lib_calls(true);

    let context = Context::create();
    let module = context.create_module("my_module");

    let fn_pass_manager = PassManager::create(&module);

    pass_manager_builder.populate_function_pass_manager(&fn_pass_manager);

    let void_type = context.void_type();
    let fn_type = void_type.fn_type(&[], false);
    let fn_value = module.add_function("my_fn", fn_type, None);
    let builder = context.create_builder();
    let entry = context.append_basic_block(fn_value, "entry");

    builder.position_at_end(entry);
    builder.build_return(None);

    #[cfg(not(feature = "llvm3-7"))]
    assert!(!fn_pass_manager.initialize());
    #[cfg(feature = "llvm3-7")]
    fn_pass_manager.initialize();

    // TODO: Test with actual changes? Would be true in that case
    // REVIEW: Segfaults in 4.0
    #[cfg(not(feature = "llvm4-0"))]
    assert!(!fn_pass_manager.run_on(&fn_value));

    assert!(!fn_pass_manager.finalize());

    let module_pass_manager = PassManager::create(());

    pass_manager_builder.populate_module_pass_manager(&module_pass_manager);

    let module2 = module.clone();

    // TODOC: In 3.6, 3.8, & 3.9 it returns false. Seems like a LLVM bug?
    #[cfg(not(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0")))]
    assert!(!module_pass_manager.run_on(&module));
    #[cfg(any(feature = "llvm3-7", feature = "llvm6-0", feature = "llvm7-0", feature = "llvm8-0", feature = "llvm9-0", feature = "llvm10-0", feature = "llvm11-0", feature = "llvm12-0"))]
    assert!(module_pass_manager.run_on(&module));

    let lto_pass_manager = PassManager::create(());

    pass_manager_builder.populate_lto_pass_manager(&lto_pass_manager, false, false);

    assert!(lto_pass_manager.run_on(&module2));
}

#[test]
fn test_pass_registry() {
    let pass_registry = PassRegistry::get_global();

    pass_registry.initialize_core();
    pass_registry.initialize_transform_utils();
    pass_registry.initialize_scalar_opts();
    pass_registry.initialize_obj_carc_opts();
    pass_registry.initialize_vectorization();
    pass_registry.initialize_inst_combine();
    pass_registry.initialize_ipo();
    pass_registry.initialize_instrumentation();
    pass_registry.initialize_analysis();
    pass_registry.initialize_ipa();
    pass_registry.initialize_codegen();
    pass_registry.initialize_target();
    #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9",
                  feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
    pass_registry.initialize_aggressive_inst_combiner();
}
<|endoftext|>


<commit_before>extern crate cryt;
extern crate clap;

use clap::{App, Arg, SubCommand};
use std::io::{self, Read, Write};

use cryt::criteria;
use cryt::encoding;
use cryt::xor::{self, Xor};

fn main() {
    let matches = App::new("cryt")
                          .version("v0.1")
                          .author("Nicolas Schmidt <nfschmidt@gmail.com>")
                          .about("Cryptographic tools")
                          .subcommand(SubCommand::with_name("encode")
                                      .about("Encode input with the specified encoding")
                                      .subcommand(SubCommand::with_name("hex")
                                                  .about("Encode input in hex"))
                                      .subcommand(SubCommand::with_name("base64")
                                                  .about("Encode input in base64")))
                          .subcommand(SubCommand::with_name("decode")
                                      .about("Decode input with the specified encoding")
                                      .subcommand(SubCommand::with_name("hex")
                                                  .about("Decode input in hex"))
                                      .subcommand(SubCommand::with_name("base64")
                                                  .about("Decode input in base64")))
                          .subcommand(SubCommand::with_name("encrypt")
                                      .about("Encrypt input with the specified algorithm")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Encrypt using xor")
                                                  .arg(Arg::with_name("key")
                                                       .short("k")
                                                       .long("key")
                                                       .takes_value(true)
                                                       .required(true)
                                                       .help("xor key to be used"))))
                          .subcommand(SubCommand::with_name("decrypt")
                                      .about("Decrypt input with the specified algorithm")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Decrypt using xor")
                                                  .arg(Arg::with_name("key")
                                                       .short("k")
                                                       .long("key")
                                                       .takes_value(true)
                                                       .required(true)
                                                       .help("xor key to be used"))))
                          .subcommand(SubCommand::with_name("attack")
                                      .about("Attack the specified encryption algorithm to decrypt the input")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Attack xor encrypted input")
                                                  .arg(Arg::with_name("criterion")
                                                       .short("c")
                                                       .long("criterion")
                                                       .takes_value(true)
                                                       .possible_values(&["printable", "text"])
                                                       .help("criterion to be used for scoring the results"))
                                                  .arg(Arg::with_name("detailed")
                                                       .short("d")
                                                       .long("detailed")
                                                       .required(false)
                                                       .help("Print decrypted result, the key and the score for the selected criterion"))
                                                  .subcommand(SubCommand::with_name("keysize")
                                                              .about("Determine the keysize of a repeated xor encryption")
                                                              .arg(Arg::with_name("criterion")
                                                                   .help("Criterion to determine keysize")
                                                                   .short("c")
                                                                   .long("criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["hamming-distance"])
                                                                   .required(false))
                                                              .arg(Arg::with_name("min")
                                                                   .help("Minimum keysize to try")
                                                                   .long("min")
                                                                   .takes_value(true)
                                                                   .required(false))
                                                              .arg(Arg::with_name("max")
                                                                   .help("Maximum keysize to try")
                                                                   .long("max")
                                                                   .short("m")
                                                                   .takes_value(true)
                                                                   .required(true)))
                                                  .subcommand(SubCommand::with_name("repeated")
                                                              .about("Attack repeated xor encrypted input")
                                                              .arg(Arg::with_name("keysize-criterion")
                                                                   .help("Criterion to determine keysize")
                                                                   .short("k")
                                                                   .long("keysize-criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["hamming-distance"])
                                                                   .required(false))
                                                              .arg(Arg::with_name("xor-criterion")
                                                                   .short("x")
                                                                   .long("xor-criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["printable", "text"])
                                                                   .help("criterion to be used for scoring the intermediate block results"))
                                                              .arg(Arg::with_name("criterion")
                                                                   .short("c")
                                                                   .long("criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["printable", "text"])
                                                                   .help("criterion to be used for scoring the results for different keysizes"))
                                                              .arg(Arg::with_name("keysizes-try")
                                                                   .short("t")
                                                                   .long("keysizes-try")
                                                                   .takes_value(true)
                                                                   .required(false)
                                                                   .help("criterion to be used for scoring the results for different keysizes"))
                                                              .arg(Arg::with_name("min")
                                                                   .help("Minimum keysize to try")
                                                                   .long("min")
                                                                   .takes_value(true)
                                                                   .required(false))
                                                              .arg(Arg::with_name("max")
                                                                   .help("Maximum keysize to try")
                                                                   .long("max")
                                                                   .short("m")
                                                                   .takes_value(true)
                                                                   .required(true)))))
                          .get_matches();

    if let Some(matches) = matches.subcommand_matches("encode") {
        if let Some(_) = matches.subcommand_matches("base64") {
            run_encode_base64();
        } else if let Some(_) = matches.subcommand_matches("hex") {
            run_encode_hex();
        }
    } else if let Some(matches) = matches.subcommand_matches("decode") {
        if let Some(_) = matches.subcommand_matches("base64") {
            run_decode_base64();
        } else if let Some(_) = matches.subcommand_matches("hex") {
            run_decode_hex();
        }
    } else if let Some(matches) = matches.subcommand_matches("encrypt") {
        if let Some(matches) = matches.subcommand_matches("xor") {
            match matches.value_of("key") {
                Some(k) => {
                    run_encrypt_xor(k);
                }
                None => {
                    println!("Error: No key received!");
                }
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("decrypt") {
        if let Some(matches) = matches.subcommand_matches("xor") {
            match matches.value_of("key") {
                Some(k) => {
                    run_decrypt_xor(k);
                }
                None => {
                    println!("Error: No key received!");
                }
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("attack") {
        if let Some(xor_matches) = matches.subcommand_matches("xor") {
            if let Some(keysize_matches) = xor_matches.subcommand_matches("keysize") {
                let criterion = match keysize_matches.value_of("criterion") {
                    Some("hamming-distance") => xor::hamming_distance_criterion,
                    Some(_) => xor::hamming_distance_criterion,
                    None => xor::hamming_distance_criterion
                };

                let min = match keysize_matches.value_of("min") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                let max = match keysize_matches.value_of("max") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                run_attack_xor_keysize(criterion, min, max);
                return;
            } else if let Some(repeated_matches) = xor_matches.subcommand_matches("repeated") {
                let xor_criterion = match repeated_matches.value_of("xor-criterion") {
                    Some("printable") => criteria::printable_bytes,
                    Some("text") => criteria::text_bytes,
                    Some(_) => criteria::printable_bytes,
                    None => criteria::printable_bytes
                };

                let result_criterion = match xor_matches.value_of("criterion") {
                    Some("printable") => criteria::printable_bytes,
                    Some("text") => criteria::text_bytes,
                    Some(_) => criteria::text_bytes,
                    None => criteria::text_bytes
                };

                let keysize_criterion = match repeated_matches.value_of("keysize-criterion") {
                    Some("hamming-distance") => xor::hamming_distance_criterion,
                    Some(_) => xor::hamming_distance_criterion,
                    None => xor::hamming_distance_criterion
                };

                let keysize_try = match repeated_matches.value_of("keysizes-try") {
                    Some(v) => v.parse::<usize>().unwrap(),
                    None => 1
                };

                let min = match repeated_matches.value_of("min") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                let max = match repeated_matches.value_of("max") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                run_attack_xor_repeated(keysize_criterion, min, max, keysize_try, xor_criterion, result_criterion);
                return;
            }

            let criterion = match xor_matches.value_of("criterion") {
                Some("printable") => criteria::printable_bytes,
                Some("text") => criteria::text_bytes,
                Some(_) => criteria::printable_bytes,
                None => criteria::printable_bytes
            };

            if xor_matches.is_present("detailed") {
                run_attack_xor_detailed(criterion);
            } else {
                run_attack_xor(criterion);
            }
        }
    } else {
        run_interpreter();
    }
}

fn run_encode_base64() {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = encoding::base64_encode(&input);
    print!("{}", result);
}

fn run_encode_hex() {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = encoding::hex_encode(&input);
    print!("{}", result);
}

fn run_decode_base64() {
    let mut input = String::new();
    match io::stdin().read_to_string(&mut input) {
        Ok(_) => {
            let result = encoding::base64_decode(&input);
            io::stdout().write(&result).unwrap();
        }
        Err(error) => { println!("Error: {}", error); }
    }
}

fn run_decode_hex() {
    let mut input = String::new();
    match io::stdin().read_to_string(&mut input) {
        Ok(_) => {
            let result = encoding::hex_decode(&input);
            io::stdout().write(&result).unwrap();
        }
        Err(error) => { println!("Error: {}", error); }
    }
}

fn run_encrypt_xor(key: &str) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = Xor::new(key.as_bytes()).encrypt(&input);
    io::stdout().write(&result).unwrap();
}

fn run_decrypt_xor(key: &str) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = Xor::new(key.as_bytes()).decrypt(&input);
    io::stdout().write(&result).unwrap();
}

fn run_attack_xor(criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (_, _, decrypted) = xor::SingleByteAttack::new()
        .with_criterion(Box::new(criterion))
        .result(&input);

    io::stdout().write(&decrypted).unwrap();
}

fn run_attack_xor_detailed(criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (key, score, decrypted) = xor::SingleByteAttack::new()
        .with_criterion(Box::new(criterion))
        .result(&input);

    print!("Key: {}\tScore: {}\tResult: ", key, score);
    io::stdout().write(&decrypted).unwrap();
    println!("");
}

fn run_attack_xor_keysize(criterion: fn(&[u8], size: u32) -> f32, min: u32, max: u32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let results = xor::KeysizeAttack::new()
        .with_min_length(min)
        .with_max_length(max)
        .with_criterion(Box::new(criterion))
        .result(&input);

    for (size, score) in results {
        println!("Size: {}\tScore: {}", size, score);
    }
}

fn run_attack_xor_repeated(keysize_criterion: fn(&[u8], size: u32) -> f32, min: u32, max: u32, keysize_try: usize, xor_criterion: fn(&[u8]) -> f32, result_criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (key, decrypted) = xor::RepeatedAttack::new()
        .with_single_byte_attack(xor::SingleByteAttack::new()
                                 .with_criterion(Box::new(xor_criterion)))
        .with_keysize_attack(xor::KeysizeAttack::new()
                             .with_min_length(min)
                             .with_max_length(max)
                             .with_criterion(Box::new(keysize_criterion)))
        .with_result_criterion(Box::new(result_criterion))
        .with_keysizes_count(keysize_try)
        .result(&input);

    let mut stdout = io::stdout();
    print!("Key: ");
    stdout.write(&key).unwrap();
    print!("\nDecrypted:\n");
    stdout.write(&decrypted).unwrap();
}

fn run_interpreter() {
    println!("Interpreter");
}
<commit_msg>Defaulted repeated xor attack xor criterion to text<commit_after>extern crate cryt;
extern crate clap;

use clap::{App, Arg, SubCommand};
use std::io::{self, Read, Write};

use cryt::criteria;
use cryt::encoding;
use cryt::xor::{self, Xor};

fn main() {
    let matches = App::new("cryt")
                          .version("v0.1")
                          .author("Nicolas Schmidt <nfschmidt@gmail.com>")
                          .about("Cryptographic tools")
                          .subcommand(SubCommand::with_name("encode")
                                      .about("Encode input with the specified encoding")
                                      .subcommand(SubCommand::with_name("hex")
                                                  .about("Encode input in hex"))
                                      .subcommand(SubCommand::with_name("base64")
                                                  .about("Encode input in base64")))
                          .subcommand(SubCommand::with_name("decode")
                                      .about("Decode input with the specified encoding")
                                      .subcommand(SubCommand::with_name("hex")
                                                  .about("Decode input in hex"))
                                      .subcommand(SubCommand::with_name("base64")
                                                  .about("Decode input in base64")))
                          .subcommand(SubCommand::with_name("encrypt")
                                      .about("Encrypt input with the specified algorithm")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Encrypt using xor")
                                                  .arg(Arg::with_name("key")
                                                       .short("k")
                                                       .long("key")
                                                       .takes_value(true)
                                                       .required(true)
                                                       .help("xor key to be used"))))
                          .subcommand(SubCommand::with_name("decrypt")
                                      .about("Decrypt input with the specified algorithm")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Decrypt using xor")
                                                  .arg(Arg::with_name("key")
                                                       .short("k")
                                                       .long("key")
                                                       .takes_value(true)
                                                       .required(true)
                                                       .help("xor key to be used"))))
                          .subcommand(SubCommand::with_name("attack")
                                      .about("Attack the specified encryption algorithm to decrypt the input")
                                      .subcommand(SubCommand::with_name("xor")
                                                  .about("Attack xor encrypted input")
                                                  .arg(Arg::with_name("criterion")
                                                       .short("c")
                                                       .long("criterion")
                                                       .takes_value(true)
                                                       .possible_values(&["printable", "text"])
                                                       .help("criterion to be used for scoring the results"))
                                                  .arg(Arg::with_name("detailed")
                                                       .short("d")
                                                       .long("detailed")
                                                       .required(false)
                                                       .help("Print decrypted result, the key and the score for the selected criterion"))
                                                  .subcommand(SubCommand::with_name("keysize")
                                                              .about("Determine the keysize of a repeated xor encryption")
                                                              .arg(Arg::with_name("criterion")
                                                                   .help("Criterion to determine keysize")
                                                                   .short("c")
                                                                   .long("criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["hamming-distance"])
                                                                   .required(false))
                                                              .arg(Arg::with_name("min")
                                                                   .help("Minimum keysize to try")
                                                                   .long("min")
                                                                   .takes_value(true)
                                                                   .required(false))
                                                              .arg(Arg::with_name("max")
                                                                   .help("Maximum keysize to try")
                                                                   .long("max")
                                                                   .short("m")
                                                                   .takes_value(true)
                                                                   .required(true)))
                                                  .subcommand(SubCommand::with_name("repeated")
                                                              .about("Attack repeated xor encrypted input")
                                                              .arg(Arg::with_name("keysize-criterion")
                                                                   .help("Criterion to determine keysize")
                                                                   .short("k")
                                                                   .long("keysize-criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["hamming-distance"])
                                                                   .required(false))
                                                              .arg(Arg::with_name("xor-criterion")
                                                                   .short("x")
                                                                   .long("xor-criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["printable", "text"])
                                                                   .help("criterion to be used for scoring the intermediate block results"))
                                                              .arg(Arg::with_name("criterion")
                                                                   .short("c")
                                                                   .long("criterion")
                                                                   .takes_value(true)
                                                                   .possible_values(&["printable", "text"])
                                                                   .help("criterion to be used for scoring the results for different keysizes"))
                                                              .arg(Arg::with_name("keysizes-try")
                                                                   .short("t")
                                                                   .long("keysizes-try")
                                                                   .takes_value(true)
                                                                   .required(false)
                                                                   .help("criterion to be used for scoring the results for different keysizes"))
                                                              .arg(Arg::with_name("min")
                                                                   .help("Minimum keysize to try")
                                                                   .long("min")
                                                                   .takes_value(true)
                                                                   .required(false))
                                                              .arg(Arg::with_name("max")
                                                                   .help("Maximum keysize to try")
                                                                   .long("max")
                                                                   .short("m")
                                                                   .takes_value(true)
                                                                   .required(true)))))
                          .get_matches();

    if let Some(matches) = matches.subcommand_matches("encode") {
        if let Some(_) = matches.subcommand_matches("base64") {
            run_encode_base64();
        } else if let Some(_) = matches.subcommand_matches("hex") {
            run_encode_hex();
        }
    } else if let Some(matches) = matches.subcommand_matches("decode") {
        if let Some(_) = matches.subcommand_matches("base64") {
            run_decode_base64();
        } else if let Some(_) = matches.subcommand_matches("hex") {
            run_decode_hex();
        }
    } else if let Some(matches) = matches.subcommand_matches("encrypt") {
        if let Some(matches) = matches.subcommand_matches("xor") {
            match matches.value_of("key") {
                Some(k) => {
                    run_encrypt_xor(k);
                }
                None => {
                    println!("Error: No key received!");
                }
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("decrypt") {
        if let Some(matches) = matches.subcommand_matches("xor") {
            match matches.value_of("key") {
                Some(k) => {
                    run_decrypt_xor(k);
                }
                None => {
                    println!("Error: No key received!");
                }
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("attack") {
        if let Some(xor_matches) = matches.subcommand_matches("xor") {
            if let Some(keysize_matches) = xor_matches.subcommand_matches("keysize") {
                let criterion = match keysize_matches.value_of("criterion") {
                    Some("hamming-distance") => xor::hamming_distance_criterion,
                    Some(_) => xor::hamming_distance_criterion,
                    None => xor::hamming_distance_criterion
                };

                let min = match keysize_matches.value_of("min") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                let max = match keysize_matches.value_of("max") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                run_attack_xor_keysize(criterion, min, max);
                return;
            } else if let Some(repeated_matches) = xor_matches.subcommand_matches("repeated") {
                let xor_criterion = match repeated_matches.value_of("xor-criterion") {
                    Some("printable") => criteria::printable_bytes,
                    Some("text") => criteria::text_bytes,
                    Some(_) => criteria::text_bytes,
                    None => criteria::text_bytes
                };

                let result_criterion = match xor_matches.value_of("criterion") {
                    Some("printable") => criteria::printable_bytes,
                    Some("text") => criteria::text_bytes,
                    Some(_) => criteria::text_bytes,
                    None => criteria::text_bytes
                };

                let keysize_criterion = match repeated_matches.value_of("keysize-criterion") {
                    Some("hamming-distance") => xor::hamming_distance_criterion,
                    Some(_) => xor::hamming_distance_criterion,
                    None => xor::hamming_distance_criterion
                };

                let keysize_try = match repeated_matches.value_of("keysizes-try") {
                    Some(v) => v.parse::<usize>().unwrap(),
                    None => 1
                };

                let min = match repeated_matches.value_of("min") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                let max = match repeated_matches.value_of("max") {
                    Some(v) => v.parse::<u32>().unwrap(),
                    None => 1
                };

                run_attack_xor_repeated(keysize_criterion, min, max, keysize_try, xor_criterion, result_criterion);
                return;
            }

            let criterion = match xor_matches.value_of("criterion") {
                Some("printable") => criteria::printable_bytes,
                Some("text") => criteria::text_bytes,
                Some(_) => criteria::printable_bytes,
                None => criteria::printable_bytes
            };

            if xor_matches.is_present("detailed") {
                run_attack_xor_detailed(criterion);
            } else {
                run_attack_xor(criterion);
            }
        }
    } else {
        run_interpreter();
    }
}

fn run_encode_base64() {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = encoding::base64_encode(&input);
    print!("{}", result);
}

fn run_encode_hex() {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = encoding::hex_encode(&input);
    print!("{}", result);
}

fn run_decode_base64() {
    let mut input = String::new();
    match io::stdin().read_to_string(&mut input) {
        Ok(_) => {
            let result = encoding::base64_decode(&input);
            io::stdout().write(&result).unwrap();
        }
        Err(error) => { println!("Error: {}", error); }
    }
}

fn run_decode_hex() {
    let mut input = String::new();
    match io::stdin().read_to_string(&mut input) {
        Ok(_) => {
            let result = encoding::hex_decode(&input);
            io::stdout().write(&result).unwrap();
        }
        Err(error) => { println!("Error: {}", error); }
    }
}

fn run_encrypt_xor(key: &str) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = Xor::new(key.as_bytes()).encrypt(&input);
    io::stdout().write(&result).unwrap();
}

fn run_decrypt_xor(key: &str) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let result = Xor::new(key.as_bytes()).decrypt(&input);
    io::stdout().write(&result).unwrap();
}

fn run_attack_xor(criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (_, _, decrypted) = xor::SingleByteAttack::new()
        .with_criterion(Box::new(criterion))
        .result(&input);

    io::stdout().write(&decrypted).unwrap();
}

fn run_attack_xor_detailed(criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (key, score, decrypted) = xor::SingleByteAttack::new()
        .with_criterion(Box::new(criterion))
        .result(&input);

    print!("Key: {}\tScore: {}\tResult: ", key, score);
    io::stdout().write(&decrypted).unwrap();
    println!("");
}

fn run_attack_xor_keysize(criterion: fn(&[u8], size: u32) -> f32, min: u32, max: u32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let results = xor::KeysizeAttack::new()
        .with_min_length(min)
        .with_max_length(max)
        .with_criterion(Box::new(criterion))
        .result(&input);

    for (size, score) in results {
        println!("Size: {}\tScore: {}", size, score);
    }
}

fn run_attack_xor_repeated(keysize_criterion: fn(&[u8], size: u32) -> f32, min: u32, max: u32, keysize_try: usize, xor_criterion: fn(&[u8]) -> f32, result_criterion: fn(&[u8]) -> f32) {
    let mut input = Vec::new();
    io::stdin().read_to_end(&mut input).unwrap();

    let (key, decrypted) = xor::RepeatedAttack::new()
        .with_single_byte_attack(xor::SingleByteAttack::new()
                                 .with_criterion(Box::new(xor_criterion)))
        .with_keysize_attack(xor::KeysizeAttack::new()
                             .with_min_length(min)
                             .with_max_length(max)
                             .with_criterion(Box::new(keysize_criterion)))
        .with_result_criterion(Box::new(result_criterion))
        .with_keysizes_count(keysize_try)
        .result(&input);

    let mut stdout = io::stdout();
    print!("Key: ");
    stdout.write(&key).unwrap();
    print!("\nDecrypted:\n");
    stdout.write(&decrypted).unwrap();
}

fn run_interpreter() {
    println!("Interpreter");
}
<|endoftext|>