<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::exec;
use crate::exit_codes::ExitCode;
use crate::fshelper;
use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH};
use crate::output;

use std::borrow::Cow;
use std::error::Error;
use std::ffi::OsStr;
use std::io;
use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time;

use ignore::overrides::OverrideBuilder;
use ignore::{self, WalkBuilder};
use regex::bytes::Regex;

/// The receiver thread can either be buffering results or directly streaming to the console.
enum ReceiverMode {
    /// Receiver is still buffering in order to sort the results, if the search finishes fast
    /// enough.
    Buffering,

    /// Receiver is directly printing results to the output.
    Streaming,
}

/// The Worker threads can result in a valid entry having PathBuf or an error.
pub enum WorkerResult {
    Entry(PathBuf),
    Error(ignore::Error),
}

/// Recursively scan the given search path for files / pathnames matching the pattern.
///
/// If the `--exec` argument was supplied, this will create a thread pool for executing
/// jobs in parallel from a given command line and the discovered paths. Otherwise, each
/// path will simply be written to standard output.
pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) -> ExitCode {
    let mut path_iter = path_vec.iter();
    let first_path_buf = path_iter
        .next()
        .expect("Error: Path vector can not be empty");
    let (tx, rx) = channel();

    let mut override_builder = OverrideBuilder::new(first_path_buf.as_path());

    for pattern in &config.exclude_patterns {
        let res = override_builder.add(pattern);
        if res.is_err() {
            print_error_and_exit!("Malformed exclude pattern '{}'", pattern);
        }
    }
    let overrides = override_builder.build().unwrap_or_else(|_| {
        print_error_and_exit!("Mismatch in exclude patterns");
    });

    let mut walker = WalkBuilder::new(first_path_buf.as_path());
    walker
        .hidden(config.ignore_hidden)
        .ignore(config.read_fdignore)
        .parents(config.read_fdignore || config.read_vcsignore)
        .git_ignore(config.read_vcsignore)
        .git_global(config.read_vcsignore)
        .git_exclude(config.read_vcsignore)
        .overrides(overrides)
        .follow_links(config.follow_links)
        // No need to check for supported platforms, option is unavailable on unsupported ones
        .same_file_system(config.one_file_system)
        .max_depth(config.max_depth);

    if config.read_fdignore {
        walker.add_custom_ignore_filename(".fdignore");
    }

    for ignore_file in &config.ignore_files {
        let result = walker.add_ignore(ignore_file);
        match result {
            Some(ignore::Error::Partial(_)) => (),
            Some(err) => {
                print_error!(
                    "{}",
                    format!(
                        "Malformed pattern in custom ignore file '{}': {}.",
                        ignore_file.to_string_lossy(),
                        err.description()
                    )
                );
            }
            None => (),
        }
    }

    for path_entry in path_iter {
        walker.add(path_entry.as_path());
    }

    let parallel_walker = walker.threads(config.threads).build_parallel();

    let wants_to_quit = Arc::new(AtomicBool::new(false));
    if config.ls_colors.is_some() && config.command.is_none() {
        let wq = Arc::clone(&wants_to_quit);
        ctrlc::set_handler(move || {
            if wq.load(Ordering::Relaxed) {
                // Ctrl-C has been pressed twice, exit NOW
                process::exit(ExitCode::KilledBySigint.into());
            } else {
                wq.store(true, Ordering::Relaxed);
            }
        })
        .unwrap();
    }

    // Spawn the thread that receives all results through the channel.
    let receiver_thread = spawn_receiver(&config, &wants_to_quit, rx);

    // Spawn the sender threads.
    spawn_senders(&config, &wants_to_quit, pattern, parallel_walker, tx);

    // Wait for the receiver thread to print out all results.
    let exit_code = receiver_thread.join().unwrap();

    if wants_to_quit.load(Ordering::Relaxed) {
        process::exit(ExitCode::KilledBySigint.into());
    }

    exit_code
}

fn spawn_receiver(
    config: &Arc<FdOptions>,
    wants_to_quit: &Arc<AtomicBool>,
    rx: Receiver<WorkerResult>,
) -> thread::JoinHandle<ExitCode> {
    let config = Arc::clone(config);
    let wants_to_quit = Arc::clone(wants_to_quit);

    let show_filesystem_errors = config.show_filesystem_errors;
    let threads = config.threads;

    thread::spawn(move || {
        // This will be set to `Some` if the `--exec` argument was supplied.
        if let Some(ref cmd) = config.command {
            if cmd.in_batch_mode() {
                exec::batch(rx, cmd, show_filesystem_errors)
            } else {
                let shared_rx = Arc::new(Mutex::new(rx));

                let out_perm = Arc::new(Mutex::new(()));

                // Each spawned job will store it's thread handle in here.
                let mut handles = Vec::with_capacity(threads);
                for _ in 0..threads {
                    let rx = Arc::clone(&shared_rx);
                    let cmd = Arc::clone(cmd);
                    let out_perm = Arc::clone(&out_perm);

                    // Spawn a job thread that will listen for and execute inputs.
                    let handle =
                        thread::spawn(move || exec::job(rx, cmd, out_perm, show_filesystem_errors));

                    // Push the handle of the spawned thread into the vector for later joining.
                    handles.push(handle);
                }

                // Wait for all threads to exit before exiting the program.
                for h in handles {
                    h.join().unwrap();
                }

                ExitCode::Success
            }
        } else {
            let start = time::Instant::now();

            let mut buffer = vec![];

            // Start in buffering mode
            let mut mode = ReceiverMode::Buffering;

            // Maximum time to wait before we start streaming to the console.
            let max_buffer_time = config
                .max_buffer_time
                .unwrap_or_else(|| time::Duration::from_millis(100));

            let stdout = io::stdout();
            let mut stdout = stdout.lock();

            for worker_result in rx {
                match worker_result {
                    WorkerResult::Entry(value) => {
                        match mode {
                            ReceiverMode::Buffering => {
                                buffer.push(value);

                                // Have we reached the maximum buffer size or maximum buffering time?
                                if buffer.len() > MAX_BUFFER_LENGTH
                                    || time::Instant::now() - start > max_buffer_time
                                {
                                    // Flush the buffer
                                    for v in &buffer {
                                        output::print_entry(
                                            &mut stdout,
                                            v,
                                            &config,
                                            &wants_to_quit,
                                        );
                                    }
                                    buffer.clear();

                                    // Start streaming
                                    mode = ReceiverMode::Streaming;
                                }
                            }
                            ReceiverMode::Streaming => {
                                output::print_entry(&mut stdout, &value, &config, &wants_to_quit);
                            }
                        }
                    }
                    WorkerResult::Error(err) => {
                        if show_filesystem_errors {
                            print_error!("{}", err);
                        }
                    }
                }
            }

            // If we have finished fast enough (faster than max_buffer_time), we haven't streamed
            // anything to the console, yet. In this case, sort the results and print them:
            if !buffer.is_empty() {
                buffer.sort();
                for value in buffer {
                    output::print_entry(&mut stdout, &value, &config, &wants_to_quit);
                }
            }

            ExitCode::Success
        }
    })
}

