<commit_before>extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, Device, FeatureSet, LanguageVersion, SpecificLanguageVersion};
use metl::LibraryErrorType;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(), DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options =
        CompileOptions::default()
            .fast_math_enabled(fast_math_enabled)
            .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
            .with_macro("Foo", 54)
            .with_macro("Bar", 32.0)
            .with_macro("Baz", "Hi")
            .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

// Shader source taken from http://metalbyexample.com/up-and-running-2/
const SHADER: &'static str = r"
using namespace metal;

struct ColoredVertex
{
    float4 position [[position]];
    float4 color;
};

vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                 constant float4 *color [[buffer(1)]],
                                 uint vid [[vertex_id]])
{
    ColoredVertex vert;
    vert.position = position[vid];
    vert.color = color[vid];
    return vert;
}

fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
{
    return vert.color;
}
";

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
fn shader_get_function_with_name() {
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main");
    assert!(function.is_some());
}

#[test]
#[ignore]
fn shader_get_struct_info() {
    use metl::{StructMember, StructType};
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main").unwrap();
    unimplemented!();
}
<commit_msg>Add test device_create_library_async, and fix tests from previous refactoring<commit_after>extern crate metl;
extern crate cocoa;

use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;
use metl::{CompileOptions, Device, FeatureSet, LanguageVersion, SpecificLanguageVersion};
use metl::LibraryError;
use metl::{FromRaw, FromRawError, IntoRaw};
use metl::sys::{MTLCompileOptions, MTLLanguageVersion};

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[cfg(target_os = "macos")]
#[test]
fn device_supports_base_features() {
    let base_osx_feature_set = FeatureSet::OsxGpuFamily1_v1;
    let device = Device::system_default_device().unwrap();
    assert!(device.supports_feature_set(base_osx_feature_set));
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    const DUMMY_COMMAND_QUEUE_NAME: &'static str = "foo";
    command_queue.set_label(&DUMMY_COMMAND_QUEUE_NAME);

    assert_eq!(command_queue.label(), DUMMY_COMMAND_QUEUE_NAME);
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options =
        CompileOptions::default()
            .fast_math_enabled(fast_math_enabled)
            .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
            .with_macro("Foo", 54)
            .with_macro("Bar", 32.0)
            .with_macro("Baz", "Hi")
            .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(LibraryError::SourceError(_)) => assert!(true),
        Err(_) => panic!("Incorrect error type")
    }
}

// Shader source taken from http://metalbyexample.com/up-and-running-2/
const SHADER: &'static str = r"
using namespace metal;

struct ColoredVertex
{
    float4 position [[position]];
    float4 color;
};

vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                 constant float4 *color [[buffer(1)]],
                                 uint vid [[vertex_id]])
{
    ColoredVertex vert;
    vert.position = position[vid];
    vert.color = color[vid];
    return vert;
}

fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
{
    return vert.color;
}
";

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}

#[test]
fn device_create_library_async() {
    let mut device = Device::system_default_device().unwrap();
    let library = device.new_library_with_source_async(&SHADER, &Default::default())
                        .recv()
                        .unwrap();
    assert!(library.is_ok());
}

#[test]
fn shader_get_function_with_name() {
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main");
    assert!(function.is_some());
}

#[test]
#[ignore]
fn shader_get_struct_info() {
    use metl::{StructMember, StructType};
    let mut device = Device::system_default_device().unwrap();
    let mut library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let function = library.new_function_with_name(&"fragment_main").unwrap();
    unimplemented!();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2016 Nathan Fiedler
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate magick_rust;

use magick_rust::{MagickWand, magick_wand_genesis};
use magick_rust::filters::{FilterType};

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::sync::{Once, ONCE_INIT};

// Used to make sure MagickWand is initialized exactly once. Note that we
// do not bother shutting down, we simply exit when the tests are done.
static START: Once = ONCE_INIT;

#[test]
fn test_new_drop() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    MagickWand::new();
}

#[test]
fn test_resize_image() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let halfwidth = match wand.get_image_width() {
        1 => 1,
        width => width / 2
    };
    let halfheight = match wand.get_image_height() {
        1 => 1,
        height => height / 2
    };
    wand.resize_image(halfwidth, halfheight, FilterType::LanczosFilter, 1.0);
    assert_eq!(256, wand.get_image_width());
    assert_eq!(192, wand.get_image_height());
}