fn spawn_senders(
    config: &Arc<FdOptions>,
    wants_to_quit: &Arc<AtomicBool>,
    pattern: Arc<Regex>,
    parallel_walker: ignore::WalkParallel,
    tx: Sender<WorkerResult>,
) {
    parallel_walker.run(|| {
        let config = Arc::clone(config);
        let pattern = Arc::clone(&pattern);
        let tx_thread = tx.clone();
        let wants_to_quit = Arc::clone(wants_to_quit);

        Box::new(move |entry_o| {
            if wants_to_quit.load(Ordering::Relaxed) {
                return ignore::WalkState::Quit;
            }

            let entry = match entry_o {
                Ok(e) => e,
                Err(err) => {
                    tx_thread.send(WorkerResult::Error(err)).unwrap();
                    return ignore::WalkState::Continue;
                }
            };

            if entry.depth() == 0 {
                return ignore::WalkState::Continue;
            }

            // Check the name first, since it doesn't require metadata
            let entry_path = entry.path();

            let search_str: Cow<OsStr> = if config.search_full_path {
                match fshelper::path_absolute_form(entry_path) {
                    Ok(path_abs_buf) => Cow::Owned(path_abs_buf.as_os_str().to_os_string()),
                    Err(_) => {
                        print_error_and_exit!("Unable to retrieve absolute path.");
                    }
                }
            } else {
                match entry_path.file_name() {
                    Some(filename) => Cow::Borrowed(filename),
                    None => unreachable!(
                        "Encountered file system entry without a file name. This should only \
                         happen for paths like 'foo/bar/..' or '/' which are not supposed to \
                         appear in a file system traversal."
                    ),
                }
            };

            if !pattern.is_match(&osstr_to_bytes(search_str.as_ref())) {
                return ignore::WalkState::Continue;
            }

            // Filter out unwanted extensions.
            if let Some(ref exts_regex) = config.extensions {
                if let Some(path_str) = entry_path.file_name() {
                    if !exts_regex.is_match(&osstr_to_bytes(path_str)) {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted file types.
            if let Some(ref file_types) = config.file_types {
                if let Some(ref entry_type) = entry.file_type() {
                    if (!file_types.files && entry_type.is_file())
                        || (!file_types.directories && entry_type.is_dir())
                        || (!file_types.symlinks && entry_type.is_symlink())
                        || (file_types.executables_only
                            && !entry
                                .metadata()
                                .map(|m| fshelper::is_executable(&m))
                                .unwrap_or(false))
                        || (file_types.empty_only && !fshelper::is_empty(&entry))
                        || !(entry_type.is_file() || entry_type.is_dir() || entry_type.is_symlink())
                    {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted sizes if it is a file and we have been given size constraints.
            if !config.size_constraints.is_empty() {
                if entry_path.is_file() {
                    if let Ok(metadata) = entry_path.metadata() {
                        let file_size = metadata.len();
                        if config
                            .size_constraints
                            .iter()
                            .any(|sc| !sc.is_within(file_size))
                        {
                            return ignore::WalkState::Continue;
                        }
                    } else {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted modification times
            if !config.time_constraints.is_empty() {
                let mut matched = false;
                if let Ok(metadata) = entry_path.metadata() {
                    if let Ok(modified) = metadata.modified() {
                        matched = config
                            .time_constraints
                            .iter()
                            .all(|tf| tf.applies_to(&modified));
                    }
                }
                if !matched {
                    return ignore::WalkState::Continue;
                }
            }

            let send_result = tx_thread
                .send(WorkerResult::Entry(entry_path.to_owned()));

            if !send_result.is_ok() {
                return ignore::WalkState::Quit;
            }

            ignore::WalkState::Continue
        })
    });
}
<commit_msg>Formatting<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::exec;
use crate::exit_codes::ExitCode;
use crate::fshelper;
use crate::internal::{opts::FdOptions, osstr_to_bytes, MAX_BUFFER_LENGTH};
use crate::output;

use std::borrow::Cow;
use std::error::Error;
use std::ffi::OsStr;
use std::io;
use std::path::PathBuf;
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time;

use ignore::overrides::OverrideBuilder;
use ignore::{self, WalkBuilder};
use regex::bytes::Regex;

/// The receiver thread can either be buffering results or directly streaming to the console.
enum ReceiverMode {
    /// Receiver is still buffering in order to sort the results, if the search finishes fast
    /// enough.
    Buffering,

    /// Receiver is directly printing results to the output.
    Streaming,
}

/// The Worker threads can result in a valid entry having PathBuf or an error.
pub enum WorkerResult {
    Entry(PathBuf),
    Error(ignore::Error),
}

/// Recursively scan the given search path for files / pathnames matching the pattern.
///
/// If the `--exec` argument was supplied, this will create a thread pool for executing
/// jobs in parallel from a given command line and the discovered paths. Otherwise, each
/// path will simply be written to standard output.
pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) -> ExitCode {
    let mut path_iter = path_vec.iter();
    let first_path_buf = path_iter
        .next()
        .expect("Error: Path vector can not be empty");
    let (tx, rx) = channel();

    let mut override_builder = OverrideBuilder::new(first_path_buf.as_path());

    for pattern in &config.exclude_patterns {
        let res = override_builder.add(pattern);
        if res.is_err() {
            print_error_and_exit!("Malformed exclude pattern '{}'", pattern);
        }
    }
    let overrides = override_builder.build().unwrap_or_else(|_| {
        print_error_and_exit!("Mismatch in exclude patterns");
    });

    let mut walker = WalkBuilder::new(first_path_buf.as_path());
    walker
        .hidden(config.ignore_hidden)
        .ignore(config.read_fdignore)
        .parents(config.read_fdignore || config.read_vcsignore)
        .git_ignore(config.read_vcsignore)
        .git_global(config.read_vcsignore)
        .git_exclude(config.read_vcsignore)
        .overrides(overrides)
        .follow_links(config.follow_links)
        // No need to check for supported platforms, option is unavailable on unsupported ones
        .same_file_system(config.one_file_system)
        .max_depth(config.max_depth);

    if config.read_fdignore {
        walker.add_custom_ignore_filename(".fdignore");
    }

    for ignore_file in &config.ignore_files {
        let result = walker.add_ignore(ignore_file);
        match result {
            Some(ignore::Error::Partial(_)) => (),
            Some(err) => {
                print_error!(
                    "{}",
                    format!(
                        "Malformed pattern in custom ignore file '{}': {}.",
                        ignore_file.to_string_lossy(),
                        err.description()
                    )
                );
            }
            None => (),
        }
    }

    for path_entry in path_iter {
        walker.add(path_entry.as_path());
    }

    let parallel_walker = walker.threads(config.threads).build_parallel();

    let wants_to_quit = Arc::new(AtomicBool::new(false));
    if config.ls_colors.is_some() && config.command.is_none() {
        let wq = Arc::clone(&wants_to_quit);
        ctrlc::set_handler(move || {
            if wq.load(Ordering::Relaxed) {
                // Ctrl-C has been pressed twice, exit NOW
                process::exit(ExitCode::KilledBySigint.into());
            } else {
                wq.store(true, Ordering::Relaxed);
            }
        })
        .unwrap();
    }

    // Spawn the thread that receives all results through the channel.
    let receiver_thread = spawn_receiver(&config, &wants_to_quit, rx);

    // Spawn the sender threads.
    spawn_senders(&config, &wants_to_quit, pattern, parallel_walker, tx);

    // Wait for the receiver thread to print out all results.
    let exit_code = receiver_thread.join().unwrap();

    if wants_to_quit.load(Ordering::Relaxed) {
        process::exit(ExitCode::KilledBySigint.into());
    }

    exit_code
}

fn spawn_receiver(
    config: &Arc<FdOptions>,
    wants_to_quit: &Arc<AtomicBool>,
    rx: Receiver<WorkerResult>,
) -> thread::JoinHandle<ExitCode> {
    let config = Arc::clone(config);
    let wants_to_quit = Arc::clone(wants_to_quit);

    let show_filesystem_errors = config.show_filesystem_errors;
    let threads = config.threads;

    thread::spawn(move || {
        // This will be set to `Some` if the `--exec` argument was supplied.
        if let Some(ref cmd) = config.command {
            if cmd.in_batch_mode() {
                exec::batch(rx, cmd, show_filesystem_errors)
            } else {
                let shared_rx = Arc::new(Mutex::new(rx));

                let out_perm = Arc::new(Mutex::new(()));

                // Each spawned job will store it's thread handle in here.
                let mut handles = Vec::with_capacity(threads);
                for _ in 0..threads {
                    let rx = Arc::clone(&shared_rx);
                    let cmd = Arc::clone(cmd);
                    let out_perm = Arc::clone(&out_perm);

                    // Spawn a job thread that will listen for and execute inputs.
                    let handle =
                        thread::spawn(move || exec::job(rx, cmd, out_perm, show_filesystem_errors));

                    // Push the handle of the spawned thread into the vector for later joining.
                    handles.push(handle);
                }

                // Wait for all threads to exit before exiting the program.
                for h in handles {
                    h.join().unwrap();
                }

                ExitCode::Success
            }
        } else {
            let start = time::Instant::now();

            let mut buffer = vec![];

            // Start in buffering mode
            let mut mode = ReceiverMode::Buffering;

            // Maximum time to wait before we start streaming to the console.
            let max_buffer_time = config
                .max_buffer_time
                .unwrap_or_else(|| time::Duration::from_millis(100));

            let stdout = io::stdout();
            let mut stdout = stdout.lock();

            for worker_result in rx {
                match worker_result {
                    WorkerResult::Entry(value) => {
                        match mode {
                            ReceiverMode::Buffering => {
                                buffer.push(value);

                                // Have we reached the maximum buffer size or maximum buffering time?
                                if buffer.len() > MAX_BUFFER_LENGTH
                                    || time::Instant::now() - start > max_buffer_time
                                {
                                    // Flush the buffer
                                    for v in &buffer {
                                        output::print_entry(
                                            &mut stdout,
                                            v,
                                            &config,
                                            &wants_to_quit,
                                        );
                                    }
                                    buffer.clear();

                                    // Start streaming
                                    mode = ReceiverMode::Streaming;
                                }
                            }
                            ReceiverMode::Streaming => {
                                output::print_entry(&mut stdout, &value, &config, &wants_to_quit);
                            }
                        }
                    }
                    WorkerResult::Error(err) => {
                        if show_filesystem_errors {
                            print_error!("{}", err);
                        }
                    }
                }
            }

            // If we have finished fast enough (faster than max_buffer_time), we haven't streamed
            // anything to the console, yet. In this case, sort the results and print them:
            if !buffer.is_empty() {
                buffer.sort();
                for value in buffer {
                    output::print_entry(&mut stdout, &value, &config, &wants_to_quit);
                }
            }

            ExitCode::Success
        }
    })
}

fn spawn_senders(
    config: &Arc<FdOptions>,
    wants_to_quit: &Arc<AtomicBool>,
    pattern: Arc<Regex>,
    parallel_walker: ignore::WalkParallel,
    tx: Sender<WorkerResult>,
) {
    parallel_walker.run(|| {
        let config = Arc::clone(config);
        let pattern = Arc::clone(&pattern);
        let tx_thread = tx.clone();
        let wants_to_quit = Arc::clone(wants_to_quit);

        Box::new(move |entry_o| {
            if wants_to_quit.load(Ordering::Relaxed) {
                return ignore::WalkState::Quit;
            }

            let entry = match entry_o {
                Ok(e) => e,
                Err(err) => {
                    tx_thread.send(WorkerResult::Error(err)).unwrap();
                    return ignore::WalkState::Continue;
                }
            };

            if entry.depth() == 0 {
                return ignore::WalkState::Continue;
            }

            // Check the name first, since it doesn't require metadata
            let entry_path = entry.path();

            let search_str: Cow<OsStr> = if config.search_full_path {
                match fshelper::path_absolute_form(entry_path) {
                    Ok(path_abs_buf) => Cow::Owned(path_abs_buf.as_os_str().to_os_string()),
                    Err(_) => {
                        print_error_and_exit!("Unable to retrieve absolute path.");
                    }
                }
            } else {
                match entry_path.file_name() {
                    Some(filename) => Cow::Borrowed(filename),
                    None => unreachable!(
                        "Encountered file system entry without a file name. This should only \
                         happen for paths like 'foo/bar/..' or '/' which are not supposed to \
                         appear in a file system traversal."
                    ),
                }
            };

            if !pattern.is_match(&osstr_to_bytes(search_str.as_ref())) {
                return ignore::WalkState::Continue;
            }

            // Filter out unwanted extensions.
            if let Some(ref exts_regex) = config.extensions {
                if let Some(path_str) = entry_path.file_name() {
                    if !exts_regex.is_match(&osstr_to_bytes(path_str)) {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted file types.
            if let Some(ref file_types) = config.file_types {
                if let Some(ref entry_type) = entry.file_type() {
                    if (!file_types.files && entry_type.is_file())
                        || (!file_types.directories && entry_type.is_dir())
                        || (!file_types.symlinks && entry_type.is_symlink())
                        || (file_types.executables_only
                            && !entry
                                .metadata()
                                .map(|m| fshelper::is_executable(&m))
                                .unwrap_or(false))
                        || (file_types.empty_only && !fshelper::is_empty(&entry))
                        || !(entry_type.is_file() || entry_type.is_dir() || entry_type.is_symlink())
                    {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted sizes if it is a file and we have been given size constraints.
            if !config.size_constraints.is_empty() {
                if entry_path.is_file() {
                    if let Ok(metadata) = entry_path.metadata() {
                        let file_size = metadata.len();
                        if config
                            .size_constraints
                            .iter()
                            .any(|sc| !sc.is_within(file_size))
                        {
                            return ignore::WalkState::Continue;
                        }
                    } else {
                        return ignore::WalkState::Continue;
                    }
                } else {
                    return ignore::WalkState::Continue;
                }
            }

            // Filter out unwanted modification times
            if !config.time_constraints.is_empty() {
                let mut matched = false;
                if let Ok(metadata) = entry_path.metadata() {
                    if let Ok(modified) = metadata.modified() {
                        matched = config
                            .time_constraints
                            .iter()
                            .all(|tf| tf.applies_to(&modified));
                    }
                }
                if !matched {
                    return ignore::WalkState::Continue;
                }
            }

            let send_result = tx_thread.send(WorkerResult::Entry(entry_path.to_owned()));

            if !send_result.is_ok() {
                return ignore::WalkState::Quit;
            }

            ignore::WalkState::Continue
        })
    });
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Make sure the destructor is run for unit-like structs.
// xfail-fast

use std::task;

struct Foo;

impl Drop for Foo {
    fn drop(&mut self) {
        fail!("This failure should happen.");
    }
}

fn main() {
    let x = do task::try {
        let _b = Foo;
    };
    assert_eq!(x, Err(()));
}
<commit_msg>testsuite: Un-xfail unit-like-struct-drop-run on Windows<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Make sure the destructor is run for unit-like structs.

use std::task;

struct Foo;

impl Drop for Foo {
    fn drop(&mut self) {
        fail!("This failure should happen.");
    }
}

pub fn main() {
    let x = do task::try {
        let _b = Foo;
    };
    assert_eq!(x, Err(()));
}
<|endoftext|>


<commit_before>use hir::HirDisplay;
use syntax::{
    ast::{self, AstNode, LetStmt, NameOwner},
    TextRange,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_explicit_type
//
// Specify type for a let binding.
//
// ```
// fn main() {
//     let x$0 = 92;
// }
// ```
// ->
// ```
// fn main() {
//     let x: i32 = 92;
// }
// ```
pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
    let module = ctx.sema.scope(let_stmt.syntax()).module()?;
    let expr = let_stmt.initializer()?;
    // Must be a binding
    let pat = match let_stmt.pat()? {
        ast::Pat::IdentPat(bind_pat) => bind_pat,
        _ => return None,
    };
    let pat_range = pat.syntax().text_range();
    // The binding must have a name
    let name = pat.name()?;
    let name_range = name.syntax().text_range();
    let stmt_range = let_stmt.syntax().text_range();
    let eq_range = let_stmt.eq_token()?.text_range();
    // Assist should only be applicable if cursor is between 'let' and '='
    let let_range = TextRange::new(stmt_range.start(), eq_range.start());
    let cursor_in_range = let_range.contains_range(ctx.frange.range);
    if !cursor_in_range {
        return None;
    }
    // Assist not applicable if the type has already been specified
    // and it has no placeholders
    let ascribed_ty = let_stmt.ty();
    if let Some(ty) = &ascribed_ty {
        if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
            return None;
        }
    }
    // Infer type
    let ty = ctx.sema.type_of_expr(&expr)?;

    if ty.contains_unknown() || ty.is_closure() {
        return None;
    }

    let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
    acc.add(
        AssistId("add_explicit_type", AssistKind::RefactorRewrite),
        format!("Insert explicit type `{}`", inferred_type),
        pat_range,
        |builder| match ascribed_ty {
            Some(ascribed_ty) => {
                builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
            }
            None => {
                builder.insert(name_range.end(), format!(": {}", inferred_type));
            }
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn add_explicit_type_target() {
        check_assist_target(add_explicit_type, "fn f() { let a$0 = 1; }", "a");
    }

    #[test]
    fn add_explicit_type_works_for_simple_expr() {
        check_assist(add_explicit_type, "fn f() { let a$0 = 1; }", "fn f() { let a: i32 = 1; }");
    }

    #[test]
    fn add_explicit_type_works_for_underscore() {
        check_assist(add_explicit_type, "fn f() { let a$0: _ = 1; }", "fn f() { let a: i32 = 1; }");
    }

    #[test]
    fn add_explicit_type_works_for_nested_underscore() {
        check_assist(
            add_explicit_type,
            r#"
            enum Option<T> {
                Some(T),
                None
            }

            fn f() {
                let a$0: Option<_> = Option::Some(1);
            }"#,
            r#"
            enum Option<T> {
                Some(T),
                None
            }

            fn f() {
                let a: Option<i32> = Option::Some(1);
            }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call() {
        check_assist(
            add_explicit_type,
            r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }",
            r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call_recursive() {
        check_assist(
            add_explicit_type,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_not_inferred() {
        check_assist_not_applicable(add_explicit_type, "fn f() { let a$0 = None; }");
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_already_specified() {
        check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: i32 = 1; }");
    }

    #[test]
    fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
        check_assist_not_applicable(add_explicit_type, "fn f() { let a$0: (i32, i32) = (3, 4); }");
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_after_equals() {
        check_assist_not_applicable(
            add_explicit_type,
            "fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}",
        )
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_before_let() {
        check_assist_not_applicable(
            add_explicit_type,
            "fn f() $0{let a = match 1 {2 => 3, 3 => 5};}",
        )
    }

    #[test]
    fn closure_parameters_are_not_added() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let multiply_by_two$0 = |i| i * 3;
    let six = multiply_by_two(2);
}"#,
        )
    }

    #[test]
    fn default_generics_should_not_be_added() {
        check_assist(
            add_explicit_type,
            r#"
struct Test<K, T = u8> {
    k: K,
    t: T,
}

fn main() {
    let test$0 = Test { t: 23u8, k: 33 };
}"#,
            r#"
struct Test<K, T = u8> {
    k: K,
    t: T,
}

fn main() {
    let test: Test<i32> = Test { t: 23u8, k: 33 };
}"#,
        );
    }
}
<commit_msg>Unify test style<commit_after>use hir::HirDisplay;
use syntax::{
    ast::{self, AstNode, LetStmt, NameOwner},
    TextRange,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_explicit_type
//
// Specify type for a let binding.
//
// ```
// fn main() {
//     let x$0 = 92;
// }
// ```
// ->
// ```
// fn main() {
//     let x: i32 = 92;
// }
// ```
pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
    let module = ctx.sema.scope(let_stmt.syntax()).module()?;
    let expr = let_stmt.initializer()?;
    // Must be a binding
    let pat = match let_stmt.pat()? {
        ast::Pat::IdentPat(bind_pat) => bind_pat,
        _ => return None,
    };
    let pat_range = pat.syntax().text_range();
    // The binding must have a name
    let name = pat.name()?;
    let name_range = name.syntax().text_range();

    // Assist should only be applicable if cursor is between 'let' and '='
    let cursor_in_range = {
        let stmt_range = let_stmt.syntax().text_range();
        let eq_range = let_stmt.eq_token()?.text_range();
        let let_range = TextRange::new(stmt_range.start(), eq_range.start());
        let_range.contains_range(ctx.frange.range)
    };
    if !cursor_in_range {
        cov_mark::hit!(add_explicit_type_not_applicable_if_cursor_after_equals);
        return None;
    }

    // Assist not applicable if the type has already been specified
    // and it has no placeholders
    let ascribed_ty = let_stmt.ty();
    if let Some(ty) = &ascribed_ty {
        if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
            cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
            return None;
        }
    }

    // Infer type
    let ty = ctx.sema.type_of_expr(&expr)?;
    if ty.contains_unknown() || ty.is_closure() {
        cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
        return None;
    }

    let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
    acc.add(
        AssistId("add_explicit_type", AssistKind::RefactorRewrite),
        format!("Insert explicit type `{}`", inferred_type),
        pat_range,
        |builder| match ascribed_ty {
            Some(ascribed_ty) => {
                builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
            }
            None => {
                builder.insert(name_range.end(), format!(": {}", inferred_type));
            }
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn add_explicit_type_target() {
        check_assist_target(add_explicit_type, r#"fn f() { let a$0 = 1; }"#, "a");
    }

    #[test]
    fn add_explicit_type_works_for_simple_expr() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0 = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_underscore() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0: _ = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_nested_underscore() {
        check_assist(
            add_explicit_type,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a$0: Option<_> = Option::Some(1);
}
"#,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a: Option<i32> = Option::Some(1);
}
"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call() {
        check_assist(
            add_explicit_type,
            r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }",
            r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call_recursive() {
        check_assist(
            add_explicit_type,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_not_inferred() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_already_specified() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_already_specified);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0: i32 = 1; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() { let a$0: (i32, i32) = (3, 4); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_after_equals() {
        cov_mark::check!(add_explicit_type_not_applicable_if_cursor_after_equals);
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_before_let() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() $0{let a = match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn closure_parameters_are_not_added() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let multiply_by_two$0 = |i| i * 3;
    let six = multiply_by_two(2);
}
"#,
        )
    }

    #[test]
    fn default_generics_should_not_be_added() {
        check_assist(
            add_explicit_type,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test$0 = Test { t: 23u8, k: 33 };
}
"#,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test: Test<i32> = Test { t: 23u8, k: 33 };
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>#![feature(fs_walk)]
#![feature(slice_patterns)]

extern crate rustc_serialize;
extern crate time;
extern crate eve;

use std::env;
use std::fs::{OpenOptions, walk_dir};
use std::io::prelude::*;
use rustc_serialize::json::{ToJson, Json};

use eve::server::*;
use eve::flow::*;
use eve::compiler::*;
use eve::value::*;

fn read_events(filename: &str) -> Vec<Event> {
    let mut events_string = String::new();
    {
        let mut events_file = OpenOptions::new().create(true).open(&filename).unwrap();
        events_file.read_to_string(&mut events_string).unwrap();
    }
    events_string.lines().map(|line|
        FromJson::from_json(&Json::from_str(&line).unwrap())
        ).collect()
}

fn write_events(filename: &str, events: &[Event]) {
    let mut new_events_file = OpenOptions::new().create(true).truncate(true).write(true).open(&filename).unwrap();
    for event in events.iter() {
        new_events_file.write_all(format!("{}", event.to_json()).as_bytes()).unwrap();
        new_events_file.write_all("\n".as_bytes()).unwrap();
    }
}

fn all_filenames() -> Vec<String> {
    let mut filenames = vec![];
    for entry in walk_dir("./test-inputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("./test-outputs").unwrap() {
        filenames.push(entry.unwrap().path().to_str().unwrap().to_owned());
    }
    for entry in walk_dir("../example data").unwrap() {
        let path = entry.unwrap().path();
        if path.extension().unwrap().to_str().unwrap() == "eve" {
            filenames.push(path.to_str().unwrap().to_owned());
        }
    }
    filenames
}

fn remove_view(view: &str) {
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_view, _)| change_view != view);
        }
        write_events(&filename[..], &events[..]);
    }
}

fn remove_row(view: &str, row: Vec<Value>) {
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            for &mut (ref change_view, ref mut change) in event.changes.iter_mut() {
                if change_view == view {
                    change.insert.retain(|insert_row| *insert_row != row)
                }
            }
        }
        write_events(&filename[..], &events[..]);
    }
}

fn reset_internal_views() {
    let compiler_schema = compiler_schema();
    let client_schema = client_schema();
    for filename in all_filenames() {
        let mut events = read_events(&filename[..]);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)|
                !compiler_schema.iter().chain(client_schema.iter()).any(|&(ref id, _)| change_id == id)
                );
        }
        write_events(&filename[..], &events[..]);
    }
}

fn compact(filename: &str) {
    let mut flow = Flow::new();
    for event in read_events(&filename[..]).into_iter() {
        flow.quiesce(event.changes);
    }
    // TODO session is blank which doesn't seem to matter because it is never used
    write_events(&filename[..], &[Event{changes: flow.as_changes(), commands: vec![]}]);
}

fn make_bug_test() {
    let events = read_events("./autosave");
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/bug-{}", time);
    let output_filename = format!("./test-outputs/bug-{}", time);
    write_events(&input_filename[..], &events[..]);
    write_events(&output_filename[..], &[]);
}

fn make_regression_test() {
    let mut flow = Flow::new();
    for event in read_events("./autosave").into_iter() {
        flow.quiesce(event.changes);
    }
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/regression-{}", time);
    let output_filename = format!("./test-outputs/regression-{}", time);
    write_events(&input_filename[..], &[Event{changes: flow.as_changes(), commands: vec![]}]);
    write_events(&output_filename[..],  &[Event{changes: flow.as_changes(), commands: vec![]}]);
}

#[test]
fn test_examples() {
    let inputs = walk_dir("./test-inputs").unwrap().collect::<Vec<_>>();
    let outputs = walk_dir("./test-outputs").unwrap().collect::<Vec<_>>();
    assert_eq!(inputs.len(), outputs.len());
    for (input_entry, output_entry) in inputs.into_iter().zip(outputs.into_iter()) {
        let input_filename = input_entry.unwrap().path().to_str().unwrap().to_owned();
        let output_filename = output_entry.unwrap().path().to_str().unwrap().to_owned();
        println!("Testing {:?} against {:?}", input_filename, output_filename);

        let mut input_flow = Flow::new();
        for event in read_events(&input_filename[..]).into_iter() {
            input_flow.quiesce(event.changes);
        }

        let mut output_flow = Flow::new();
        for event in read_events(&output_filename[..]).into_iter() {
            output_flow.change(event.changes);
        }

        let schema = schema();
        for output_cell in output_flow.outputs.iter() {
            let output = output_cell.borrow();
            // ignore internal views
            if !schema.iter().any(|&(ref id, _)| **id == *output.view) {
                let input = input_flow.get_output(&output.view[..]);
                assert_eq!((&output.view, &output.index), (&input.view, &input.index));
            }
        }
    }
}

#[allow(dead_code)]
fn main() {
    let args = env::args().collect::<Vec<String>>();
    let borrowed_args = args.iter().map(|s| &s[..]).collect::<Vec<&str>>();
    match &borrowed_args[..] {
        [_, "remove_view", view] => remove_view(view),
        [_, "remove_row", view, row] => remove_row(view, FromJson::from_json(&Json::from_str(&row).unwrap())),
        [_, "reset_internal_views"] => reset_internal_views(),
        [_, "compact", filename] => compact(filename),
        [_, "make_bug_test"] => make_bug_test(),
        [_, "make_regression_test"] => make_regression_test(),
        other => panic!("Bad arguments (look at src/bin/migrate.rs for correct usage): {:?}", &other[1..]),
    }
}
<commit_msg>Clean up file handling for tests. Add a test that runs examples.<commit_after>#![feature(fs_walk)]
#![feature(slice_patterns)]

extern crate rustc_serialize;
extern crate time;
extern crate eve;

use std::env;
use std::fs::{OpenOptions, walk_dir};
use std::path::{Path, PathBuf};
use std::io::prelude::*;
use rustc_serialize::json::{ToJson, Json};

use eve::server::*;
use eve::flow::*;
use eve::compiler::*;
use eve::value::*;

fn read_events<P: AsRef<Path>>(filename: P) -> Vec<Event> {
    let mut events_string = String::new();
    {
        let mut events_file = OpenOptions::new().create(true).open(&filename).unwrap();
        events_file.read_to_string(&mut events_string).unwrap();
    }
    events_string.lines().map(|line|
        FromJson::from_json(&Json::from_str(&line).unwrap())
        ).collect()
}

fn write_events<P: AsRef<Path>>(filename: P, events: &[Event]) {
    let mut new_events_file = OpenOptions::new().create(true).truncate(true).write(true).open(&filename).unwrap();
    for event in events.iter() {
        new_events_file.write_all(format!("{}", event.to_json()).as_bytes()).unwrap();
        new_events_file.write_all("\n".as_bytes()).unwrap();
    }
}

fn all_paths() -> Vec<PathBuf> {
    let mut filenames = vec![];
    for entry in walk_dir("./test-inputs").unwrap() {
        filenames.push(entry.unwrap().path());
    }
    for entry in walk_dir("./test-outputs").unwrap() {
        filenames.push(entry.unwrap().path());
    }
    for entry in walk_dir("../example data").unwrap() {
        let path = entry.unwrap().path();
        if path.extension().unwrap().to_str().unwrap() == "eve" {
            filenames.push(path);
        }
    }
    filenames
}

fn remove_view(view: &str) {
    for path in all_paths().iter() {
        let mut events = read_events(path);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_view, _)| change_view != view);
        }
        write_events(path, &events[..]);
    }
}

fn remove_row(view: &str, row: Vec<Value>) {
    for path in all_paths().iter() {
        let mut events = read_events(path);
        for event in events.iter_mut() {
            for &mut (ref change_view, ref mut change) in event.changes.iter_mut() {
                if change_view == view {
                    change.insert.retain(|insert_row| *insert_row != row)
                }
            }
        }
        write_events(path, &events[..]);
    }
}

fn reset_internal_views() {
    let compiler_schema = compiler_schema();
    let client_schema = client_schema();
    for path in all_paths().iter() {
        let mut events = read_events(path);
        for event in events.iter_mut() {
            event.changes.retain(|&(ref change_id, _)|
                !compiler_schema.iter().chain(client_schema.iter()).any(|&(ref id, _)| change_id == id)
                );
        }
        write_events(path, &events[..]);
    }
}

fn compact(filename: &str) {
    let mut flow = Flow::new();
    for event in read_events(filename).into_iter() {
        flow.quiesce(event.changes);
    }
    write_events(filename, &[Event{changes: flow.as_changes(), commands: vec![]}]);
}

fn make_bug_test() {
    let events = read_events("./autosave");
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/bug-{}", time);
    let output_filename = format!("./test-outputs/bug-{}", time);
    write_events(&input_filename[..], &events[..]);
    write_events(&output_filename[..], &[]);
}

fn make_regression_test() {
    let mut flow = Flow::new();
    for event in read_events("./autosave").into_iter() {
        flow.quiesce(event.changes);
    }
    let time = time::get_time().sec;
    let input_filename = format!("./test-inputs/regression-{}", time);
    let output_filename = format!("./test-outputs/regression-{}", time);
    write_events(&input_filename[..], &[Event{changes: flow.as_changes(), commands: vec![]}]);
    write_events(&output_filename[..],  &[Event{changes: flow.as_changes(), commands: vec![]}]);
}

#[test]
fn test_regressions() {
    let inputs = walk_dir("./test-inputs").unwrap().collect::<Vec<_>>();
    let outputs = walk_dir("./test-outputs").unwrap().collect::<Vec<_>>();
    assert_eq!(inputs.len(), outputs.len());
    for (input_entry, output_entry) in inputs.into_iter().zip(outputs.into_iter()) {
        let input_path = input_entry.unwrap().path();
        let output_path = output_entry.unwrap().path();
        println!("Testing {:?} against {:?}", input_path, output_path);

        let mut input_flow = Flow::new();
        for event in read_events(input_path).into_iter() {
            input_flow.quiesce(event.changes);
        }

        let mut output_flow = Flow::new();
        for event in read_events(output_path).into_iter() {
            output_flow.change(event.changes);
        }

        let schema = schema();
        for output_cell in output_flow.outputs.iter() {
            let output = output_cell.borrow();
            // ignore internal views
            if !schema.iter().any(|&(ref id, _)| **id == *output.view) {
                let input = input_flow.get_output(&output.view[..]);
                assert_eq!((&output.view, &output.index), (&input.view, &input.index));
            }
        }
    }
}

#[test]
fn test_examples() {
    for entry in walk_dir("../example data").unwrap() {
        let path = entry.unwrap().path();
        if path.extension().unwrap().to_str().unwrap() == "eve" {
            let mut flow = Flow::new();
            for event in read_events(path).into_iter() {
                flow.quiesce(event.changes);
            }
            // if we haven't crashed yet, we're good :)
        }
    }
}

#[allow(dead_code)]
fn main() {
    let args = env::args().collect::<Vec<String>>();
    let borrowed_args = args.iter().map(|s| &s[..]).collect::<Vec<&str>>();
    match &borrowed_args[..] {
        [_, "remove_view", view] => remove_view(view),
        [_, "remove_row", view, row] => remove_row(view, FromJson::from_json(&Json::from_str(&row).unwrap())),
        [_, "reset_internal_views"] => reset_internal_views(),
        [_, "compact", filename] => compact(filename),
        [_, "make_bug_test"] => make_bug_test(),
        [_, "make_regression_test"] => make_regression_test(),
        other => panic!("Bad arguments (look at src/bin/migrate.rs for correct usage): {:?}", &other[1..]),
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JS, Root};
use dom::document::Document;
use dom::window::Window;
use msg::constellation_msg::PipelineId;
use std::cell::Cell;
use std::rc::Rc;

/// Encapsulates a handle to a frame in a frame tree.
#[derive(JSTraceable, HeapSizeOf)]
#[allow(unrooted_must_root)] // FIXME(#6687) this is wrong
pub struct Page {
    /// Pipeline id associated with this page.
    id: PipelineId,

    /// The outermost frame containing the document and window.
    frame: DOMRefCell<Option<Frame>>,

    /// Indicates if reflow is required when reloading.
    needs_reflow: Cell<bool>,

    // Child Pages.
    pub children: DOMRefCell<Vec<Rc<Page>>>,
}

pub struct PageIterator {
    stack: Vec<Rc<Page>>,
}

pub trait IterablePage {
    fn iter(&self) -> PageIterator;
    fn find(&self, id: PipelineId) -> Option<Rc<Page>>;
}

impl IterablePage for Rc<Page> {
    fn iter(&self) -> PageIterator {
        PageIterator {
            stack: vec!(self.clone()),
        }
    }
    fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
        if self.id == id { return Some(self.clone()); }
        for page in &*self.children.borrow() {
            let found = page.find(id);
            if found.is_some() { return found; }
        }
        None
    }

}

impl Page {
    pub fn new(id: PipelineId) -> Page {
        Page {
            id: id,
            frame: DOMRefCell::new(None),
            needs_reflow: Cell::new(true),
            children: DOMRefCell::new(vec!()),
        }
    }

    pub fn pipeline(&self) -> PipelineId {
        self.id
    }

    pub fn window(&self) -> Root<Window> {
        Root::from_ref(&*self.frame.borrow().as_ref().unwrap().window)
    }

    pub fn document(&self) -> Root<Document> {
        Root::from_ref(&*self.frame.borrow().as_ref().unwrap().document)
    }

    // must handle root case separately
    pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
        let remove_idx = {
            self.children
                .borrow()
                .iter()
                .position(|page_tree| page_tree.id == id)
        };
        match remove_idx {
            Some(idx) => Some(self.children.borrow_mut().remove(idx)),
            None => {
                self.children
                    .borrow_mut()
                    .iter_mut()
                    .filter_map(|page_tree| page_tree.remove(id))
                    .next()
            }
        }
    }
}

impl Iterator for PageIterator {
    type Item = Rc<Page>;

    fn next(&mut self) -> Option<Rc<Page>> {
        let popped = self.stack.pop();
        if let Some(ref page) = popped {
            self.stack.extend(page.children.borrow().iter().cloned());
        }
        popped
    }
}

impl Page {
    pub fn set_reflow_status(&self, status: bool) -> bool {
        let old = self.needs_reflow.get();
        self.needs_reflow.set(status);
        old
    }

    #[allow(unrooted_must_root)]
    pub fn set_frame(&self, frame: Option<Frame>) {
        *self.frame.borrow_mut() = frame;
    }
}

/// Information for one frame in the browsing context.
#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct Frame {
    /// The document for this frame.
    pub document: JS<Document>,
    /// The window object for this frame.
    pub window: JS<Window>,
}
<commit_msg>Auto merge of #8481 - frewsxcv:iterablepage-iter, r=Ms2ger<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JS, Root};
use dom::document::Document;
use dom::window::Window;
use msg::constellation_msg::PipelineId;
use std::cell::Cell;
use std::rc::Rc;

/// Encapsulates a handle to a frame in a frame tree.
#[derive(JSTraceable, HeapSizeOf)]
#[allow(unrooted_must_root)] // FIXME(#6687) this is wrong
pub struct Page {
    /// Pipeline id associated with this page.
    id: PipelineId,

    /// The outermost frame containing the document and window.
    frame: DOMRefCell<Option<Frame>>,

    /// Indicates if reflow is required when reloading.
    needs_reflow: Cell<bool>,

    // Child Pages.
    pub children: DOMRefCell<Vec<Rc<Page>>>,
}

pub struct PageIterator {
    stack: Vec<Rc<Page>>,
}

pub trait IterablePage {
    fn iter(&self) -> PageIterator;
    fn find(&self, id: PipelineId) -> Option<Rc<Page>>;
}

impl IterablePage for Rc<Page> {
    fn iter(&self) -> PageIterator {
        PageIterator {
            stack: vec!(self.clone()),
        }
    }
    fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
        if self.id == id {
            return Some(self.clone());
        }

        self.children.borrow()
                     .iter()
                     .filter_map(|p| p.find(id))
                     .next()
    }

}

impl Page {
    pub fn new(id: PipelineId) -> Page {
        Page {
            id: id,
            frame: DOMRefCell::new(None),
            needs_reflow: Cell::new(true),
            children: DOMRefCell::new(vec!()),
        }
    }

    pub fn pipeline(&self) -> PipelineId {
        self.id
    }

    pub fn window(&self) -> Root<Window> {
        Root::from_ref(&*self.frame.borrow().as_ref().unwrap().window)
    }

    pub fn document(&self) -> Root<Document> {
        Root::from_ref(&*self.frame.borrow().as_ref().unwrap().document)
    }

    // must handle root case separately
    pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
        let remove_idx = {
            self.children
                .borrow()
                .iter()
                .position(|page_tree| page_tree.id == id)
        };
        match remove_idx {
            Some(idx) => Some(self.children.borrow_mut().remove(idx)),
            None => {
                self.children
                    .borrow_mut()
                    .iter_mut()
                    .filter_map(|page_tree| page_tree.remove(id))
                    .next()
            }
        }
    }
}

impl Iterator for PageIterator {
    type Item = Rc<Page>;

    fn next(&mut self) -> Option<Rc<Page>> {
        let popped = self.stack.pop();
        if let Some(ref page) = popped {
            self.stack.extend(page.children.borrow().iter().cloned());
        }
        popped
    }
}

impl Page {
    pub fn set_reflow_status(&self, status: bool) -> bool {
        let old = self.needs_reflow.get();
        self.needs_reflow.set(status);
        old
    }

    #[allow(unrooted_must_root)]
    pub fn set_frame(&self, frame: Option<Frame>) {
        *self.frame.borrow_mut() = frame;
    }
}

/// Information for one frame in the browsing context.
#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct Frame {
    /// The document for this frame.
    pub document: JS<Document>,
    /// The window object for this frame.
    pub window: JS<Window>,
}
<|endoftext|>


<commit_before>#![forbid(missing_docs, warnings)]
#![deny(deprecated, drop_with_repr_extern, improper_ctypes,
        non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
        private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, variant_size_differences)]

extern crate ntru;
use ntru::types::{NTRU_MAX_DEGREE, NTRU_MAX_ONES, NtruIntPoly, NtruTernPoly, NtruProdPoly,
                  NtruPrivPoly};
use ntru::encparams::EES1087EP1;
use ntru::rand::{NTRU_RNG_DEFAULT, NtruRandContext};

fn ntru_mult_int_nomod(a: &NtruIntPoly, b: &NtruIntPoly) -> NtruIntPoly {
    if a.get_coeffs().len() != b.get_coeffs().len() {
        panic!("Incompatible int polys")
    }
    let n = a.get_coeffs().len();

    let mut coeffs = Vec::with_capacity(n);
    for k in 0..n {
        let mut ck = 0i32;
        for i in 0..n {
            ck += b.get_coeffs()[i] as i32 * a.get_coeffs()[((n + k - i) % n)] as i32;
        }
        coeffs.push(ck as i16);
    }

    NtruIntPoly::new(&coeffs[..])
}

fn u8_arr_to_u16(arr: &[u8]) -> u16 {
    if arr.len() != 2 {
        panic!("u8_arr_to_u16() requires an array of 2 elements")
    }
    ((arr[0] as u16) << 8) + arr[1] as u16
}

fn ntru_priv_to_int(a: &NtruPrivPoly, modulus: u16) -> NtruIntPoly {
    if a.is_product() {
        a.get_poly_prod().to_int_poly(modulus)
    } else {
        a.get_poly_tern().to_int_poly()
    }
}

fn rand_int(n: u16, pow2q: u16, rand_ctx: &NtruRandContext) -> NtruIntPoly {
    let rand_data = rand_ctx.get_rng().generate(n * 2, rand_ctx).unwrap();
    let shift = if pow2q < 16 {
        16 - pow2q
    } else {
        u16::max_value() - pow2q + 16
    };

    let mut coeffs = vec![0i16; n as usize];
    for i in n..0 {
        coeffs[i as usize] = rand_data[i as usize] as i16 >> shift;
    }
    NtruIntPoly::new(&coeffs.into_boxed_slice())
}

fn verify_inverse(a: &NtruPrivPoly, b: &NtruIntPoly, modulus: u16) -> bool {
    let mut a_int = ntru_priv_to_int(a, modulus);
    a_int.mult_fac(3);
    let new_coeff = a_int.get_coeffs()[0] + 1;
    a_int.set_coeff(0, new_coeff);

    let (mut c, _) = a_int.mult_int(b, modulus - 1);
    c.mod_mask(modulus - 1);
    c.equals1()
}

#[test]
fn it_mult_int() {
    // Multiplication modulo q
    let a1 = NtruIntPoly::new(&[-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1]);
    let b1 = NtruIntPoly::new(&[14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19]);
    let (c1, _) = a1.mult_int(&b1, 32 - 1);

    let c1_exp = NtruIntPoly::new(&[3, 25, -10, 21, 10, 7, 6, 7, 5, 29, -7]);
    assert!(c1_exp.equals_mod(&c1, 32));

    // ntru_mult_mod should give the same result as ntru_mult_int_nomod followed by ntru_mod_mask
    let a2 = NtruIntPoly::new(&[1278, 1451, 850, 1071, 942]);
    let b2 = NtruIntPoly::new(&[571, 52, 1096, 1800, 662]);

    let (c2, _) = a2.mult_int(&b2, 2048 - 1);
    let mut c2_exp = ntru_mult_int_nomod(&a2, &b2);
    c2_exp.mod_mask(2048 - 1);

    assert!(c2_exp.equals_mod(&c2, 2048));

    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    for _ in 0..10 {
        let n_arr = rand_ctx.get_rng().generate(2, &rand_ctx).unwrap();
        let mut n = u8_arr_to_u16(&n_arr);
        n = 100 + (n % (NTRU_MAX_DEGREE - 100) as u16);

        let a3 = NtruIntPoly::rand(n, 11, &rand_ctx);
        let b3 = NtruIntPoly::rand(n, 11, &rand_ctx);
        let mut c3_exp = ntru_mult_int_nomod(&a3, &b3);
        c3_exp.mod_mask(2048 - 1);

        let (c3, _) = a3.mult_int_16(&b3, 2048 - 1);
        assert!(c3_exp.equals_mod(&c3, 2048));
        // ifndef __ARMEL__
        let (c3, _) = a3.mult_int_64(&b3, 2048 - 1);
        assert!(c3_exp.equals_mod(&c3, 2048));
        // endif
    }
}

#[test]
fn it_mult_tern() {
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    let a = NtruTernPoly::rand(11, 3, 3, &rand_ctx).unwrap();
    let b = rand_int(11, 5, &rand_ctx);

    let a_int = a.to_int_poly();
    let (c_int, _) = a_int.mult_int(&b, 32 - 1);
    let (c_tern, _) = b.mult_tern_32(&a, 32 - 1);

    assert!(c_tern.equals_mod(&c_int, 32));

    // #ifndef __ARMEL__
    let (c_tern, _) = b.mult_tern_64(&a, 32 - 1);
    assert!(c_tern.equals_mod(&c_int, 32));
    // #endif

    // #ifdef __SSSE3__
    let (c_tern, _) = b.mult_tern_sse(&a, 32 - 1);
    assert!(c_tern.equals_mod(&c_int, 32));
    // #endif

    for _ in 0..10 {
        let mut n = u8_arr_to_u16(&rand_ctx.get_rng().generate(2, &rand_ctx).unwrap());
        n = 100 + (n % (NTRU_MAX_DEGREE as u16 - 100));
        let mut num_ones = u8_arr_to_u16(&rand_ctx.get_rng()
                                                  .generate(2, &rand_ctx)
                                                  .unwrap());
        num_ones %= n / 2;
        num_ones %= NTRU_MAX_ONES as u16;

        let mut num_neg_ones = u8_arr_to_u16(&rand_ctx.get_rng()
                                                      .generate(2, &rand_ctx)
                                                      .unwrap());
        num_neg_ones %= n / 2;
        num_neg_ones %= NTRU_MAX_ONES as u16;

        let a = NtruTernPoly::rand(n, num_ones, num_neg_ones, &rand_ctx).unwrap();
        let b = rand_int(n, 11, &rand_ctx);
        let a_int = a.to_int_poly();

        let c_int = ntru_mult_int_nomod(&a_int, &b);
        let (c_tern, _) = b.mult_tern_32(&a, 2048 - 1);

        assert!(c_tern.equals_mod(&c_int, 2048));

        // #ifdef __ARMEL__
        let (c_tern, _) = b.mult_tern_64(&a, 2048 - 1);
        assert!(c_tern.equals_mod(&c_int, 2048));
        // #endif
        // #ifdef __SSSE3__
        let (c_tern, _) = b.mult_tern_sse(&a, 2048 - 1);
        assert!(c_tern.equals_mod(&c_int, 2048));
        // #endif
    }
}

#[test]
fn it_mult_prod() {
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    let log_modulus = 11u16;
    let modulus = 1 << log_modulus;

    for _ in 0..10 {
        let a = NtruProdPoly::rand(853, 8, 8, 8, 9, &rand_ctx).unwrap();
        let b = rand_int(853, 1 << log_modulus, &rand_ctx);
        let (c_prod, _) = b.mult_prod(&a, modulus - 1);

        let a_int = a.to_int_poly(modulus);
        let (c_int, _) = a_int.mult_int(&b, modulus - 1);

        assert!(c_prod.equals_mod(&c_int, log_modulus));
    }
}

#[test]
fn it_inv() {
    let a1 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::new(11, &[1, 2, 6, 9], &[0, 3, 4, 10]));
    let (b1, invertible) = a1.invert_32(32 - 1);
    assert!(invertible);
    assert!(verify_inverse(&a1, &b1, 32));

    let (b1, invertible) = a1.invert_64(32 - 1);
    assert!(invertible);
    assert!(verify_inverse(&a1, &b1, 32));

    // Test 3 random polynomials
    let mut num_invertible = 0u16;
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    while num_invertible < 3 {
        let a2 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::rand(853, 100, 100, &rand_ctx)
                                                      .unwrap());
        let (b, invertible) = a2.invert(2048 - 1);

        if invertible {
            assert!(verify_inverse(&a2, &b, 2048));
            num_invertible += 1;
        }
    }

    // #ifdef NTRU_AVOID_HAMMING_WT_PATENT
    num_invertible = 0;
    while num_invertible < 3 {
        let a3 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::rand(853, 100, 100, &rand_ctx)
                                                      .unwrap());
        let (b, invertible) = a3.invert(2048 - 1);

        if invertible {
            assert!(verify_inverse(&a3, &b, 2048));
            num_invertible += 1;
        }
    }
    // #endif

    // test a non-invertible polynomial
    let a2 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::new(11, &[3, 10], &[0, 6, 8]));
    let (_, invertible) = a2.invert(32 - 1);
    assert!(!invertible);
}

#[test]
fn it_arr() {
    let params = EES1087EP1;
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();
    let p1 = rand_int(params.get_n(), 11, &rand_ctx);
    let a = p1.to_arr_32(&params);

    let p2 = NtruIntPoly::from_arr(&a, params.get_n(), params.get_q());

    assert_eq!(p1, p2);

    let b = p1.to_arr_64(&params);

    assert_eq!(a.len(), b.len());
    for (i, val) in a.iter().enumerate() {
        assert_eq!(val, b[i]);
    }

    // #ifdef __SSSE3__
    let b = p1.to_arr_sse_2048(&params);

    assert_eq!(a.len(), b.len());
    for (i, val) in a.iter().enumerate() {
        assert_eq!(val, b[i]);
    }
    // #endif
}
<commit_msg>Fixed build<commit_after>#![forbid(missing_docs, warnings)]
#![deny(deprecated, drop_with_repr_extern, improper_ctypes,
        non_shorthand_field_patterns, overflowing_literals, plugin_as_library,
        private_no_mangle_fns, private_no_mangle_statics, stable_features, unconditional_recursion,
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, variant_size_differences)]

extern crate ntru;
use ntru::types::{NTRU_MAX_DEGREE, NTRU_MAX_ONES, NtruIntPoly, NtruTernPoly, NtruProdPoly,
                  NtruPrivPoly};
use ntru::encparams::EES1087EP1;
use ntru::rand::{NTRU_RNG_DEFAULT, NtruRandContext};

fn ntru_mult_int_nomod(a: &NtruIntPoly, b: &NtruIntPoly) -> NtruIntPoly {
    if a.get_coeffs().len() != b.get_coeffs().len() {
        panic!("Incompatible int polys")
    }
    let n = a.get_coeffs().len();

    let mut coeffs = Vec::with_capacity(n);
    for k in 0..n {
        let mut ck = 0i32;
        for i in 0..n {
            ck += b.get_coeffs()[i] as i32 * a.get_coeffs()[((n + k - i) % n)] as i32;
        }
        coeffs.push(ck as i16);
    }

    NtruIntPoly::new(&coeffs[..])
}

fn u8_arr_to_u16(arr: &[u8]) -> u16 {
    if arr.len() != 2 {
        panic!("u8_arr_to_u16() requires an array of 2 elements")
    }
    ((arr[0] as u16) << 8) + arr[1] as u16
}

fn ntru_priv_to_int(a: &NtruPrivPoly, modulus: u16) -> NtruIntPoly {
    if a.is_product() {
        a.get_poly_prod().to_int_poly(modulus)
    } else {
        a.get_poly_tern().to_int_poly()
    }
}