#[test]
fn test_read_from_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();

    let path = Path::new("tests/data/IMG_5745.JPG");
    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
        Ok(file) => file
    };
    let mut data: Vec<u8> = Vec::new();
    match file.read_to_end(&mut data) {
        Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
        Ok(_) => ()
    };
    assert!(wand.read_image_blob(data).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_image_blob("jpeg").unwrap();
    if cfg!(target_os = "macos") {
        // yeah, don't know why...
        assert_eq!(104061, blob.len());
    } else {
        assert_eq!(104060, blob.len());
    }
    // should be able to read it back again
    assert!(wand.read_image_blob(blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_fit() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    wand.fit(240, 240);
    assert_eq!(240, wand.get_image_width());
    assert_eq!(180, wand.get_image_height());
}

#[test]
fn test_get_image_property() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // retrieve a property we know exists
    let found_value = wand.get_image_property("exif:DateTimeOriginal");
    assert!(found_value.is_ok());
    assert_eq!("2014:04:23 13:33:08", found_value.unwrap());
    // retrieve a property that does not exist
    let missing_value = wand.get_image_property("exif:Foobar");
    assert!(missing_value.is_err());
    assert_eq!("missing property", missing_value.unwrap_err());
}

#[test]
fn test_requires_orientation() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_auto_orient() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    assert_eq!(true, wand.requires_orientation());
    assert!(wand.auto_orient());
    assert_eq!(false, wand.requires_orientation());
}
<commit_msg>Fix the tests after the API change<commit_after>/*
 * Copyright 2015-2016 Nathan Fiedler
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate magick_rust;

use magick_rust::{MagickWand, magick_wand_genesis};
use magick_rust::filters::{FilterType};

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::sync::{Once, ONCE_INIT};

// Used to make sure MagickWand is initialized exactly once. Note that we
// do not bother shutting down, we simply exit when the tests are done.
static START: Once = ONCE_INIT;

#[test]
fn test_new_drop() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    MagickWand::new();
}

#[test]
fn test_resize_image() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let halfwidth = match wand.get_image_width() {
        1 => 1,
        width => width / 2
    };
    let halfheight = match wand.get_image_height() {
        1 => 1,
        height => height / 2
    };
    wand.resize_image(halfwidth, halfheight, FilterType::LanczosFilter, 1.0);
    assert_eq!(256, wand.get_image_width());
    assert_eq!(192, wand.get_image_height());
}

#[test]
fn test_read_from_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();

    let path = Path::new("tests/data/IMG_5745.JPG");
    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
        Ok(file) => file
    };
    let mut data: Vec<u8> = Vec::new();
    match file.read_to_end(&mut data) {
        Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
        Ok(_) => ()
    };
    assert!(wand.read_image_blob(&data).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_image_blob("jpeg").unwrap();
    if cfg!(target_os = "macos") {
        // yeah, don't know why...
        assert_eq!(104061, blob.len());
    } else {
        assert_eq!(104060, blob.len());
    }
    // should be able to read it back again
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_fit() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    wand.fit(240, 240);
    assert_eq!(240, wand.get_image_width());
    assert_eq!(180, wand.get_image_height());
}

#[test]
fn test_get_image_property() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // retrieve a property we know exists
    let found_value = wand.get_image_property("exif:DateTimeOriginal");
    assert!(found_value.is_ok());
    assert_eq!("2014:04:23 13:33:08", found_value.unwrap());
    // retrieve a property that does not exist
    let missing_value = wand.get_image_property("exif:Foobar");
    assert!(missing_value.is_err());
    assert_eq!("missing property", missing_value.unwrap_err());
}

#[test]
fn test_requires_orientation() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_auto_orient() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    assert_eq!(true, wand.requires_orientation());
    assert!(wand.auto_orient());
    assert_eq!(false, wand.requires_orientation());
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate quickcheck;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path};
use quickcheck::{quickcheck, TestResult};

extern crate hyphenation;
use hyphenation::{load, Language, Corpus, Hyphenation, FullTextHyphenation, Standard};

fn fiat_io(lang: Language) -> Corpus { load::language(lang).unwrap() }

lazy_static! {
    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[test]
fn collected_equals_original() {
    fn property(original: String) -> bool {
        let collected: String = original.hyphenate(&EN_US).collect();

        collected == original
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn opportunities_within_bounds() {
    fn property(s: String) -> bool {
        let os = s.opportunities(&EN_US);
        let l = s.len();

        os.iter().all(|&i| i < l)
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn punctuated_count() {
    fn property(s: String) -> bool {
        let l = s.chars().count();
        let os = s.opportunities(&EN_US);
        let h: String = s.hyphenate(&EN_US).punctuate().collect();

        h.chars().count() == l + os.len()
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn hyphenation_bounds() {
    fn property(s: String) -> TestResult {
        let ci: Vec<_> = s.char_indices().collect();
        let (l_min, r_min) = (&EN_US.left_min, &EN_US.right_min);
        let s_len = ci.len();
        if s_len < l_min + r_min {
            return TestResult::discard();
        }

        let os = s.opportunities(&EN_US);
        let ((l, _), (r, _)) = (ci[l_min - 1], ci[s_len - r_min]);
        let within_bounds = |&i| i > l && i <= r;

        TestResult::from_bool(os.iter().all(within_bounds))
    }

    quickcheck(property as fn(String) -> TestResult);
}

#[test]
fn basics() {
    let h1: Standard = "hyphenation".hyphenate(&EN_US);
    let h2: Standard = "project".hyphenate(&EN_US);
    let h3: Standard = "hypha".hyphenate(&EN_US);
    let h4: Standard = "Word hyphenation by computer.".fulltext_hyphenate(&EN_US);

    assert_eq!(h1.size_hint(), (3, Some(3)));
    assert_eq!(h2.size_hint(), (1, Some(1)));
    assert_eq!(h3.size_hint(), (2, Some(2)));
    assert_eq!(h4.size_hint(), (4, Some(4)));

    let v1: Vec<&str> = h1.clone().collect();
    let v2: Vec<&str> = h2.clone().collect();
    let v3: Vec<&str> = h3.clone().collect();
    let v4: Vec<&str> = h4.clone().collect();
    assert_eq!(v1, vec!["hy", "phen", "ation"]);
    assert_eq!(v2, vec!["project"]);
    assert_eq!(v3, vec!["hy", "pha"]);
    assert_eq!(v4, vec!["Word hy", "phen", "ation by com", "puter."]);

    let s1: String = h1.punctuate().collect();
    assert_eq!(s1, "hy\u{ad}phen\u{ad}ation".to_owned());

    // And some further size_hint sanity checking for partially consumed iterators.
    let mut h2 = h2;
    h2.next();
    assert_eq!(h2.size_hint(), (0, Some(0)));
    h2.next();
    assert_eq!(h2.size_hint(), (0, Some(0)));

    let mut h3 = h3;
    h3.next();
    assert_eq!(h3.size_hint(), (1, Some(1)));
    h3.next();
    assert_eq!(h3.size_hint(), (0, Some(0)));
}
<commit_msg>Test for known inaccuracies in word hyphenation<commit_after>#[macro_use]
extern crate lazy_static;
extern crate quickcheck;

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path};
use quickcheck::{quickcheck, TestResult};

extern crate hyphenation;
use hyphenation::{load, Language, Corpus, Hyphenation, FullTextHyphenation, Standard};

fn fiat_io(lang: Language) -> Corpus { load::language(lang).unwrap() }

lazy_static! {
    static ref EN_US: Corpus = fiat_io(Language::English_US);

    static ref WORDS: Vec<String> = {
        let file = File::open(Path::new("/usr/share/dict/words")).unwrap();
        let words: Vec<_> = BufReader::new(file).lines().map(|l| l.unwrap()).collect();

        words
    };
}

#[test]
fn collected_equals_original() {
    fn property(original: String) -> bool {
        let collected: String = original.hyphenate(&EN_US).collect();

        collected == original
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn opportunities_within_bounds() {
    fn property(s: String) -> bool {
        let os = s.opportunities(&EN_US);
        let l = s.len();

        os.iter().all(|&i| i < l)
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn punctuated_count() {
    fn property(s: String) -> bool {
        let l = s.chars().count();
        let os = s.opportunities(&EN_US);
        let h: String = s.hyphenate(&EN_US).punctuate().collect();

        h.chars().count() == l + os.len()
    }

    quickcheck(property as fn(String) -> bool);
}

#[test]
fn hyphenation_bounds() {
    fn property(s: String) -> TestResult {
        let ci: Vec<_> = s.char_indices().collect();
        let (l_min, r_min) = (&EN_US.left_min, &EN_US.right_min);
        let s_len = ci.len();
        if s_len < l_min + r_min {
            return TestResult::discard();
        }

        let os = s.opportunities(&EN_US);
        let ((l, _), (r, _)) = (ci[l_min - 1], ci[s_len - r_min]);
        let within_bounds = |&i| i > l && i <= r;

        TestResult::from_bool(os.iter().all(within_bounds))
    }

    quickcheck(property as fn(String) -> TestResult);
}

#[test]
fn basics() {
    let h1: Standard = "hyphenation".hyphenate(&EN_US);
    let h2: Standard = "project".hyphenate(&EN_US);
    let h3: Standard = "hypha".hyphenate(&EN_US);
    let h4: Standard = "Word hyphenation by computer.".fulltext_hyphenate(&EN_US);

    assert_eq!(h1.size_hint(), (3, Some(3)));
    assert_eq!(h2.size_hint(), (1, Some(1)));
    assert_eq!(h3.size_hint(), (2, Some(2)));
    assert_eq!(h4.size_hint(), (4, Some(4)));

    let v1: Vec<&str> = h1.clone().collect();
    let v2: Vec<&str> = h2.clone().collect();
    let v3: Vec<&str> = h3.clone().collect();
    let v4: Vec<&str> = h4.clone().collect();
    assert_eq!(v1, vec!["hy", "phen", "ation"]);
    assert_eq!(v2, vec!["project"]);
    assert_eq!(v3, vec!["hy", "pha"]);
    assert_eq!(v4, vec!["Word hy", "phen", "ation by com", "puter."]);

    let s1: String = h1.punctuate().collect();
    assert_eq!(s1, "hy\u{ad}phen\u{ad}ation".to_owned());

    // And some further size_hint sanity checking for partially consumed iterators.
    let mut h2 = h2;
    h2.next();
    assert_eq!(h2.size_hint(), (0, Some(0)));
    h2.next();
    assert_eq!(h2.size_hint(), (0, Some(0)));

    let mut h3 = h3;
    h3.next();
    assert_eq!(h3.size_hint(), (1, Some(1)));
    h3.next();
    assert_eq!(h3.size_hint(), (0, Some(0)));
}

#[test]
#[should_panic(expected = "assertion failed")]
fn known_inaccuracies() {
    let example1: Vec<&str> = "chionididae".hyphenate(&EN_US).collect();

    assert!(example1 == vec!["chi", "o", "nid", "i", "dae"]);
}
<|endoftext|>


<commit_before>extern crate assert;
extern crate dft;

use dft::{Operation, Plan, Transform, c64};

mod fixtures;

#[test]
fn complex_forward_128() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    as_c64_mut(&mut data).transform(&Plan::new(Operation::Forward, 128));
    assert::close(&data, &fixtures::FREQUENCY_DATA_128_COMPLEX[..], 1e-14);
}

#[test]
fn complex_forward_real_256() {
    let mut data = to_c64(&fixtures::TIME_DATA_256);
    data.transform(&Plan::new(Operation::Forward, 256));
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn complex_inverse_128() {
    let mut data = fixtures::FREQUENCY_DATA_128_COMPLEX.to_vec();
    as_c64_mut(&mut data).transform(&Plan::new(Operation::Inverse, 128));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_forward_256() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    data.transform(&Plan::new(Operation::Forward, 256));
    assert::close(&data, &fixtures::FREQUENCY_DATA_256_REAL_PACKED[..], 1e-13);
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn real_forward_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    data.transform(&Plan::new(Operation::Forward, 512));
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_512_REAL_UNPACKED[..], 1e-12);
}

#[test]
fn real_inverse_256() {
    let mut data = fixtures::FREQUENCY_DATA_256_REAL_PACKED.to_vec();
    data.transform(&Plan::new(Operation::Inverse, 256));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_inverse_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    data.transform(&Plan::new(Operation::Forward, 512));
    data.transform(&Plan::new(Operation::Inverse, 512));
    assert::close(&data, &fixtures::TIME_DATA_512[..], 1e-14);
}

fn as_f64<'l>(slice: &'l [c64]) -> &'l [f64] {
    unsafe {
        std::slice::from_raw_parts(slice.as_ptr() as *const _, 2 * slice.len())
    }
}

fn as_c64_mut<'l>(slice: &'l mut [f64]) -> &'l mut [c64] {
    unsafe {
        std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut _, slice.len() / 2)
    }
}

fn to_c64(slice: &[f64]) -> Vec<c64> {
    slice.iter().map(|&re| c64::new(re, 0.0)).collect()
}
<commit_msg>Eliminate redundant lifetime annotations<commit_after>extern crate assert;
extern crate dft;

use dft::{Operation, Plan, Transform, c64};

mod fixtures;

#[test]
fn complex_forward_128() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    as_c64_mut(&mut data).transform(&Plan::new(Operation::Forward, 128));
    assert::close(&data, &fixtures::FREQUENCY_DATA_128_COMPLEX[..], 1e-14);
}

#[test]
fn complex_forward_real_256() {
    let mut data = to_c64(&fixtures::TIME_DATA_256);
    data.transform(&Plan::new(Operation::Forward, 256));
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn complex_inverse_128() {
    let mut data = fixtures::FREQUENCY_DATA_128_COMPLEX.to_vec();
    as_c64_mut(&mut data).transform(&Plan::new(Operation::Inverse, 128));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_forward_256() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    data.transform(&Plan::new(Operation::Forward, 256));
    assert::close(&data, &fixtures::FREQUENCY_DATA_256_REAL_PACKED[..], 1e-13);
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn real_forward_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    data.transform(&Plan::new(Operation::Forward, 512));
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_512_REAL_UNPACKED[..], 1e-12);
}

#[test]
fn real_inverse_256() {
    let mut data = fixtures::FREQUENCY_DATA_256_REAL_PACKED.to_vec();
    data.transform(&Plan::new(Operation::Inverse, 256));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_inverse_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    data.transform(&Plan::new(Operation::Forward, 512));
    data.transform(&Plan::new(Operation::Inverse, 512));
    assert::close(&data, &fixtures::TIME_DATA_512[..], 1e-14);
}

fn as_f64(slice: &[c64]) -> &[f64] {
    unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const _, 2 * slice.len()) }
}

fn as_c64_mut(slice: &mut [f64]) -> &mut [c64] {
    unsafe { std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut _, slice.len() / 2) }
}

fn to_c64(slice: &[f64]) -> Vec<c64> {
    slice.iter().map(|&re| c64::new(re, 0.0)).collect()
}
<|endoftext|>


<commit_before>use node::serde_json;
use events::Channel;
use node::{ExternalMessage, NodeHandler, NodeTimeout};
use super::super::messages::{ConfigPropose, ConfigVote};
use super::super::blockchain::{Blockchain, View};
use super::super::crypto::{PublicKey, Hash};
use super::super::storage::Map;
use super::super::messages::Message;
use byteorder::{ByteOrder, LittleEndian};

#[derive(Debug, Serialize, Deserialize)]
pub struct Configuration {
    actual_from: u64,
    validators: Vec<PublicKey>,
    consensus: ConsensusCfg
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ConsensusCfg {
    round_timeout: u64,    // 2000
    status_timeout: u64,   // 5000
    peers_timeout: u64,    // 10000
    propose_timeout: u64,  // 500
    txs_block_limit: u16   // 500
}

trait ConfigurationValidator {
    fn is_valid(&self) -> bool;
}

impl ConfigurationValidator for ConsensusCfg {
    fn is_valid(&self) -> bool {
        self.round_timeout < 10000
    }
}

impl Configuration {

    #[allow(dead_code)]
    fn serialize(&self) -> Vec<u8> {
        serde_json::to_vec(&self).unwrap()
    }

    #[allow(dead_code)]
    fn deserialize(serialized: &[u8]) -> Result<Configuration, &str> {
        let cfg: Configuration = serde_json::from_slice(serialized).unwrap();
        if cfg.is_valid() {
            return Ok(cfg);
        }
        Err("not valid")
    }
}

impl ConfigurationValidator for Configuration {
    fn is_valid(&self) -> bool {
        self.consensus.is_valid()
    }
}

impl<B, S> NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    pub fn handle_config_propose(&self, config_propose: ConfigPropose) {

        if config_propose.height() < self.state.height() || config_propose.height() > self.state.height() + 1 {
            warn!("Received ConfigPropose message from other height: msg.height={}, self.height={}",
                  config_propose.height(),
                  self.state.height());
            return;
        }

        if config_propose.actual_from_height() < self.state.height() {
            error!("Received config for past height: msg.actual_from_height={}, self.height={}",
                config_propose.actual_from_height(), self.state.height());
            return;
        }

        if !self.state.validators().contains(config_propose.from()){
            error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
            return;
        }

        let view = self.blockchain.view();
        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose);

    }

    pub fn handle_config_vote(&self, config_vote: ConfigVote){

        if config_vote.height() < self.state.height() || config_vote.height() > self.state.height() + 1 {
            warn!("Received ConfigVote message from other height: msg.height={}, self.height={}",
                  config_vote.height(),
                  self.state.height());
            return;
        }

        if !self.state.validators().contains(config_vote.from()){
            error!("ConfigVote from unknown validator: {:?}", config_vote.from());
            return;
        }

        let view = self.blockchain.view();
        if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
            error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
            return;
        }

        if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
            if vote.seed() != config_vote.seed() -1 {
                error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                return;
            }
        }

        let msg = config_vote.clone();
        let _ = view.config_votes().put(msg.from(), config_vote.clone());

        let mut votes_count = 0;
        for pub_key in self.state.validators(){
            if let Some(vote) = view.config_votes().get(pub_key).unwrap() {
                if !vote.revoke() {
                    votes_count += 1;
                }
            }
        }

        if votes_count >= 2/3 * self.state.validators().len(){
            if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                view.configs().put(&Hash(self.height_to_slice(config_propose.actual_from_height())), config_propose.config().to_vec()).unwrap();
                // TODO: clear storages
            }
        }
    }

    fn height_to_slice(&self, height: u64) -> [u8;32] {
        let mut result = [0; 32];
        LittleEndian::write_u64(&mut result[24..], height);
        result
    }
}

#[cfg(test)]
mod tests {

    use super::super::super::crypto::{gen_keypair};
    use super::{Configuration, ConsensusCfg, NetworkCfg, ConfigurationValidator};

    #[test]
    fn validate_configuration(){
        // Arrange

        let (p1, _) = gen_keypair();
        let (p2, _) = gen_keypair();
        let (p3, _) = gen_keypair();

        let cfg = Configuration {
            version: 1,
            validators: vec![p1, p2, p3],
            consensus: ConsensusCfg {
                round_timeout: 2000,
                status_timeout: 5000,
                peers_timeout: 10000,
                propose_timeout: 500,
                txs_block_limit: 500
            }
        };

        // Assert
        assert_eq!(cfg.is_valid(), true);
    }

    #[test]
    fn deserialize_correct_configuration(){
        // Arrange
        let json = String::from("{\"actual_from\":1,\"validators\":[[255,110,239,100,242,107,33,125,149,196,6,71,45,5,143,15,66,144,168,233,171,18,1,81,183,253,49,72,248,226,88,224],[100,2,253,143,161,127,247,209,175,28,191,6,240,0,255,119,238,66,101,154,110,219,187,25,28,34,69,65,223,131,163,227],[185,187,188,22,223,202,133,226,118,76,203,52,17,132,193,213,117,57,36,15,106,67,129,218,175,32,34,235,240,51,83,81]],\"consensus\":{\"round_timeout\":2000,\"status_timeout\":5000,\"peers_timeout\":10000,\"propose_timeout\":500,\"txs_block_limit\":500}}").into_bytes().as_slice();

        // Act
        let cfg = Configuration::deserialize(&json);

        // Assert
        assert_eq!(cfg.is_ok(), true);

    }

    #[test]
    fn deserialize_wrong_configuration(){
        // Arrange
        let json = String::from("{\"actual_from\":1,\"validators\":[[255,110,239,100,242,107,33,125,149,196,6,71,45,5,143,15,66,144,168,233,171,18,1,81,183,253,49,72,248,226,88,224],[100,2,253,143,161,127,247,209,175,28,191,6,240,0,255,119,238,66,101,154,110,219,187,25,28,34,69,65,223,131,163,227],[185,187,188,22,223,202,133,226,118,76,203,52,17,132,193,213,117,57,36,15,106,67,129,218,175,32,34,235,240,51,83,81]],\"consensus\":{\"round_timeout\":11000,\"status_timeout\":5000,\"peers_timeout\":10000,\"propose_timeout\":500,\"txs_block_limit\":500}}").into_bytes().as_slice();

        // Act
        let cfg = Configuration::deserialize(json);

        // Assert
        assert_eq!(cfg.is_ok(), false);

    }

}<commit_msg>tests fix<commit_after>use node::serde_json;
use events::Channel;
use node::{ExternalMessage, NodeHandler, NodeTimeout};
use super::super::messages::{ConfigPropose, ConfigVote};
use super::super::blockchain::{Blockchain, View};
use super::super::crypto::{PublicKey, Hash};
use super::super::storage::Map;
use super::super::messages::Message;
use byteorder::{ByteOrder, LittleEndian};

#[derive(Debug, Serialize, Deserialize)]
pub struct Configuration {
    actual_from: u64,
    validators: Vec<PublicKey>,
    consensus: ConsensusCfg
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ConsensusCfg {
    round_timeout: u64,    // 2000
    status_timeout: u64,   // 5000
    peers_timeout: u64,    // 10000
    propose_timeout: u64,  // 500
    txs_block_limit: u16   // 500
}

trait ConfigurationValidator {
    fn is_valid(&self) -> bool;
}

impl ConfigurationValidator for ConsensusCfg {
    fn is_valid(&self) -> bool {
        self.round_timeout < 10000
    }
}

impl Configuration {

    #[allow(dead_code)]
    fn serialize(&self) -> Vec<u8> {
        serde_json::to_vec(&self).unwrap()
    }

    #[allow(dead_code)]
    fn deserialize(serialized: &[u8]) -> Result<Configuration, &str> {
        let cfg: Configuration = serde_json::from_slice(serialized).unwrap();
        if cfg.is_valid() {
            return Ok(cfg);
        }
        Err("not valid")
    }
}

impl ConfigurationValidator for Configuration {
    fn is_valid(&self) -> bool {
        self.consensus.is_valid()
    }
}

impl<B, S> NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    pub fn handle_config_propose(&self, config_propose: ConfigPropose) {

        if config_propose.height() < self.state.height() || config_propose.height() > self.state.height() + 1 {
            warn!("Received ConfigPropose message from other height: msg.height={}, self.height={}",
                  config_propose.height(),
                  self.state.height());
            return;
        }

        if config_propose.actual_from_height() < self.state.height() {
            error!("Received config for past height: msg.actual_from_height={}, self.height={}",
                config_propose.actual_from_height(), self.state.height());
            return;
        }

        if !self.state.validators().contains(config_propose.from()){
            error!("ConfigPropose from unknown validator: {:?}", config_propose.from());
            return;
        }

        let view = self.blockchain.view();
        if view.config_proposes().get(&config_propose.hash()).unwrap().is_some() {
            error!("Received config_propose has already been handled, msg={:?}", config_propose);
            return;
        }

        trace!("Handle ConfigPropose");
        let _ = view.config_proposes().put(&config_propose.hash(), config_propose);

    }

    pub fn handle_config_vote(&self, config_vote: ConfigVote){

        if config_vote.height() < self.state.height() || config_vote.height() > self.state.height() + 1 {
            warn!("Received ConfigVote message from other height: msg.height={}, self.height={}",
                  config_vote.height(),
                  self.state.height());
            return;
        }

        if !self.state.validators().contains(config_vote.from()){
            error!("ConfigVote from unknown validator: {:?}", config_vote.from());
            return;
        }

        let view = self.blockchain.view();
        if view.config_proposes().get(config_vote.hash_propose()).unwrap().is_some() {
            error!("Received config_vote for unknown transaciton, msg={:?}", config_vote);
            return;
        }

        if let Some(vote) = view.config_votes().get(config_vote.from()).unwrap() {
            if vote.seed() != config_vote.seed() -1 {
                error!("Received config_vote with wrong seed, msg={:?}", config_vote);
                return;
            }
        }

        let msg = config_vote.clone();
        let _ = view.config_votes().put(msg.from(), config_vote.clone());

        let mut votes_count = 0;
        for pub_key in self.state.validators(){
            if let Some(vote) = view.config_votes().get(pub_key).unwrap() {
                if !vote.revoke() {
                    votes_count += 1;
                }
            }
        }

        if votes_count >= 2/3 * self.state.validators().len(){
            if let Some(config_propose) = view.config_proposes().get(config_vote.hash_propose()).unwrap() {
                view.configs().put(&Hash(self.height_to_slice(config_propose.actual_from_height())), config_propose.config().to_vec()).unwrap();
                // TODO: clear storages
            }
        }
    }

    fn height_to_slice(&self, height: u64) -> [u8;32] {
        let mut result = [0; 32];
        LittleEndian::write_u64(&mut result[24..], height);
        result
    }
}

#[cfg(test)]
mod tests {

    use super::super::super::crypto::{gen_keypair};
    use super::{Configuration, ConsensusCfg, ConfigurationValidator};

    #[test]
    fn validate_configuration(){
        // Arrange

        let (p1, _) = gen_keypair();
        let (p2, _) = gen_keypair();
        let (p3, _) = gen_keypair();

        let cfg = Configuration {
            actual_from: 1,
            validators: vec![p1, p2, p3],
            consensus: ConsensusCfg {
                round_timeout: 2000,
                status_timeout: 5000,
                peers_timeout: 10000,
                propose_timeout: 500,
                txs_block_limit: 500
            }
        };

        // Assert
        assert_eq!(cfg.is_valid(), true);
    }

    // #[test]
    // fn deserialize_correct_configuration(){
    //     // Arrange
    //     let json = String::from("{\"actual_from\":1,\"validators\":[[255,110,239,100,242,107,33,125,149,196,6,71,45,5,143,15,66,144,168,233,171,18,1,81,183,253,49,72,248,226,88,224],[100,2,253,143,161,127,247,209,175,28,191,6,240,0,255,119,238,66,101,154,110,219,187,25,28,34,69,65,223,131,163,227],[185,187,188,22,223,202,133,226,118,76,203,52,17,132,193,213,117,57,36,15,106,67,129,218,175,32,34,235,240,51,83,81]],\"consensus\":{\"round_timeout\":2000,\"status_timeout\":5000,\"peers_timeout\":10000,\"propose_timeout\":500,\"txs_block_limit\":500}}").into_bytes().as_slice();

    //     // Act
    //     let cfg = Configuration::deserialize(&json);

    //     // Assert
    //     assert_eq!(cfg.is_ok(), true);

    // }

    // #[test]
    // fn deserialize_wrong_configuration(){
    //     // Arrange
    //     let json = String::from("{\"actual_from\":1,\"validators\":[[255,110,239,100,242,107,33,125,149,196,6,71,45,5,143,15,66,144,168,233,171,18,1,81,183,253,49,72,248,226,88,224],[100,2,253,143,161,127,247,209,175,28,191,6,240,0,255,119,238,66,101,154,110,219,187,25,28,34,69,65,223,131,163,227],[185,187,188,22,223,202,133,226,118,76,203,52,17,132,193,213,117,57,36,15,106,67,129,218,175,32,34,235,240,51,83,81]],\"consensus\":{\"round_timeout\":11000,\"status_timeout\":5000,\"peers_timeout\":10000,\"propose_timeout\":500,\"txs_block_limit\":500}}").into_bytes().as_slice();

    //     // Act
    //     let cfg = Configuration::deserialize(json);

    //     // Assert
    //     assert_eq!(cfg.is_ok(), false);

    // }

}<|endoftext|>


<commit_before>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};
use futures::stream::Stream;

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(f: F, initial_state: S) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let (s, more) = try_ready!(self.in_progress.poll());
        if more {
            self.in_progress = (self.f)(s);
            Ok(Async::NotReady)
        } else {
            Ok(Async::Ready(s))
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (Option<Vec<u8>>, R);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((Some(result), self.reader.take().unwrap())))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((None, self.reader.take().unwrap())))
                }

                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        unimplemented!()
    }
}

pub fn main() {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr = "127.0.0.1:8080";
    let child = ::std::process::Command::new(executable)
        .arg(addr)
        .spawn();

}
<commit_msg>start reactor and threadpool<commit_after>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};
use futures::stream::Stream;

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(f: F, initial_state: S) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let (s, more) = try_ready!(self.in_progress.poll());
        if more {
            self.in_progress = (self.f)(s);
            Ok(Async::NotReady)
        } else {
            Ok(Async::Ready(s))
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (Option<Vec<u8>>, R);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((Some(result), self.reader.take().unwrap())))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((None, self.reader.take().unwrap())))
                }

                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        unimplemented!()
    }
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr) -> Box<Future<Item=(), Error=::std::io::Error> + Send> {
    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle);
    let mut subscribers = Vec::new();
    for _ in 0..3 {
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle));
    }
    Box::new(publisher.join(::all::All::new(subscribers.into_iter())).and_then(|(publisher, subscribers)| {
        println!("connected");
        Ok(())
    }))
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = "127.0.0.1:8080";
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let _child = ::std::process::Command::new(executable)
        .arg(addr_str)
        .spawn();

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();

    let f = pool.spawn(new_task(&handle, &addr));

    try!(core.run(f));

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<|endoftext|>


<commit_before>
struct median_filter_t<'a> {
    window: &'a mut u8,
    input: &'a mut usize,
    hole: &'a mut i64,
    max: &'a mut i64,
}

fn median_init(f: median_filter_t, w_size: isize) -> i64 {
    *f.max = 0;
    *f.hole = 0;

    return 0;
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>simply init 2 fields of the struct<commit_after>
struct median_filter_t<'a> {
    window: &'a mut u8,
    input: &'a mut usize,
    hole: &'a mut i64,
    max: &'a mut i64,
}

fn median_init(f: median_filter_t, w_size: isize){
    *f.max = 0;
    *f.hole = 0;
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate cpython;
extern crate numpy;
extern crate ndarray;

use numpy::*;
use ndarray::*;
use cpython::{PyResult, Python};

// Pure Rust ndarray function
fn axpy(a: f64, x: ArrayViewD<f64>, y: ArrayViewD<f64>) -> ArrayD<f64> {
    a * &x + &y
}

// Python-wrapper of `axpy`
fn axpy_py(py: Python, a: f64, x: PyArray, y: PyArray) -> PyResult<PyArray> {
    let np = PyArrayModule::import(py)?;
    let x = x.as_array().expect("x must be f64 array");
    let y = y.as_array().expect("y must be f64 array");
    Ok(axpy(a, x, y).into_pyarray(py, &np))
}

// Define module "_rust_ext"
py_module_initializer!(_rust_ext, init_rust_ext, PyInit__rust_ext, |py, m| {
    m.add(py, "__doc__", "Rust extension for NumPy")?;
    m.add(py,
             "axpy",
             py_fn!(py, axpy_py(a: f64, x: PyArray, y: PyArray)))?;
    Ok(())
});
<commit_msg>Re-add `mult` as mutable/no-return example<commit_after>
#[macro_use]
extern crate cpython;
extern crate numpy;
extern crate ndarray;

use numpy::*;
use ndarray::*;
use cpython::{PyResult, Python, PyObject};

/* Pure rust-ndarray functions */