fn rand_int(n: u16, pow2q: u16, rand_ctx: &NtruRandContext) -> NtruIntPoly {
    let rand_data = rand_ctx.get_rng().generate(n * 2, rand_ctx).unwrap();
    let shift = if pow2q < 16 {
        16 - pow2q
    } else {
        u16::max_value() - pow2q + 16
    };

    let mut coeffs = vec![0i16; n as usize];
    for i in n..0 {
        coeffs[i as usize] = rand_data[i as usize] as i16 >> shift;
    }
    NtruIntPoly::new(&coeffs.into_boxed_slice())
}

fn verify_inverse(a: &NtruPrivPoly, b: &NtruIntPoly, modulus: u16) -> bool {
    let mut a_int = ntru_priv_to_int(a, modulus);
    a_int.mult_fac(3);
    let new_coeff = a_int.get_coeffs()[0] + 1;
    a_int.set_coeff(0, new_coeff);

    let (mut c, _) = a_int.mult_int(b, modulus - 1);
    c.mod_mask(modulus - 1);
    c.equals1()
}

#[test]
fn it_mult_int() {
    // Multiplication modulo q
    let a1 = NtruIntPoly::new(&[-1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1]);
    let b1 = NtruIntPoly::new(&[14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19]);
    let (c1, _) = a1.mult_int(&b1, 32 - 1);

    let c1_exp = NtruIntPoly::new(&[3, 25, -10, 21, 10, 7, 6, 7, 5, 29, -7]);
    assert!(c1_exp.equals_mod(&c1, 32));

    // ntru_mult_mod should give the same result as ntru_mult_int_nomod followed by ntru_mod_mask
    let a2 = NtruIntPoly::new(&[1278, 1451, 850, 1071, 942]);
    let b2 = NtruIntPoly::new(&[571, 52, 1096, 1800, 662]);

    let (c2, _) = a2.mult_int(&b2, 2048 - 1);
    let mut c2_exp = ntru_mult_int_nomod(&a2, &b2);
    c2_exp.mod_mask(2048 - 1);

    assert!(c2_exp.equals_mod(&c2, 2048));

    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    for _ in 0..10 {
        let n_arr = rand_ctx.get_rng().generate(2, &rand_ctx).unwrap();
        let mut n = u8_arr_to_u16(&n_arr);
        n = 100 + (n % (NTRU_MAX_DEGREE - 100) as u16);

        let a3 = NtruIntPoly::rand(n, 11, &rand_ctx);
        let b3 = NtruIntPoly::rand(n, 11, &rand_ctx);
        let mut c3_exp = ntru_mult_int_nomod(&a3, &b3);
        c3_exp.mod_mask(2048 - 1);

        let (c3, _) = a3.mult_int_16(&b3, 2048 - 1);
        assert!(c3_exp.equals_mod(&c3, 2048));
        // ifndef __ARMEL__
        let (c3, _) = a3.mult_int_64(&b3, 2048 - 1);
        assert!(c3_exp.equals_mod(&c3, 2048));
        // endif
    }
}