// immutable example
fn axpy(a: f64, x: ArrayViewD<f64>, y: ArrayViewD<f64>) -> ArrayD<f64> {
    a * &x + &y
}

// mutable example (no return)
fn mult(a: f64, mut x: ArrayViewMutD<f64>) {
    x *= a;
}

/* rust-cpython wrappers (to be exposed) */

// wrapper of `axpy`
fn axpy_py(py: Python, a: f64, x: PyArray, y: PyArray) -> PyResult<PyArray> {
    let np = PyArrayModule::import(py)?;
    let x = x.as_array().expect("x must be f64 array");
    let y = y.as_array().expect("y must be f64 array");
    Ok(axpy(a, x, y).into_pyarray(py, &np))
}

// wrapper of `mult`
fn mult_py(py: Python, a: f64, x: PyArray) -> PyResult<PyObject> {
    let x = x.as_array_mut().expect("x must be f64 array");
    mult(a, x);
    Ok(py.None()) // Python function must returns
}

/* Define module "_rust_ext" */
py_module_initializer!(_rust_ext, init_rust_ext, PyInit__rust_ext, |py, m| {
    m.add(py, "__doc__", "Rust extension for NumPy")?;
    m.add(py,
             "axpy",
             py_fn!(py, axpy_py(a: f64, x: PyArray, y: PyArray)))?;
    m.add(py, "mult", py_fn!(py, mult_py(a: f64, x: PyArray)))?;
    Ok(())
});
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore tldr