#[test]
fn it_mult_tern() {
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    let a = NtruTernPoly::rand(11, 3, 3, &rand_ctx).unwrap();
    let b = rand_int(11, 5, &rand_ctx);

    let a_int = a.to_int_poly();
    let (c_int, _) = a_int.mult_int(&b, 32 - 1);
    let (c_tern, _) = b.mult_tern_32(&a, 32 - 1);

    assert!(c_tern.equals_mod(&c_int, 32));

    // #ifndef __ARMEL__
    let (c_tern, _) = b.mult_tern_64(&a, 32 - 1);
    assert!(c_tern.equals_mod(&c_int, 32));
    // #endif

    // #ifdef __SSSE3__
    let (c_tern, _) = b.mult_tern_sse(&a, 32 - 1);
    assert!(c_tern.equals_mod(&c_int, 32));
    // #endif

    for _ in 0..10 {
        let mut n = u8_arr_to_u16(&rand_ctx.get_rng().generate(2, &rand_ctx).unwrap());
        n = 100 + (n % (NTRU_MAX_DEGREE as u16 - 100));
        let mut num_ones = u8_arr_to_u16(&rand_ctx.get_rng()
                                                  .generate(2, &rand_ctx)
                                                  .unwrap());
        num_ones %= n / 2;
        num_ones %= NTRU_MAX_ONES as u16;

        let mut num_neg_ones = u8_arr_to_u16(&rand_ctx.get_rng()
                                                      .generate(2, &rand_ctx)
                                                      .unwrap());
        num_neg_ones %= n / 2;
        num_neg_ones %= NTRU_MAX_ONES as u16;

        let a = NtruTernPoly::rand(n, num_ones, num_neg_ones, &rand_ctx).unwrap();
        let b = rand_int(n, 11, &rand_ctx);
        let a_int = a.to_int_poly();

        let c_int = ntru_mult_int_nomod(&a_int, &b);
        let (c_tern, _) = b.mult_tern_32(&a, 2048 - 1);

        assert!(c_tern.equals_mod(&c_int, 2048));

        // #ifdef __ARMEL__
        let (c_tern, _) = b.mult_tern_64(&a, 2048 - 1);
        assert!(c_tern.equals_mod(&c_int, 2048));
        // #endif
        // #ifdef __SSSE3__
        let (c_tern, _) = b.mult_tern_sse(&a, 2048 - 1);
        assert!(c_tern.equals_mod(&c_int, 2048));
        // #endif
    }
}

#[test]
fn it_mult_prod() {
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    let log_modulus = 11u16;
    let modulus = 1 << log_modulus;

    for _ in 0..10 {
        let a = NtruProdPoly::rand(853, 8, 8, 8, 9, &rand_ctx).unwrap();
        let b = rand_int(853, 1 << log_modulus, &rand_ctx);
        let (c_prod, _) = b.mult_prod(&a, modulus - 1);

        let a_int = a.to_int_poly(modulus);
        let (c_int, _) = a_int.mult_int(&b, modulus - 1);

        assert!(c_prod.equals_mod(&c_int, log_modulus));
    }
}

#[test]
fn it_inv() {
    let a1 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::new(11, &[1, 2, 6, 9], &[0, 3, 4, 10]));
    let (b1, invertible) = a1.invert_32(32 - 1);
    assert!(invertible);
    assert!(verify_inverse(&a1, &b1, 32));

    let (b1, invertible) = a1.invert_64(32 - 1);
    assert!(invertible);
    assert!(verify_inverse(&a1, &b1, 32));

    // Test 3 random polynomials
    let mut num_invertible = 0u16;
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();

    while num_invertible < 3 {
        let a2 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::rand(853, 100, 100, &rand_ctx)
                                                      .unwrap());
        let (b, invertible) = a2.invert(2048 - 1);

        if invertible {
            assert!(verify_inverse(&a2, &b, 2048));
            num_invertible += 1;
        }
    }

    // #ifdef NTRU_AVOID_HAMMING_WT_PATENT
    num_invertible = 0;
    while num_invertible < 3 {
        let a3 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::rand(853, 100, 100, &rand_ctx)
                                                      .unwrap());
        let (b, invertible) = a3.invert(2048 - 1);

        if invertible {
            assert!(verify_inverse(&a3, &b, 2048));
            num_invertible += 1;
        }
    }
    // #endif

    // test a non-invertible polynomial
    let a2 = NtruPrivPoly::new_with_tern_poly(NtruTernPoly::new(11, &[3, 10], &[0, 6, 8]));
    let (_, invertible) = a2.invert(32 - 1);
    assert!(!invertible);
}