use clap::Command;
use std::collections::HashMap;
use std::ffi::OsString;
use std::fs::File;
use std::io::{self, Read, Seek, Write};
use zip::ZipArchive;

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn main() -> io::Result<()> {
    let mut tldr_zip = File::open("docs/tldr.zip")
        .ok()
        .and_then(|f| ZipArchive::new(f).ok());

    if tldr_zip.is_none() {
        println!("Warning: No tldr archive found, so the documentation will not include examples.");
        println!("To include examples in the documentation, download the tldr archive and put it in the docs/ folder.");
        println!();
        println!("  curl https://tldr.sh/assets/tldr.zip -o docs/tldr.zip");
        println!();
    }

    let utils = util_map::<Box<dyn Iterator<Item = OsString>>>();
    match std::fs::create_dir("docs/src/utils/") {
        Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
        x => x,
    }?;

    println!("Writing initial info to SUMMARY.md");
    let mut summary = File::create("docs/src/SUMMARY.md")?;

    let _ = write!(
        summary,
        "# Summary\n\
        \n\
        [Introduction](index.md)\n\
        * [Installation](installation.md)\n\
        * [Build from source](build.md)\n\
        * [Contributing](contributing.md)\n\
        * [GNU test coverage](test_coverage.md)\n\
        \n\
        # Reference\n\
        * [Multi-call binary](multicall.md)\n",
    );

    println!("Gathering utils per platform");
    let utils_per_platform = {
        let mut map = HashMap::new();
        for platform in ["unix", "macos", "windows"] {
            let platform_utils: Vec<String> = String::from_utf8(
                std::process::Command::new("./util/show-utils.sh")
                    .arg(format!("--features=feat_os_{}", platform))
                    .output()?
                    .stdout,
            )
            .unwrap()
            .split(' ')
            .map(ToString::to_string)
            .collect();
            map.insert(platform, platform_utils);
        }

        // Linux is a special case because it can support selinux
        let platform_utils: Vec<String> = String::from_utf8(
            std::process::Command::new("./util/show-utils.sh")
                .arg("--features=feat_os_unix feat_selinux")
                .output()?
                .stdout,
        )
        .unwrap()
        .split(' ')
        .map(ToString::to_string)
        .collect();
        map.insert("linux", platform_utils);

        map
    };

    println!("Writing to utils");
    let mut utils = utils.entries().collect::<Vec<_>>();
    utils.sort();
    for (&name, (_, command)) in utils {
        if name == "[" {
            continue;
        }
        let p = format!("docs/src/utils/{}.md", name);
        if let Ok(f) = File::create(&p) {
            MDWriter {
                w: Box::new(f),
                command: command(),
                name,
                tldr_zip: &mut tldr_zip,
                utils_per_platform: &utils_per_platform,
            }
            .markdown()?;
            println!("Wrote to '{}'", p);
        } else {
            println!("Error writing to {}", p);
        }
        writeln!(summary, "* [{0}](utils/{0}.md)", name)?;
    }
    Ok(())
}