#[test]
fn it_arr() {
    let params = EES1087EP1;
    let rng = NTRU_RNG_DEFAULT;
    let rand_ctx = ntru::rand::init(&rng).unwrap();
    let p1 = rand_int(params.get_n(), 11, &rand_ctx);
    let a = p1.to_arr_32(&params);

    let p2 = NtruIntPoly::from_arr(&a, params.get_n(), params.get_q());

    assert_eq!(p1, p2);

    let b = p1.to_arr_64(&params);

    assert_eq!(a.len(), b.len());
    for (i, val) in a.iter().enumerate() {
        assert_eq!(*val, b[i]);
    }

    // #ifdef __SSSE3__
    let b = p1.to_arr_sse_2048(&params);

    assert_eq!(a.len(), b.len());
    for (i, val) in a.iter().enumerate() {
        assert_eq!(*val, b[i]);
    }
    // #endif
}
<|endoftext|>


<commit_before>#![feature(custom_attribute, rustc_attrs)]
#![allow(dead_code, unused_attributes)]

#[rustc_mir]
#[miri_run]
fn foo() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

fn main() {}
<commit_msg>Add more tests. Remove unecessary attributes.<commit_after>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

fn main() {}
<|endoftext|>


<commit_before>extern crate gooddata_fs;

use gooddata_fs::*;