struct MDWriter<'a, 'b> {
    w: Box<dyn Write>,
    command: Command,
    name: &'a str,
    tldr_zip: &'b mut Option<ZipArchive<File>>,
    utils_per_platform: &'b HashMap<&'b str, Vec<String>>,
}

impl<'a, 'b> MDWriter<'a, 'b> {
    fn markdown(&mut self) -> io::Result<()> {
        write!(self.w, "# {}\n\n", self.name)?;
        self.additional()?;
        self.usage()?;
        self.description()?;
        self.options()?;
        self.examples()
    }

    fn additional(&mut self) -> io::Result<()> {
        writeln!(self.w, "
")?;
        self.platforms()?;
        self.version()?;
        writeln!(self.w, "
")
    }

    fn platforms(&mut self) -> io::Result<()> {
        writeln!(self.w, "
")?;
        for (feature, icon) in [
            ("linux", "linux"),
            // freebsd is disabled for now because mdbook does not use font-awesome 5 yet.
            // ("unix", "freebsd"),
            ("macos", "apple"),
            ("windows", "windows"),
        ] {
            if self.name.contains("sum")
                || self.utils_per_platform[feature]
                    .iter()
                    .any(|u| u == self.name)
            {
                writeln!(self.w, "", icon)?;
            }
        }
        writeln!(self.w, "
")?;

        Ok(())
    }

    fn version(&mut self) -> io::Result<()> {
        writeln!(
            self.w,
            "
v{}
",
            self.command.render_version().split_once(' ').unwrap().1
        )
    }

    fn usage(&mut self) -> io::Result<()> {
        writeln!(self.w, "\n```")?;
        let mut usage: String = self
            .command
            .render_usage()
            .to_string()
            .lines()
            .skip(1)
            .map(|l| l.trim())
            .filter(|l| !l.is_empty())
            .collect::<Vec<_>>()
            .join("\n");
        usage = usage
            .to_string()
            .replace(uucore::execution_phrase(), self.name);
        writeln!(self.w, "{}", usage)?;
        writeln!(self.w, "```")
    }

    fn description(&mut self) -> io::Result<()> {
        if let Some(about) = self
            .command
            .get_long_about()
            .or_else(|| self.command.get_about())
        {
            writeln!(self.w, "{}", about)
        } else {
            Ok(())
        }
    }

    fn examples(&mut self) -> io::Result<()> {
        if let Some(zip) = self.tldr_zip {
            let content = if let Some(f) =
                get_zip_content(zip, &format!("pages/common/{}.md", self.name))
            {
                f
            } else if let Some(f) = get_zip_content(zip, &format!("pages/linux/{}.md", self.name)) {
                f
            } else {
                return Ok(());
            };

            writeln!(self.w, "## Examples")?;
            writeln!(self.w)?;
            for line in content.lines().skip_while(|l| !l.starts_with('-')) {
                if let Some(l) = line.strip_prefix("- ") {
                    writeln!(self.w, "{}", l)?;
                } else if line.starts_with('`') {
                    writeln!(self.w, "```shell\n{}\n```", line.trim_matches('`'))?;
                } else if line.is_empty() {
                    writeln!(self.w)?;
                } else {
                    println!("Not sure what to do with this line:");
                    println!("{}", line);
                }
            }
            writeln!(self.w)?;
            writeln!(
                self.w,
                "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
            )?;
            writeln!(self.w, ">")?;
            writeln!(
                self.w,
                "> Please note that, as uutils is a work in progress, some examples might fail."
            )?;
        }
        Ok(())
    }

    fn options(&mut self) -> io::Result<()> {
        writeln!(self.w, "
Options
")?;
        write!(self.w, "
")?;
        for arg in self.command.get_arguments() {
            write!(self.w, "
")?;
            let mut first = true;
            for l in arg.get_long_and_visible_aliases().unwrap_or_default() {
                if !first {
                    write!(self.w, ", ")?;
                } else {
                    first = false;
                }
                write!(self.w, "")?;
                write!(self.w, "--{}", l)?;
                if let Some(names) = arg.get_value_names() {
                    write!(
                        self.w,
                        "={}",
                        names
                            .iter()
                            .map(|x| format!("<{}>", x))
                            .collect::<Vec<_>>()
                            .join(" ")
                    )?;
                }
                write!(self.w, "")?;
            }
            for s in arg.get_short_and_visible_aliases().unwrap_or_default() {
                if !first {
                    write!(self.w, ", ")?;
                } else {
                    first = false;
                }
                write!(self.w, "")?;
                write!(self.w, "-{}", s)?;
                if let Some(names) = arg.get_value_names() {
                    write!(
                        self.w,
                        " {}",
                        names
                            .iter()
                            .map(|x| format!("<{}>", x))
                            .collect::<Vec<_>>()
                            .join(" ")
                    )?;
                }
                write!(self.w, "")?;
            }
            writeln!(self.w, "
")?;
            writeln!(
                self.w,
                "
\n\n{}\n\n
",
                arg.get_help()
                    .unwrap_or_default()
                    .to_string()
                    .replace('\n', "
")
            )?;
        }
        writeln!(self.w, "
\n")
    }
}

fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Option<String> {
    let mut s = String::new();
    archive.by_name(name).ok()?.read_to_string(&mut s).unwrap();
    Some(s)
}
<commit_msg>docs: fix usage string since clap 4<commit_after>// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore tldr

use clap::Command;
use std::collections::HashMap;
use std::ffi::OsString;
use std::fs::File;
use std::io::{self, Read, Seek, Write};
use zip::ZipArchive;

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn main() -> io::Result<()> {
    let mut tldr_zip = File::open("docs/tldr.zip")
        .ok()
        .and_then(|f| ZipArchive::new(f).ok());

    if tldr_zip.is_none() {
        println!("Warning: No tldr archive found, so the documentation will not include examples.");
        println!("To include examples in the documentation, download the tldr archive and put it in the docs/ folder.");
        println!();
        println!("  curl https://tldr.sh/assets/tldr.zip -o docs/tldr.zip");
        println!();
    }

    let utils = util_map::<Box<dyn Iterator<Item = OsString>>>();
    match std::fs::create_dir("docs/src/utils/") {
        Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
        x => x,
    }?;

    println!("Writing initial info to SUMMARY.md");
    let mut summary = File::create("docs/src/SUMMARY.md")?;

    let _ = write!(
        summary,
        "# Summary\n\
        \n\
        [Introduction](index.md)\n\
        * [Installation](installation.md)\n\
        * [Build from source](build.md)\n\
        * [Contributing](contributing.md)\n\
        * [GNU test coverage](test_coverage.md)\n\
        \n\
        # Reference\n\
        * [Multi-call binary](multicall.md)\n",
    );

    println!("Gathering utils per platform");
    let utils_per_platform = {
        let mut map = HashMap::new();
        for platform in ["unix", "macos", "windows"] {
            let platform_utils: Vec<String> = String::from_utf8(
                std::process::Command::new("./util/show-utils.sh")
                    .arg(format!("--features=feat_os_{}", platform))
                    .output()?
                    .stdout,
            )
            .unwrap()
            .split(' ')
            .map(ToString::to_string)
            .collect();
            map.insert(platform, platform_utils);
        }

        // Linux is a special case because it can support selinux
        let platform_utils: Vec<String> = String::from_utf8(
            std::process::Command::new("./util/show-utils.sh")
                .arg("--features=feat_os_unix feat_selinux")
                .output()?
                .stdout,
        )
        .unwrap()
        .split(' ')
        .map(ToString::to_string)
        .collect();
        map.insert("linux", platform_utils);

        map
    };

    println!("Writing to utils");
    let mut utils = utils.entries().collect::<Vec<_>>();
    utils.sort();
    for (&name, (_, command)) in utils {
        if name == "[" {
            continue;
        }
        let p = format!("docs/src/utils/{}.md", name);
        if let Ok(f) = File::create(&p) {
            MDWriter {
                w: Box::new(f),
                command: command(),
                name,
                tldr_zip: &mut tldr_zip,
                utils_per_platform: &utils_per_platform,
            }
            .markdown()?;
            println!("Wrote to '{}'", p);
        } else {
            println!("Error writing to {}", p);
        }
        writeln!(summary, "* [{0}](utils/{0}.md)", name)?;
    }
    Ok(())
}

struct MDWriter<'a, 'b> {
    w: Box<dyn Write>,
    command: Command,
    name: &'a str,
    tldr_zip: &'b mut Option<ZipArchive<File>>,
    utils_per_platform: &'b HashMap<&'b str, Vec<String>>,
}

impl<'a, 'b> MDWriter<'a, 'b> {
    fn markdown(&mut self) -> io::Result<()> {
        write!(self.w, "# {}\n\n", self.name)?;
        self.additional()?;
        self.usage()?;
        self.description()?;
        self.options()?;
        self.examples()
    }

    fn additional(&mut self) -> io::Result<()> {
        writeln!(self.w, "
")?;
        self.platforms()?;
        self.version()?;
        writeln!(self.w, "
")
    }

    fn platforms(&mut self) -> io::Result<()> {
        writeln!(self.w, "
")?;
        for (feature, icon) in [
            ("linux", "linux"),
            // freebsd is disabled for now because mdbook does not use font-awesome 5 yet.
            // ("unix", "freebsd"),
            ("macos", "apple"),
            ("windows", "windows"),
        ] {
            if self.name.contains("sum")
                || self.utils_per_platform[feature]
                    .iter()
                    .any(|u| u == self.name)
            {
                writeln!(self.w, "", icon)?;
            }
        }
        writeln!(self.w, "
")?;

        Ok(())
    }

    fn version(&mut self) -> io::Result<()> {
        writeln!(
            self.w,
            "
v{}
",
            self.command.render_version().split_once(' ').unwrap().1
        )
    }

    fn usage(&mut self) -> io::Result<()> {
        writeln!(self.w, "\n```")?;
        let mut usage: String = self
            .command
            .render_usage()
            .to_string()
            .lines()
            .map(|l| l.strip_prefix("Usage:").unwrap_or(l))
            .map(|l| l.trim())
            .filter(|l| !l.is_empty())
            .collect::<Vec<_>>()
            .join("\n");
        usage = usage
            .to_string()
            .replace(uucore::execution_phrase(), self.name);
        writeln!(self.w, "{}", usage)?;
        writeln!(self.w, "```")
    }

    fn description(&mut self) -> io::Result<()> {
        if let Some(about) = self
            .command
            .get_long_about()
            .or_else(|| self.command.get_about())
        {
            writeln!(self.w, "{}", about)
        } else {
            Ok(())
        }
    }

    fn examples(&mut self) -> io::Result<()> {
        if let Some(zip) = self.tldr_zip {
            let content = if let Some(f) =
                get_zip_content(zip, &format!("pages/common/{}.md", self.name))
            {
                f
            } else if let Some(f) = get_zip_content(zip, &format!("pages/linux/{}.md", self.name)) {
                f
            } else {
                return Ok(());
            };

            writeln!(self.w, "## Examples")?;
            writeln!(self.w)?;
            for line in content.lines().skip_while(|l| !l.starts_with('-')) {
                if let Some(l) = line.strip_prefix("- ") {
                    writeln!(self.w, "{}", l)?;
                } else if line.starts_with('`') {
                    writeln!(self.w, "```shell\n{}\n```", line.trim_matches('`'))?;
                } else if line.is_empty() {
                    writeln!(self.w)?;
                } else {
                    println!("Not sure what to do with this line:");
                    println!("{}", line);
                }
            }
            writeln!(self.w)?;
            writeln!(
                self.w,
                "> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
            )?;
            writeln!(self.w, ">")?;
            writeln!(
                self.w,
                "> Please note that, as uutils is a work in progress, some examples might fail."
            )?;
        }
        Ok(())
    }

    fn options(&mut self) -> io::Result<()> {
        writeln!(self.w, "
Options
")?;
        write!(self.w, "
")?;
        for arg in self.command.get_arguments() {
            write!(self.w, "
")?;
            let mut first = true;
            for l in arg.get_long_and_visible_aliases().unwrap_or_default() {
                if !first {
                    write!(self.w, ", ")?;
                } else {
                    first = false;
                }
                write!(self.w, "")?;
                write!(self.w, "--{}", l)?;
                if let Some(names) = arg.get_value_names() {
                    write!(
                        self.w,
                        "={}",
                        names
                            .iter()
                            .map(|x| format!("<{}>", x))
                            .collect::<Vec<_>>()
                            .join(" ")
                    )?;
                }
                write!(self.w, "")?;
            }
            for s in arg.get_short_and_visible_aliases().unwrap_or_default() {
                if !first {
                    write!(self.w, ", ")?;
                } else {
                    first = false;
                }
                write!(self.w, "")?;
                write!(self.w, "-{}", s)?;
                if let Some(names) = arg.get_value_names() {
                    write!(
                        self.w,
                        " {}",
                        names
                            .iter()
                            .map(|x| format!("<{}>", x))
                            .collect::<Vec<_>>()
                            .join(" ")
                    )?;
                }
                write!(self.w, "")?;
            }
            writeln!(self.w, "
")?;
            writeln!(
                self.w,
                "
\n\n{}\n\n
",
                arg.get_help()
                    .unwrap_or_default()
                    .to_string()
                    .replace('\n', "
")
            )?;
        }
        writeln!(self.w, "
\n")
    }
}

fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Option<String> {
    let mut s = String::new();
    archive.by_name(name).ok()?.read_to_string(&mut s).unwrap();
    Some(s)
}
<|endoftext|>


<commit_before>use proc_macro2::TokenStream;

use syn::DeriveInput;
use syn::spanned::Spanned;
use syn::parse::Error;
use quote::quote;

use default_attr::{DefaultAttr, ConversionStrategy};
use util::find_only;

pub fn impl_my_derive(input: &DeriveInput) -> Result<TokenStream, Error> {
    let name = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let (default_expr, doc) = match input.data {
        syn::Data::Struct(ref body) => {
            let (body_assignment, doc) = default_body_tt(&body.fields)?;
            (quote! {
                #name #body_assignment
            }, format!("Return `{}{}`", name, doc))
        }
        syn::Data::Enum(ref body) => {
            let default_variant = find_only(body.variants.iter(), |variant| {
                if let Some(meta) = DefaultAttr::find_in_attributes(&variant.attrs)? {
                    if meta.code.is_none() {
                        Ok(true)
                    } else {
                        Err(Error::new(meta.code.span(), "Attribute #[default] on variants should have no value"))
                    }
                } else {
                    Ok(false)
                }
            })?.ok_or_else(|| Error::new(input.span(), "No default variant"))?;
            let default_variant_name = &default_variant.ident;
            let (body_assignment, doc) = default_body_tt(&default_variant.fields)?;
            (quote! {
                #name :: #default_variant_name #body_assignment
            }, format!("Return `{}::{}{}`", name, default_variant_name, doc))
        }
        syn::Data::Union(_) => {
            panic!()
        }
    };
    Ok(quote! {
        impl #impl_generics Default for #name #ty_generics #where_clause {
            #[doc = #doc]
            fn default() -> Self {
                #default_expr
            }
        }
    })
}

/// Return a token-tree for the default "body" - the part after the name that contains the values.
/// That is, the `{ ... }` part for structs, the `(...)` part for tuples, and nothing for units.
fn default_body_tt(body: &syn::Fields) -> Result<(TokenStream, String), Error> {
    let mut doc = String::new();
    use std::fmt::Write;
    let body_tt = match body {
        &syn::Fields::Named(ref fields) => {
            doc.push_str(" {");
            let result = {
                let field_assignments = fields.named.iter().map(|field| {
                    let field_name = field.ident.as_ref();
                    let (default_value, default_doc) = field_default_expr_and_doc(field)?;
                    write!(&mut doc, "\n    {}: {},", field_name.expect("field value in struct is empty"), default_doc).unwrap();
                    // let default_value = default_value.into_token_stream();
                    Ok(quote! { #field_name : #default_value })
                }).collect::<Result<Vec<_>, Error>>()?;
                quote!{
                    {
                        #( #field_assignments ),*
                    }
                }
            };
            if (&mut doc).ends_with(",") {
                doc.pop();
                doc.push('\n');
            };
            doc.push('}');
            result
        }
        &syn::Fields::Unnamed(ref fields) => {
            doc.push('(');
            let result = {
                let field_assignments = fields.unnamed.iter().map(|field| {
                    let (default_value, default_doc) = field_default_expr_and_doc(field)?;
                    write!(&mut doc, "{}, ", default_doc).unwrap();
                    Ok(default_value)
                }).collect::<Result<Vec<TokenStream>, Error>>()?;
                quote! {
                    (
                        #( #field_assignments ),*
                    )
                }
            };
            if (&mut doc).ends_with(", ") {
                doc.pop();
                doc.pop();
            };
            doc.push(')');
            result
        }
        &syn::Fields::Unit => quote!{},
    };
    Ok((body_tt, doc))
}

/// Return a default expression for a field based on it's `#[default = "..."]` attribute. Panic
/// if there is more than one, of if there is a `#[default]` attribute without value.
fn field_default_expr_and_doc(field: &syn::Field) -> Result<(TokenStream, String), Error> {
    if let Some(default_attr) = DefaultAttr::find_in_attributes(&field.attrs)? {
        let conversion_strategy = default_attr.conversion_strategy();
        let field_value = default_attr.code.ok_or_else(|| {
            Error::new(field.span(), "Expected #[default = ...] or #[default(...)]")})?;

        let field_value = match conversion_strategy {
            ConversionStrategy::NoConversion => field_value,
            ConversionStrategy::Into => quote!((#field_value).into()),
        };

        let field_doc = format!("{}", field_value);
        Ok((field_value, field_doc))
    } else {
        Ok((quote! {
            Default::default()
        }, "Default::default()".to_owned()))
    }
}
<commit_msg>Add automatically_derived attr<commit_after>use proc_macro2::TokenStream;

use syn::DeriveInput;
use syn::spanned::Spanned;
use syn::parse::Error;
use quote::quote;

use default_attr::{DefaultAttr, ConversionStrategy};
use util::find_only;

pub fn impl_my_derive(input: &DeriveInput) -> Result<TokenStream, Error> {
    let name = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let (default_expr, doc) = match input.data {
        syn::Data::Struct(ref body) => {
            let (body_assignment, doc) = default_body_tt(&body.fields)?;
            (quote! {
                #name #body_assignment
            }, format!("Return `{}{}`", name, doc))
        }
        syn::Data::Enum(ref body) => {
            let default_variant = find_only(body.variants.iter(), |variant| {
                if let Some(meta) = DefaultAttr::find_in_attributes(&variant.attrs)? {
                    if meta.code.is_none() {
                        Ok(true)
                    } else {
                        Err(Error::new(meta.code.span(), "Attribute #[default] on variants should have no value"))
                    }
                } else {
                    Ok(false)
                }
            })?.ok_or_else(|| Error::new(input.span(), "No default variant"))?;
            let default_variant_name = &default_variant.ident;
            let (body_assignment, doc) = default_body_tt(&default_variant.fields)?;
            (quote! {
                #name :: #default_variant_name #body_assignment
            }, format!("Return `{}::{}{}`", name, default_variant_name, doc))
        }
        syn::Data::Union(_) => {
            panic!()
        }
    };
    Ok(quote! {
        #[automatically_derived]
        impl #impl_generics Default for #name #ty_generics #where_clause {
            #[doc = #doc]
            fn default() -> Self {
                #default_expr
            }
        }
    })
}

/// Return a token-tree for the default "body" - the part after the name that contains the values.
/// That is, the `{ ... }` part for structs, the `(...)` part for tuples, and nothing for units.
fn default_body_tt(body: &syn::Fields) -> Result<(TokenStream, String), Error> {
    let mut doc = String::new();
    use std::fmt::Write;
    let body_tt = match body {
        &syn::Fields::Named(ref fields) => {
            doc.push_str(" {");
            let result = {
                let field_assignments = fields.named.iter().map(|field| {
                    let field_name = field.ident.as_ref();
                    let (default_value, default_doc) = field_default_expr_and_doc(field)?;
                    write!(&mut doc, "\n    {}: {},", field_name.expect("field value in struct is empty"), default_doc).unwrap();
                    // let default_value = default_value.into_token_stream();
                    Ok(quote! { #field_name : #default_value })
                }).collect::<Result<Vec<_>, Error>>()?;
                quote!{
                    {
                        #( #field_assignments ),*
                    }
                }
            };
            if (&mut doc).ends_with(",") {
                doc.pop();
                doc.push('\n');
            };
            doc.push('}');
            result
        }
        &syn::Fields::Unnamed(ref fields) => {
            doc.push('(');
            let result = {
                let field_assignments = fields.unnamed.iter().map(|field| {
                    let (default_value, default_doc) = field_default_expr_and_doc(field)?;
                    write!(&mut doc, "{}, ", default_doc).unwrap();
                    Ok(default_value)
                }).collect::<Result<Vec<TokenStream>, Error>>()?;
                quote! {
                    (
                        #( #field_assignments ),*
                    )
                }
            };
            if (&mut doc).ends_with(", ") {
                doc.pop();
                doc.pop();
            };
            doc.push(')');
            result
        }
        &syn::Fields::Unit => quote!{},
    };
    Ok((body_tt, doc))
}

/// Return a default expression for a field based on it's `#[default = "..."]` attribute. Panic
/// if there is more than one, of if there is a `#[default]` attribute without value.
fn field_default_expr_and_doc(field: &syn::Field) -> Result<(TokenStream, String), Error> {
    if let Some(default_attr) = DefaultAttr::find_in_attributes(&field.attrs)? {
        let conversion_strategy = default_attr.conversion_strategy();
        let field_value = default_attr.code.ok_or_else(|| {
            Error::new(field.span(), "Expected #[default = ...] or #[default(...)]")})?;

        let field_value = match conversion_strategy {
            ConversionStrategy::NoConversion => field_value,
            ConversionStrategy::Into => quote!((#field_value).into()),
        };

        let field_doc = format!("{}", field_value);
        Ok((field_value, field_doc))
    } else {
        Ok((quote! {
            Default::default()
        }, "Default::default()".to_owned()))
    }
}
<|endoftext|>