fn connect() -> gd::GoodDataClient {
    let mut gd = gd::GoodDataClient::new();
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

#[test]
fn it_creates_client() {
    let gd = gd::GoodDataClient::new();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token_updated.is_some(), false);
}

#[test]
fn client_can_connect() {
    let gd = connect();

    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), true);
    assert_eq!(gd.token_updated.is_some(), true);
}

#[test]
fn client_can_disconnect() {
    let mut gd = connect();
    gd.disconnect();

    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token_updated.is_some(), false);
}

#[test]
fn client_can_get_projects() {
    let mut gd = connect();
    gd.projects_fetch();

    assert_eq!(gd.projects.is_some(), true);
    assert_eq!(gd.user.is_some(), true);
    assert_eq!(gd.token_updated.is_some(), true);

    gd.disconnect();
}
<commit_msg>Fix tests<commit_after>extern crate gooddata_fs;

use gooddata_fs::*;

fn connect() -> gd::GoodDataClient {
    let mut gd = gd::GoodDataClient::new(gooddata_fs::rest::url::SERVER.to_string());
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

#[test]
fn it_creates_client() {
    let gd = gd::GoodDataClient::new(gooddata_fs::rest::url::SERVER.to_string());
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token_updated.is_some(), false);
}

#[test]
fn client_can_connect() {
    let gd = connect();

    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), true);
    assert_eq!(gd.token_updated.is_some(), true);
}

#[test]
fn client_can_disconnect() {
    let mut gd = connect();
    gd.disconnect();

    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token_updated.is_some(), false);
}

#[test]
fn client_can_get_projects() {
    let mut gd = connect();
    gd.projects_fetch();

    assert_eq!(gd.projects.is_some(), true);
    assert_eq!(gd.user.is_some(), true);
    assert_eq!(gd.token_updated.is_some(), true);

    gd.disconnect();
}
<|endoftext|>


<commit_before>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            let header_size = 20;
            return header_size;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn main() {
    use libtorresmo::{UtpSocket};

    let mut buf = [0, ..512];
    let sock = UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();

    loop {
        let mut sock = sock.clone();
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                spawn(proc() {
                    let mut sock = sock;
                    let payload = String::from_str("Hello\n").into_bytes();

                    // Send uTP packet
                    let _ = sock.sendto(payload.as_slice(), src);
                })
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<commit_msg>Properly static-ize constant.<commit_after>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            static HEADER_SIZE: uint = 20;
            return HEADER_SIZE;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn main() {
    use libtorresmo::{UtpSocket};

    let mut buf = [0, ..512];
    let sock = UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();

    loop {
        let mut sock = sock.clone();
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                spawn(proc() {
                    let mut sock = sock;
                    let payload = String::from_str("Hello\n").into_bytes();

                    // Send uTP packet
                    let _ = sock.sendto(payload.as_slice(), src);
                })
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin, rustc_private)]
#![plugin(quote_macros)]

extern crate syntax;

use syntax::ext::base::ExtCtxt;
use syntax::ext::expand;
use syntax::parse;
use syntax::print::pprust;

fn make_ext_ctxt(sess: &parse::ParseSess) -> ExtCtxt {
    let info = syntax::codemap::ExpnInfo {
        call_site: syntax::codemap::DUMMY_SP,
        callee: syntax::codemap::NameAndSpan {
            name: "test".to_string(),
            format: syntax::codemap::MacroAttribute,
            span: None
        }
    };

    let cfg = vec![];
    let ecfg = expand::ExpansionConfig {
        crate_name: String::new(),
        features: None,
        recursion_limit: 64,
    };

    let mut cx = ExtCtxt::new(&sess, cfg, ecfg);
    cx.bt_push(info);

    cx
}

#[test]
fn test_quote_expr() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let expr = quote_expr!(&cx, 23);
    assert_eq!(pprust::expr_to_string(&expr), "23");

    let value = 24;
    let expr = quote_expr!(&cx, $value);
    assert_eq!(pprust::expr_to_string(&expr), "24i32");
}

#[test]
fn test_quote_ty() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let ty = quote_ty!(&cx, isize);
    assert_eq!(pprust::ty_to_string(&ty), "isize");
}

#[test]
fn test_quote_item() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let item = quote_item!(&cx, static x : int = 10;).unwrap();
    assert_eq!(pprust::item_to_string(&item), "static x: int = 10;");
}

#[test]
fn test_quote_stmt() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let stmt = quote_stmt!(&cx, let x = 20;);
    assert_eq!(pprust::stmt_to_string(&stmt), "let x = 20;");
}

#[test]
fn test_quote_pat() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let pat = quote_pat!(&cx, Some(_));
    assert_eq!(pprust::pat_to_string(&pat), "Some(_)");
}

#[test]
fn test_quote_arm() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let arm = quote_arm!(&cx, (ref x, ref y) => (x, y),);
    assert_eq!(pprust::arm_to_string(&arm), " (ref x, ref y) => (x, y),");
}
<commit_msg>Add quote_tokens!() test<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin, rustc_private)]
#![plugin(quote_macros)]

extern crate syntax;

use syntax::ext::base::ExtCtxt;
use syntax::ext::expand;
use syntax::parse;
use syntax::print::pprust;

fn make_ext_ctxt(sess: &parse::ParseSess) -> ExtCtxt {
    let info = syntax::codemap::ExpnInfo {
        call_site: syntax::codemap::DUMMY_SP,
        callee: syntax::codemap::NameAndSpan {
            name: "test".to_string(),
            format: syntax::codemap::MacroAttribute,
            span: None
        }
    };

    let cfg = vec![];
    let ecfg = expand::ExpansionConfig {
        crate_name: String::new(),
        features: None,
        recursion_limit: 64,
    };

    let mut cx = ExtCtxt::new(&sess, cfg, ecfg);
    cx.bt_push(info);

    cx
}

#[test]
fn test_quote_tokens() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let tts = quote_tokens!(&cx, (+ 2 3));
    assert_eq!(pprust::tts_to_string(&expr), "+ 2 3");
}

#[test]
fn test_quote_expr() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let expr = quote_expr!(&cx, 23);
    assert_eq!(pprust::expr_to_string(&expr), "23");

    let value = 24;
    let expr = quote_expr!(&cx, $value);
    assert_eq!(pprust::expr_to_string(&expr), "24i32");
}

#[test]
fn test_quote_ty() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let ty = quote_ty!(&cx, isize);
    assert_eq!(pprust::ty_to_string(&ty), "isize");
}

#[test]
fn test_quote_item() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let item = quote_item!(&cx, static x : int = 10;).unwrap();
    assert_eq!(pprust::item_to_string(&item), "static x: int = 10;");
}

#[test]
fn test_quote_stmt() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let stmt = quote_stmt!(&cx, let x = 20;);
    assert_eq!(pprust::stmt_to_string(&stmt), "let x = 20;");
}

#[test]
fn test_quote_pat() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let pat = quote_pat!(&cx, Some(_));
    assert_eq!(pprust::pat_to_string(&pat), "Some(_)");
}

#[test]
fn test_quote_arm() {
    let sess = parse::new_parse_sess();
    let cx = make_ext_ctxt(&sess);

    let arm = quote_arm!(&cx, (ref x, ref y) => (x, y),);
    assert_eq!(pprust::arm_to_string(&arm), " (ref x, ref y) => (x, y),");
}
<|endoftext|>


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

use std::path::PathBuf;

#[cfg(target_family = "unix")]
pub fn from_bytes(bytes: Vec<u8>) -> PathBuf {
    use std::os::unix::ffi::OsStringExt as _;
    std::ffi::OsString::from_vec(bytes).into()
}

#[cfg(target_family = "windows")]
pub fn from_bytes(bytes: Vec<u8>) -> PathBuf {
    // TODO: This is just a quick hack that treats UTF-8-encoded strings as
    // UTF-16. This works for trivial cases but should be reworked once the GRR
    // protocol for paths is defined.
    let bytes_u16 = bytes.iter().map(|byte| *byte as u16).collect::<Vec<_>>();

    use std::os::windows::ffi::OsStringExt as _;
    std::ffi::OsString::from_wide(&bytes_u16).into()
}
<commit_msg>Write documentation for the path parsing utility.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::path::PathBuf;

/// Interprets given bytes as an operating system path.
///
/// On Linux, the path is constructed from bytes as is since system paths can
/// be made of arbitrary sequence of bytes.
///
/// On Windows, the behaviour is unspecified (for now).
///
/// ```
/// use std::ffi::OsStr;
///
/// let path = rrg_proto::path::from_bytes(b"foo/bar/baz".to_vec());
///
/// let mut components = path.components()
///     .map(|component| component.as_os_str());
///
/// assert_eq!(components.next(), Some(OsStr::new("foo")));
/// assert_eq!(components.next(), Some(OsStr::new("bar")));
/// assert_eq!(components.next(), Some(OsStr::new("baz")));
/// assert_eq!(components.next(), None);
/// ```
pub fn from_bytes(bytes: Vec<u8>) -> PathBuf {
    from_bytes_impl(bytes)
}

#[cfg(target_family = "unix")]
fn from_bytes_impl(bytes: Vec<u8>) -> PathBuf {
    use std::os::unix::ffi::OsStringExt as _;
    std::ffi::OsString::from_vec(bytes).into()
}

#[cfg(target_family = "windows")]
fn from_bytes_impl(bytes: Vec<u8>) -> PathBuf {
    // TODO: This is just a quick hack that treats UTF-8-encoded strings as
    // UTF-16. This works for trivial cases but should be reworked once the GRR
    // protocol for paths is defined.
    let bytes_u16 = bytes.iter().map(|byte| *byte as u16).collect::<Vec<_>>();

    use std::os::windows::ffi::OsStringExt as _;
    std::ffi::OsString::from_wide(&bytes_u16).into()
}
<|endoftext|>