<commit_before>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())
     .env_remove("RUSTC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<commit_msg>Clean some more env vars during tests<commit_after>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env("__CARGO_TEST_ROOT", support::paths::root())
     .env_remove("__CARGO_DEFAULT_LIB_METADATA")
     .env_remove("RUSTC")
     .env_remove("RUSTDOC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_exe())
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<|endoftext|>


<commit_before>//! Input validation API (Multi-line editing)

use crate::keymap::Invoke;
use crate::Result;

/// Input validation result
#[non_exhaustive]
pub enum ValidationResult {
    /// Incomplete input
    Incomplete,
    /// Validation fails with an optional error message. User must fix the
    /// input.
    Invalid(Option<String>),
    /// Validation succeeds with an optional message
    Valid(Option<String>),
}

impl ValidationResult {
    pub(crate) fn is_valid(&self) -> bool {
        if let ValidationResult::Valid(_) = self {
            true
        } else {
            false
        }
    }
    pub(crate) fn has_message(&self) -> bool {
        match self {
            ValidationResult::Valid(Some(_)) => true,
            ValidationResult::Invalid(Some(_)) => true,
            _ => false,
        }
    }
}

/// Give access to user input.
pub struct ValidationContext<'i> {
    i: &'i mut dyn Invoke,
}

impl<'i> ValidationContext<'i> {
    pub(crate) fn new(i: &'i mut dyn Invoke) -> Self {
        ValidationContext { i }
    }

    /// Returns user input.
    pub fn input(&self) -> &str {
        self.i.input()
    }

    // TODO
    //fn invoke(&mut self, cmd: Cmd) -> Result<?> {
    //    self.i.invoke(cmd)
    //}
}

/// This trait provides an extension interface for determining whether
/// the current input buffer is valid. Rustyline uses the method
/// provided by this trait to decide whether hitting the enter key
/// will end the current editing session and return the current line
/// buffer to the caller of `Editor::readline` or variants.
pub trait Validator {
    /// Takes the currently edited `input` and returns a
    /// `ValidationResult` indicating whether it is valid or not along
    /// with an option message to display about the result. The most
    /// common validity check to implement is probably whether the
    /// input is complete or not, for instance ensuring that all
    /// delimiters are fully balanced.
    ///
    /// If you implement more complex validation checks it's probably
    /// a good idea to also implement a `Hinter` to provide feedback
    /// about what is invalid.
    ///
    /// For auto-correction like a missing closing quote or to reject invalid
    /// char while typing, the input will be mutable (TODO).
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        let _ = ctx;
        Ok(ValidationResult::Valid(None))
    }

    /// Configure whether validation is performed while typing or only
    /// when user presses the Enter key.
    ///
    /// Default is `false`.
    ///
    /// This feature is not yet implemented, so this function is currently a no-op
    fn validate_while_typing(&self) -> bool {
        false
    }
}

impl Validator for () {}

impl<'v, V: ?Sized + Validator> Validator for &'v V {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        (**self).validate(ctx)
    }

    fn validate_while_typing(&self) -> bool {
        (**self).validate_while_typing()
    }
}

/// Simple matching bracket validator.
#[derive(Default)]
pub struct MatchingBracketValidator {
    _priv: (),
}

impl MatchingBracketValidator {
    /// Constructor
    pub fn new() -> Self {
        Self { _priv: () }
    }
}

impl Validator for MatchingBracketValidator {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        Ok(validate_brackets(ctx.input()))
    }
}

fn validate_brackets(input: &str) -> ValidationResult {
    let mut stack = vec![];
    for c in input.chars() {
        match c {
            '(' | '[' | '{' => stack.push(c),
            ')' | ']' | '}' => match (stack.pop(), c) {
                (Some('('), ')') | (Some('['), ']') | (Some('{'), '}') => {}
                (Some(wanted), _) => {
                    return ValidationResult::Invalid(Some(format!(
                        "Mismatched brackets: {:?} is not properly closed",
                        wanted
                    )))
                }
                (None, c) => {
                    return ValidationResult::Invalid(Some(format!(
                        "Mismatched brackets: {:?} is unpaired",
                        c
                    )))
                }
            },
            _ => {}
        }
    }
    if stack.is_empty() {
        ValidationResult::Valid(None)
    } else {
        ValidationResult::Incomplete
    }
}
<commit_msg>Rustfmt + Clippy<commit_after>//! Input validation API (Multi-line editing)

use crate::keymap::Invoke;
use crate::Result;

/// Input validation result
#[non_exhaustive]
pub enum ValidationResult {
    /// Incomplete input
    Incomplete,
    /// Validation fails with an optional error message. User must fix the
    /// input.
    Invalid(Option<String>),
    /// Validation succeeds with an optional message
    Valid(Option<String>),
}

impl ValidationResult {
    pub(crate) fn is_valid(&self) -> bool {
        matches!(self, ValidationResult::Valid(_))
    }

    pub(crate) fn has_message(&self) -> bool {
        matches!(self, ValidationResult::Valid(Some(_)) | ValidationResult::Invalid(Some(_)))
    }
}

/// Give access to user input.
pub struct ValidationContext<'i> {
    i: &'i mut dyn Invoke,
}

impl<'i> ValidationContext<'i> {
    pub(crate) fn new(i: &'i mut dyn Invoke) -> Self {
        ValidationContext { i }
    }

    /// Returns user input.
    pub fn input(&self) -> &str {
        self.i.input()
    }

    // TODO
    //fn invoke(&mut self, cmd: Cmd) -> Result<?> {
    //    self.i.invoke(cmd)
    //}
}

/// This trait provides an extension interface for determining whether
/// the current input buffer is valid. Rustyline uses the method
/// provided by this trait to decide whether hitting the enter key
/// will end the current editing session and return the current line
/// buffer to the caller of `Editor::readline` or variants.
pub trait Validator {
    /// Takes the currently edited `input` and returns a
    /// `ValidationResult` indicating whether it is valid or not along
    /// with an option message to display about the result. The most
    /// common validity check to implement is probably whether the
    /// input is complete or not, for instance ensuring that all
    /// delimiters are fully balanced.
    ///
    /// If you implement more complex validation checks it's probably
    /// a good idea to also implement a `Hinter` to provide feedback
    /// about what is invalid.
    ///
    /// For auto-correction like a missing closing quote or to reject invalid
    /// char while typing, the input will be mutable (TODO).
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        let _ = ctx;
        Ok(ValidationResult::Valid(None))
    }

    /// Configure whether validation is performed while typing or only
    /// when user presses the Enter key.
    ///
    /// Default is `false`.
    ///
    /// This feature is not yet implemented, so this function is currently a
    /// no-op
    fn validate_while_typing(&self) -> bool {
        false
    }
}

impl Validator for () {}

impl<'v, V: ?Sized + Validator> Validator for &'v V {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        (**self).validate(ctx)
    }

    fn validate_while_typing(&self) -> bool {
        (**self).validate_while_typing()
    }
}

/// Simple matching bracket validator.
#[derive(Default)]
pub struct MatchingBracketValidator {
    _priv: (),
}

impl MatchingBracketValidator {
    /// Constructor
    pub fn new() -> Self {
        Self { _priv: () }
    }
}

impl Validator for MatchingBracketValidator {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        Ok(validate_brackets(ctx.input()))
    }
}

fn validate_brackets(input: &str) -> ValidationResult {
    let mut stack = vec![];
    for c in input.chars() {
        match c {
            '(' | '[' | '{' => stack.push(c),
            ')' | ']' | '}' => match (stack.pop(), c) {
                (Some('('), ')') | (Some('['), ']') | (Some('{'), '}') => {}
                (Some(wanted), _) => {
                    return ValidationResult::Invalid(Some(format!(
                        "Mismatched brackets: {:?} is not properly closed",
                        wanted
                    )))
                }
                (None, c) => {
                    return ValidationResult::Invalid(Some(format!(
                        "Mismatched brackets: {:?} is unpaired",
                        c
                    )))
                }
            },
            _ => {}
        }
    }
    if stack.is_empty() {
        ValidationResult::Valid(None)
    } else {
        ValidationResult::Incomplete
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano 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 std::error;
use std::fmt;

use VulkanObject;
use buffer::TypedBufferAccess;
use device::Device;
use device::DeviceOwned;
use format::AcceptsPixels;
use format::Format;
use format::IncompatiblePixelsType;
use image::ImageAccess;

/// Type of operation to check.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CheckCopyBufferImageTy {
    BufferToImage,
    ImageToBuffer,
}

/// Checks whether a copy buffer-image command is valid. Can check both buffer-to-image copies and
/// image-to-buffer copies.
///
/// # Panic
///
/// - Panics if the buffer and image were not created with `device`.
///
pub fn check_copy_buffer_image<B, I, P>(device: &Device, buffer: &B, image: &I,
                                        ty: CheckCopyBufferImageTy, image_offset: [u32; 3],
                                        image_size: [u32; 3], image_first_layer: u32,
                                        image_num_layers: u32, image_mipmap: u32)
                                        -> Result<(), CheckCopyBufferImageError>
    where I: ?Sized + ImageAccess,
          B: ?Sized + TypedBufferAccess<Content = [P]>,
          Format: AcceptsPixels<P> // TODO: use a trait on the image itself instead
{
    let buffer_inner = buffer.inner();
    let image_inner = image.inner();

    assert_eq!(buffer_inner.buffer.device().internal_object(),
               device.internal_object());
    assert_eq!(image_inner.image.device().internal_object(),
               device.internal_object());

    match ty {
        CheckCopyBufferImageTy::BufferToImage => {
            if !buffer_inner.buffer.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !image_inner.image.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
        CheckCopyBufferImageTy::ImageToBuffer => {
            if !image_inner.image.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !buffer_inner.buffer.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
    }

    if image.samples() != 1 {
        return Err(CheckCopyBufferImageError::UnexpectedMultisampled);
    }

    let image_dimensions = match image.dimensions().mipmap_dimensions(image_mipmap) {
        Some(d) => d,
        None => return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange),
    };

    if image_first_layer + image_num_layers > image_dimensions.array_layers() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[0] + image_size[0] > image_dimensions.width() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[1] + image_size[1] > image_dimensions.height() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[2] + image_size[2] > image_dimensions.depth() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    image.format().ensure_accepts()?;

    {
        let (block_width, block_height) = image.format().block_dimensions();
        let num_blocks = (image_size[0] + block_width - 1) / block_width * (image_size[1] + block_height - 1) / block_height * image_size[2] * image_num_layers;
        let required_len = num_blocks as usize * image.format().rate() as usize;
        if required_len > buffer.len() {
            return Err(CheckCopyBufferImageError::BufferTooSmall {
                           required_len: required_len,
                           actual_len: buffer.len(),
                       });
        }
    }

    // TODO: check memory overlap?

    Ok(())
}

/// Error that can happen from `check_copy_buffer_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckCopyBufferImageError {
    /// The source buffer or image is missing the transfer source usage.
    SourceMissingTransferUsage,
    /// The destination buffer or image is missing the transfer destination usage.
    DestinationMissingTransferUsage,
    /// The source and destination are overlapping.
    OverlappingRanges,
    /// The image must not be multisampled.
    UnexpectedMultisampled,
    /// The image coordinates are out of range.
    ImageCoordinatesOutOfRange,
    /// The type of pixels in the buffer isn't compatible with the image format.
    WrongPixelType(IncompatiblePixelsType),
    /// The buffer is too small for the copy operation.
    BufferTooSmall {
        /// Required number of elements in the buffer.
        required_len: usize,
        /// Actual number of elements in the buffer.
        actual_len: usize,
    },
}

impl error::Error for CheckCopyBufferImageError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CheckCopyBufferImageError::SourceMissingTransferUsage => {
                "the source buffer is missing the transfer source usage"
            },
            CheckCopyBufferImageError::DestinationMissingTransferUsage => {
                "the destination buffer is missing the transfer destination usage"
            },
            CheckCopyBufferImageError::OverlappingRanges => {
                "the source and destination are overlapping"
            },
            CheckCopyBufferImageError::UnexpectedMultisampled => {
                "the image must not be multisampled"
            },
            CheckCopyBufferImageError::ImageCoordinatesOutOfRange => {
                "the image coordinates are out of range"
            },
            CheckCopyBufferImageError::WrongPixelType(_) => {
                "the type of pixels in the buffer isn't compatible with the image format"
            },
            CheckCopyBufferImageError::BufferTooSmall { .. } => {
                "the buffer is too small for the copy operation"
            },
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            CheckCopyBufferImageError::WrongPixelType(ref err) => {
                Some(err)
            },
            _ => None,
        }
    }
}

impl fmt::Display for CheckCopyBufferImageError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<IncompatiblePixelsType> for CheckCopyBufferImageError {
    #[inline]
    fn from(err: IncompatiblePixelsType) -> CheckCopyBufferImageError {
        CheckCopyBufferImageError::WrongPixelType(err)
    }
}
<commit_msg>fix #1292: add parentheses to fix int truncation (#1299)<commit_after>// Copyright (c) 2016 The vulkano 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 std::error;
use std::fmt;

use VulkanObject;
use buffer::TypedBufferAccess;
use device::Device;
use device::DeviceOwned;
use format::AcceptsPixels;
use format::Format;
use format::IncompatiblePixelsType;
use image::ImageAccess;

/// Type of operation to check.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CheckCopyBufferImageTy {
    BufferToImage,
    ImageToBuffer,
}

/// Checks whether a copy buffer-image command is valid. Can check both buffer-to-image copies and
/// image-to-buffer copies.
///
/// # Panic
///
/// - Panics if the buffer and image were not created with `device`.
///
pub fn check_copy_buffer_image<B, I, P>(device: &Device, buffer: &B, image: &I,
                                        ty: CheckCopyBufferImageTy, image_offset: [u32; 3],
                                        image_size: [u32; 3], image_first_layer: u32,
                                        image_num_layers: u32, image_mipmap: u32)
                                        -> Result<(), CheckCopyBufferImageError>
    where I: ?Sized + ImageAccess,
          B: ?Sized + TypedBufferAccess<Content = [P]>,
          Format: AcceptsPixels<P> // TODO: use a trait on the image itself instead
{
    let buffer_inner = buffer.inner();
    let image_inner = image.inner();

    assert_eq!(buffer_inner.buffer.device().internal_object(),
               device.internal_object());
    assert_eq!(image_inner.image.device().internal_object(),
               device.internal_object());

    match ty {
        CheckCopyBufferImageTy::BufferToImage => {
            if !buffer_inner.buffer.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !image_inner.image.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
        CheckCopyBufferImageTy::ImageToBuffer => {
            if !image_inner.image.usage_transfer_source() {
                return Err(CheckCopyBufferImageError::SourceMissingTransferUsage);
            }
            if !buffer_inner.buffer.usage_transfer_destination() {
                return Err(CheckCopyBufferImageError::DestinationMissingTransferUsage);
            }
        },
    }

    if image.samples() != 1 {
        return Err(CheckCopyBufferImageError::UnexpectedMultisampled);
    }

    let image_dimensions = match image.dimensions().mipmap_dimensions(image_mipmap) {
        Some(d) => d,
        None => return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange),
    };

    if image_first_layer + image_num_layers > image_dimensions.array_layers() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[0] + image_size[0] > image_dimensions.width() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[1] + image_size[1] > image_dimensions.height() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    if image_offset[2] + image_size[2] > image_dimensions.depth() {
        return Err(CheckCopyBufferImageError::ImageCoordinatesOutOfRange);
    }

    image.format().ensure_accepts()?;

    {
        let required_len = required_len_for_format(image.format(), image_size, image_num_layers);
        if required_len > buffer.len() {
            return Err(CheckCopyBufferImageError::BufferTooSmall {
                           required_len: required_len,
                           actual_len: buffer.len(),
                       });
        }
    }

    // TODO: check memory overlap?

    Ok(())
}

/// Computes the minimum required len in elements for buffer with image data in specified
/// format of specified size.
fn required_len_for_format<P>(format: Format, image_size: [u32; 3], image_num_layers: u32) -> usize
where Format: AcceptsPixels<P>
{
    let (block_width, block_height) = format.block_dimensions();
    let num_blocks = (image_size[0] + block_width - 1) / block_width * ((image_size[1] + block_height - 1) / block_height) * image_size[2] * image_num_layers;
    let required_len = num_blocks as usize * format.rate() as usize;

    return required_len;
}

#[cfg(test)]
mod tests {
    use crate::format::Format;
    use command_buffer::validity::copy_image_buffer::required_len_for_format;

    #[test]
    fn test_required_len_for_format() {
        // issue #1292
        assert_eq!(required_len_for_format::<u8>(Format::BC1_RGBUnormBlock, [2048, 2048, 1], 1), 2097152);
        // other test cases
        assert_eq!(required_len_for_format::<u8>(Format::R8G8B8A8Unorm, [2048, 2048, 1], 1), 16777216);
        assert_eq!(required_len_for_format::<u8>(Format::R4G4UnormPack8, [512, 512, 1], 1), 262144);
        assert_eq!(required_len_for_format::<u8>(Format::R8G8B8Uscaled, [512, 512, 1], 1), 786432);
        assert_eq!(required_len_for_format::<u8>(Format::R32G32Uint, [512, 512, 1], 1), 2097152);
        assert_eq!(required_len_for_format::<u32>(Format::R32G32Uint, [512, 512, 1], 1), 524288);
        assert_eq!(required_len_for_format::<[u32; 2]>(Format::R32G32Uint, [512, 512, 1], 1), 262144);
        assert_eq!(required_len_for_format::<u8>(Format::ASTC_8x8UnormBlock, [512, 512, 1], 1), 65536);
        assert_eq!(required_len_for_format::<u8>(Format::ASTC_12x12SrgbBlock, [512, 512, 1], 1), 29584);
    }
}

/// Error that can happen from `check_copy_buffer_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckCopyBufferImageError {
    /// The source buffer or image is missing the transfer source usage.
    SourceMissingTransferUsage,
    /// The destination buffer or image is missing the transfer destination usage.
    DestinationMissingTransferUsage,
    /// The source and destination are overlapping.
    OverlappingRanges,
    /// The image must not be multisampled.
    UnexpectedMultisampled,
    /// The image coordinates are out of range.
    ImageCoordinatesOutOfRange,
    /// The type of pixels in the buffer isn't compatible with the image format.
    WrongPixelType(IncompatiblePixelsType),
    /// The buffer is too small for the copy operation.
    BufferTooSmall {
        /// Required number of elements in the buffer.
        required_len: usize,
        /// Actual number of elements in the buffer.
        actual_len: usize,
    },
}

impl error::Error for CheckCopyBufferImageError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CheckCopyBufferImageError::SourceMissingTransferUsage => {
                "the source buffer is missing the transfer source usage"
            },
            CheckCopyBufferImageError::DestinationMissingTransferUsage => {
                "the destination buffer is missing the transfer destination usage"
            },
            CheckCopyBufferImageError::OverlappingRanges => {
                "the source and destination are overlapping"
            },
            CheckCopyBufferImageError::UnexpectedMultisampled => {
                "the image must not be multisampled"
            },
            CheckCopyBufferImageError::ImageCoordinatesOutOfRange => {
                "the image coordinates are out of range"
            },
            CheckCopyBufferImageError::WrongPixelType(_) => {
                "the type of pixels in the buffer isn't compatible with the image format"
            },
            CheckCopyBufferImageError::BufferTooSmall { .. } => {
                "the buffer is too small for the copy operation"
            },
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            CheckCopyBufferImageError::WrongPixelType(ref err) => {
                Some(err)
            },
            _ => None,
        }
    }
}

impl fmt::Display for CheckCopyBufferImageError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<IncompatiblePixelsType> for CheckCopyBufferImageError {
    #[inline]
    fn from(err: IncompatiblePixelsType) -> CheckCopyBufferImageError {
        CheckCopyBufferImageError::WrongPixelType(err)
    }
}
<|endoftext|>


<commit_before>extern crate splay_tree;
extern crate rand;

mod map {
    use splay_tree::SplayMap;

    #[test]
    fn new() {
        let map: SplayMap<(), ()> = SplayMap::new();
        assert!(map.is_empty());
    }

    #[test]
    fn default() {
        let map: SplayMap<(), ()> = SplayMap::default();
        assert!(map.is_empty());
    }

    #[test]
    fn insert_and_contains_key() {
        let mut map = SplayMap::new();
        assert!(!map.contains_key("foo"));
        assert_eq!(map.insert("foo", 1), None);
        assert!(map.contains_key("foo"));
        assert_eq!(map.insert("foo", 2), Some(1));
        assert!(map.contains_key("foo"));
    }

    #[test]
    fn clear() {
        let mut map = SplayMap::new();
        map.insert("foo", 1);
        assert!(map.contains_key("foo"));
        map.clear();
        assert!(!map.contains_key("foo"));
    }

    #[test]
    fn get_and_get_mut() {
        let mut map = SplayMap::new();
        assert_eq!(map.get("foo"), None);
        map.insert("foo", 1);
        assert_eq!(map.get("foo"), Some(&1));

        *map.get_mut("foo").unwrap() += 10;
        assert_eq!(map.get("foo"), Some(&11));
    }

    #[test]
    fn iterator() {
        let mut map: SplayMap<_, _> =
            vec![("foo", 1), ("bar", 2), ("baz", 3)].into_iter().collect();
        assert_eq!(vec!["bar", "baz", "foo"],
                   map.keys().cloned().collect::<Vec<_>>());
        assert_eq!(vec![2, 3, 1], map.values().cloned().collect::<Vec<_>>());
        for v in map.values_mut() {
            *v += 10;
        }
        assert_eq!(vec![("bar", 12), ("baz", 13), ("foo", 11)],
                   map.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn find_lower_or_upper_bound_key() {
        // small map
        let mut map: SplayMap<_, _> =
            vec![("foo", 1), ("bar", 2), ("baz", 3)].into_iter().collect();
        assert_eq!(map.find_lower_bound_key("aaa"), Some(&"bar"));
        assert_eq!(map.find_upper_bound_key("aaa"), Some(&"bar"));
        assert_eq!(map.find_lower_bound_key("baz"), Some(&"baz"));
        assert_eq!(map.find_upper_bound_key("baz"), Some(&"foo"));
        assert_eq!(map.find_lower_bound_key("zzz"), None);
        assert_eq!(map.find_upper_bound_key("zzz"), None);

        // large map
        use rand::{self, Rng};
        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut map: SplayMap<_, _> = input.into_iter().map(|n| (n, n)).collect();
        assert_eq!(map.find_lower_bound_key(&500), Some(&500));
        assert_eq!(map.find_upper_bound_key(&500), Some(&501));
        assert_eq!(map.find_lower_bound_key(&999), Some(&999));
        assert_eq!(map.find_upper_bound_key(&999), None);
    }

    #[test]
    fn remove() {
        let mut map = SplayMap::new();
        map.insert("foo", 1);
        map.insert("bar", 2);
        map.insert("baz", 3);
        assert_eq!(map.remove("bar"), Some(2));
        assert_eq!(map.remove("bar"), None);
        assert_eq!(map.len(), 2);
    }

    #[test]
    fn enry() {
        let mut count = SplayMap::new();

        for x in vec!["a", "b", "a", "c", "a", "b"] {
            *count.entry(x).or_insert(0) += 1;
        }

        assert_eq!(count.get("a"), Some(&3));
        assert_eq!(count.get("b"), Some(&2));
        assert_eq!(count.get("c"), Some(&1));
    }

    #[test]
    fn extend() {
        let mut map = SplayMap::new();
        map.extend(vec![("foo", 1), ("bar", 2)]);
        map.extend(vec![("bar", 3), ("baz", 4)]);
        assert_eq!(vec![("bar", 3), ("baz", 4), ("foo", 1)],
                   map.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn hash_eq_ord() {
        let mut a: SplayMap<_, _> = vec![("bar", 2), ("baz", 3)].into_iter().collect();
        let mut b: SplayMap<_, _> = vec![("foo", 1), ("bar", 2)].into_iter().collect();

        assert!(hash(&a) != hash(&b));
        assert!(a != b);
        assert!(a < b);

        b.insert("baz", 3);
        assert!(a < b);

        a.insert("foo", 1);
        assert!(hash(&a) == hash(&b));
        assert!(a == b);
    }

    #[test]
    fn large_map() {
        use rand::{self, Rng};

        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut map: SplayMap<_, _> = input.into_iter().map(|n| (n, n)).collect();
        for i in 0..1000 {
            assert_eq!(map.remove(&i), Some(i));
        }
        assert!(map.is_empty());
    }

    use std::hash;
    fn hash<T: hash::Hash>(x: &T) -> u64 {
        use std::hash::Hasher;
        let mut hasher = hash::SipHasher::new();
        x.hash(&mut hasher);
        hasher.finish()
    }
}

mod heap {
    use splay_tree::SplayHeap;

    #[test]
    fn new() {
        let heap: SplayHeap<()> = SplayHeap::new();
        assert!(heap.is_empty());
    }

    #[test]
    fn default() {
        let heap: SplayHeap<()> = SplayHeap::default();
        assert!(heap.is_empty());
    }

    #[test]
    fn push_and_pop() {
        let mut heap = SplayHeap::new();

        heap.push(10);
        heap.push(1);
        heap.push(30);
        heap.push(7);
        assert_eq!(heap.len(), 4);

        assert_eq!(heap.pop(), Some(30));
        assert_eq!(heap.pop(), Some(10));
        assert_eq!(heap.pop(), Some(7));
        assert_eq!(heap.pop(), Some(1));
        assert!(heap.is_empty());
    }

    #[test]
    fn peek() {
        let mut heap = vec![1, 2, 3].into_iter().collect::<SplayHeap<_>>();
        assert_eq!(heap.peek(), Some(&3));
        assert_eq!(heap.pop(), Some(3));
        heap.clear();

        assert_eq!(heap.peek(), None);
    }

    #[test]
    fn iterator() {
        let heap = vec![1, 2, 3].into_iter().collect::<SplayHeap<_>>();
        assert_eq!(vec![3, 2, 1], heap.iter().cloned().collect::<Vec<_>>());
        assert_eq!(vec![3, 2, 1],
                   (&heap).into_iter().cloned().collect::<Vec<_>>());
        assert_eq!(vec![3, 2, 1], heap.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn extend() {
        let mut heap = SplayHeap::new();
        heap.extend(vec![1, 2, 3]);
        heap.extend(vec![&3, &4]);
        assert_eq!(vec![4, 3, 3, 2, 1],
                   heap.iter().cloned().collect::<Vec<_>>());
    }

    #[test]
    fn large_heap() {
        use rand::{self, Rng};

        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut heap = input.into_iter().collect::<SplayHeap<_>>();
        while let Some(n) = heap.pop() {
            assert_eq!(n, heap.len());
        }
    }
}
<commit_msg>Add test cases for SplaySet<commit_after>extern crate splay_tree;
extern crate rand;

use std::hash;

fn hash<T: hash::Hash>(x: &T) -> u64 {
    use std::hash::Hasher;
    let mut hasher = hash::SipHasher::new();
    x.hash(&mut hasher);
    hasher.finish()
}

mod map {
    use splay_tree::SplayMap;
    use super::hash;

    #[test]
    fn new() {
        let map: SplayMap<(), ()> = SplayMap::new();
        assert!(map.is_empty());
    }

    #[test]
    fn default() {
        let map: SplayMap<(), ()> = SplayMap::default();
        assert!(map.is_empty());
    }

    #[test]
    fn insert_and_contains_key() {
        let mut map = SplayMap::new();
        assert!(!map.contains_key("foo"));
        assert_eq!(map.insert("foo", 1), None);
        assert!(map.contains_key("foo"));
        assert_eq!(map.insert("foo", 2), Some(1));
        assert!(map.contains_key("foo"));
    }

    #[test]
    fn clear() {
        let mut map = SplayMap::new();
        map.insert("foo", 1);
        assert!(map.contains_key("foo"));
        map.clear();
        assert!(!map.contains_key("foo"));
    }

    #[test]
    fn get_and_get_mut() {
        let mut map = SplayMap::new();
        assert_eq!(map.get("foo"), None);
        map.insert("foo", 1);
        assert_eq!(map.get("foo"), Some(&1));

        *map.get_mut("foo").unwrap() += 10;
        assert_eq!(map.get("foo"), Some(&11));
    }

    #[test]
    fn iterator() {
        let mut map: SplayMap<_, _> =
            vec![("foo", 1), ("bar", 2), ("baz", 3)].into_iter().collect();
        assert_eq!(vec!["bar", "baz", "foo"],
                   map.keys().cloned().collect::<Vec<_>>());
        assert_eq!(vec![2, 3, 1], map.values().cloned().collect::<Vec<_>>());
        for v in map.values_mut() {
            *v += 10;
        }
        assert_eq!(vec![("bar", 12), ("baz", 13), ("foo", 11)],
                   map.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn find_lower_or_upper_bound_key() {
        // small map
        let mut map: SplayMap<_, _> =
            vec![("foo", 1), ("bar", 2), ("baz", 3)].into_iter().collect();
        assert_eq!(map.find_lower_bound_key("aaa"), Some(&"bar"));
        assert_eq!(map.find_upper_bound_key("aaa"), Some(&"bar"));
        assert_eq!(map.find_lower_bound_key("baz"), Some(&"baz"));
        assert_eq!(map.find_upper_bound_key("baz"), Some(&"foo"));
        assert_eq!(map.find_lower_bound_key("zzz"), None);
        assert_eq!(map.find_upper_bound_key("zzz"), None);

        // large map
        use rand::{self, Rng};
        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut map: SplayMap<_, _> = input.into_iter().map(|n| (n, n)).collect();
        assert_eq!(map.find_lower_bound_key(&500), Some(&500));
        assert_eq!(map.find_upper_bound_key(&500), Some(&501));
        assert_eq!(map.find_lower_bound_key(&999), Some(&999));
        assert_eq!(map.find_upper_bound_key(&999), None);
    }

    #[test]
    fn remove() {
        let mut map = SplayMap::new();
        map.insert("foo", 1);
        map.insert("bar", 2);
        map.insert("baz", 3);
        assert_eq!(map.remove("bar"), Some(2));
        assert_eq!(map.remove("bar"), None);
        assert_eq!(map.len(), 2);
    }

    #[test]
    fn enry() {
        let mut count = SplayMap::new();

        for x in vec!["a", "b", "a", "c", "a", "b"] {
            *count.entry(x).or_insert(0) += 1;
        }

        assert_eq!(count.get("a"), Some(&3));
        assert_eq!(count.get("b"), Some(&2));
        assert_eq!(count.get("c"), Some(&1));
    }

    #[test]
    fn extend() {
        let mut map = SplayMap::new();
        map.extend(vec![("foo", 1), ("bar", 2)]);
        map.extend(vec![("bar", 3), ("baz", 4)]);
        assert_eq!(vec![("bar", 3), ("baz", 4), ("foo", 1)],
                   map.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn hash_eq_ord() {
        let mut a: SplayMap<_, _> = vec![("bar", 2), ("baz", 3)].into_iter().collect();
        let mut b: SplayMap<_, _> = vec![("foo", 1), ("bar", 2)].into_iter().collect();

        assert!(hash(&a) != hash(&b));
        assert!(a != b);
        assert!(a < b);

        b.insert("baz", 3);
        assert!(a < b);

        a.insert("foo", 1);
        assert!(hash(&a) == hash(&b));
        assert!(a == b);
    }

    #[test]
    fn large_map() {
        use rand::{self, Rng};

        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut map: SplayMap<_, _> = input.into_iter().map(|n| (n, n)).collect();
        for i in 0..1000 {
            assert_eq!(map.remove(&i), Some(i));
        }
        assert!(map.is_empty());
    }
}

mod set {
    use splay_tree::SplaySet;
    use super::hash;

    #[test]
    fn new() {
        let set: SplaySet<()> = SplaySet::new();
        assert!(set.is_empty());
    }

    #[test]
    fn default() {
        let set: SplaySet<()> = SplaySet::default();
        assert!(set.is_empty());
    }

    #[test]
    fn insert_and_replace_contains() {
        let mut set = SplaySet::new();

        assert!(!set.contains("foo"));
        assert_eq!(set.insert("foo"), true);
        assert!(set.contains("foo"));
        assert_eq!(set.insert("foo"), false);
        assert!(set.contains("foo"));

        assert_eq!(set.replace("bar"), None);
        assert_eq!(set.replace("bar"), Some("bar"));
        assert!(set.contains("bar"));
    }

    #[test]
    fn clear() {
        let mut set = SplaySet::new();
        set.insert("foo");
        assert!(set.contains("foo"));
        set.clear();
        assert!(!set.contains("foo"));
    }

    #[test]
    fn get() {
        let mut set = SplaySet::new();
        assert_eq!(set.get("foo"), None);
        set.insert("foo");
        assert_eq!(set.get("foo"), Some(&"foo"));
    }

    #[test]
    fn iterator() {
        let set: SplaySet<_> = vec!["foo", "bar", "baz"].into_iter().collect();
        assert_eq!(set.iter().cloned().collect::<Vec<_>>(),
                   ["bar", "baz", "foo"]);
        assert_eq!((&set).into_iter().cloned().collect::<Vec<_>>(),
                   ["bar", "baz", "foo"]);
        assert_eq!(set.into_iter().collect::<Vec<_>>(), ["bar", "baz", "foo"]);
    }

    #[test]
    fn find_lower_or_upper_bound() {
        // small set
        let mut set: SplaySet<_> = vec!["foo", "bar", "baz"].into_iter().collect();
        assert_eq!(set.find_lower_bound("aaa"), Some(&"bar"));
        assert_eq!(set.find_upper_bound("aaa"), Some(&"bar"));
        assert_eq!(set.find_lower_bound("baz"), Some(&"baz"));
        assert_eq!(set.find_upper_bound("baz"), Some(&"foo"));
        assert_eq!(set.find_lower_bound("zzz"), None);
        assert_eq!(set.find_upper_bound("zzz"), None);

        // large set
        use rand::{self, Rng};
        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut set: SplaySet<_> = input.into_iter().collect();
        assert_eq!(set.find_lower_bound(&500), Some(&500));
        assert_eq!(set.find_upper_bound(&500), Some(&501));
        assert_eq!(set.find_lower_bound(&999), Some(&999));
        assert_eq!(set.find_upper_bound(&999), None);
    }

    #[test]
    fn remove_and_take() {
        let mut set = SplaySet::new();
        set.insert("foo");
        set.insert("bar");
        set.insert("baz");

        assert_eq!(set.remove("bar"), true);
        assert_eq!(set.remove("bar"), false);
        assert_eq!(set.len(), 2);

        assert_eq!(set.take("foo"), Some("foo"));
        assert_eq!(set.take("foo"), None);
        assert_eq!(set.len(), 1);
    }

    #[test]
    fn extend() {
        let mut set = SplaySet::new();
        set.extend(vec!["foo", "bar"]);
        set.extend(vec!["bar", "baz"]);
        assert_eq!(set.into_iter().collect::<Vec<_>>(), ["bar", "baz", "foo"]);
    }

    #[test]
    fn hash_eq_ord() {
        let mut a: SplaySet<_> = vec!["bar", "baz"].into_iter().collect();
        let mut b: SplaySet<_> = vec!["foo", "bar"].into_iter().collect();

        assert!(hash(&a) != hash(&b));
        assert!(a != b);
        assert!(a < b);

        b.insert("baz");
        assert!(a < b);

        a.insert("foo");
        assert!(hash(&a) == hash(&b));
        assert!(a == b);
    }

    #[test]
    fn large_set() {
        use rand::{self, Rng};

        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut set: SplaySet<_> = input.into_iter().collect();
        for i in 0..1000 {
            assert!(set.remove(&i));
        }
        assert!(set.is_empty());
    }

    #[test]
    fn set_operations() {
        let a: SplaySet<_> = vec![1, 2, 3].into_iter().collect();
        let b: SplaySet<_> = vec![3, 4, 5].into_iter().collect();
        let c: SplaySet<_> = vec![5, 6, 7].into_iter().collect();
        let d: SplaySet<_> = vec![1, 2, 3, 4].into_iter().collect();

        assert_eq!(a.difference(&b).cloned().collect::<Vec<_>>(), [1, 2]);
        assert_eq!((&a - &b).into_iter().collect::<Vec<_>>(), [1, 2]);

        assert_eq!(a.symmetric_difference(&b).cloned().collect::<Vec<_>>(),
                   [1, 2, 4, 5]);
        assert_eq!((&a ^ &b).into_iter().collect::<Vec<_>>(), [1, 2, 4, 5]);

        assert_eq!(a.intersection(&b).cloned().collect::<Vec<_>>(), [3]);
        assert_eq!((&a & &b).into_iter().collect::<Vec<_>>(), [3]);

        assert_eq!(a.union(&b).cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5]);
        assert_eq!((&a | &b).into_iter().collect::<Vec<_>>(), [1, 2, 3, 4, 5]);

        assert!(!a.is_disjoint(&a));
        assert!(!a.is_disjoint(&b));
        assert!(a.is_disjoint(&c));
        assert!(!a.is_disjoint(&d));

        assert!(a.is_subset(&a));
        assert!(!a.is_subset(&b));
        assert!(!a.is_subset(&c));
        assert!(a.is_subset(&d));

        assert!(a.is_superset(&a));
        assert!(!a.is_superset(&b));
        assert!(!a.is_superset(&c));
        assert!(!a.is_superset(&d));
        assert!(d.is_superset(&a));
        assert!(!d.is_superset(&b));
        assert!(!d.is_superset(&c));
    }
}

mod heap {
    use splay_tree::SplayHeap;

    #[test]
    fn new() {
        let heap: SplayHeap<()> = SplayHeap::new();
        assert!(heap.is_empty());
    }

    #[test]
    fn default() {
        let heap: SplayHeap<()> = SplayHeap::default();
        assert!(heap.is_empty());
    }

    #[test]
    fn push_and_pop() {
        let mut heap = SplayHeap::new();

        heap.push(10);
        heap.push(1);
        heap.push(30);
        heap.push(7);
        assert_eq!(heap.len(), 4);

        assert_eq!(heap.pop(), Some(30));
        assert_eq!(heap.pop(), Some(10));
        assert_eq!(heap.pop(), Some(7));
        assert_eq!(heap.pop(), Some(1));
        assert!(heap.is_empty());
    }

    #[test]
    fn peek() {
        let mut heap = vec![1, 2, 3].into_iter().collect::<SplayHeap<_>>();
        assert_eq!(heap.peek(), Some(&3));
        assert_eq!(heap.pop(), Some(3));
        heap.clear();

        assert_eq!(heap.peek(), None);
    }

    #[test]
    fn iterator() {
        let heap = vec![1, 2, 3].into_iter().collect::<SplayHeap<_>>();
        assert_eq!(vec![3, 2, 1], heap.iter().cloned().collect::<Vec<_>>());
        assert_eq!(vec![3, 2, 1],
                   (&heap).into_iter().cloned().collect::<Vec<_>>());
        assert_eq!(vec![3, 2, 1], heap.into_iter().collect::<Vec<_>>());
    }

    #[test]
    fn extend() {
        let mut heap = SplayHeap::new();
        heap.extend(vec![1, 2, 3]);
        heap.extend(vec![&3, &4]);
        assert_eq!(vec![4, 3, 3, 2, 1],
                   heap.iter().cloned().collect::<Vec<_>>());
    }

    #[test]
    fn large_heap() {
        use rand::{self, Rng};

        let mut input = (0..1000).into_iter().collect::<Vec<_>>();
        rand::thread_rng().shuffle(&mut input);

        let mut heap = input.into_iter().collect::<SplayHeap<_>>();
        while let Some(n) = heap.pop() {
            assert_eq!(n, heap.len());
        }
    }
}
<|endoftext|>


<commit_before>//! Functions for suppressing non-maximal values.

use std::cmp;

use definitions::{
    Position,
    Score
};

use image::{
    GenericImage,
    ImageBuffer,
    Luma,
    Primitive
};

/// Returned image has zeroes for all inputs pixels which do not have the greatest
/// intensity in the (2 * radius + 1) square block centred on them.
/// Ties are resolved lexicographically.
pub fn suppress_non_maximum<I, C>(image: &I, radius: u32) -> ImageBuffer<Luma<C>, Vec<C>>
    where I: GenericImage<Pixel = Luma<C>>,
          C: Primitive + Ord + 'static
{
    let (width, height) = image.dimensions();
    let mut out: ImageBuffer<Luma<C>, Vec<C>> = ImageBuffer::new(width, height);
    if width == 0 || height == 0 {
        return out;
    }

    for y in (0..height).step_by(radius + 1) {
        for x in (0..width).step_by(radius + 1) {
            let mut best_x = x;
            let mut best_y = y;
            let mut mi = image.get_pixel(x, y)[0];

            // These mins are necessary for when radius > min(width, height)
            for cy in y..cmp::min(height, y + radius + 1) {
                for cx in x..cmp::min(width, x + radius + 1) {
                    let ci = unsafe { image.unsafe_get_pixel(cx, cy)[0] };
                    if ci < mi {
                        continue;
                    }
                    if ci > mi || (cx, cy) < (best_x, best_y) {
                        best_x = cx;
                        best_y = cy;
                        mi = ci;
                    }
                }
            }

            let mut failed = false;

            let y_lower = if radius >= best_y {0} else { best_y - radius };
            let x_lower = if radius >= best_x {0} else { best_x - radius };

            // After finding a candidate for a maximum in this r * r block,
            // we need to test that it's also a maximum in the (2r + 1) * (2r + 1)
            // block centred on it.
            // TODO: The larger block we check here includes pixels we've already
            // TODO: checked. Just adding an "if candidate in smaller block then continue"
            // TODO: doesn't improve performance. However, splitting this loop into
            // TODO: one loop per region of larger block - smaller block should be faster.
            for cy in y_lower..cmp::min(height, best_y + radius + 1) {
                for cx in x_lower..cmp::min(width, best_x + radius + 1) {
                    let ci = unsafe { image.unsafe_get_pixel(cx, cy)[0] };
                    if ci < mi || (cx, cy) == (best_x, best_y) {
                        continue;
                    }
                    if ci > mi || (cx, cy) < (best_x, best_y) {
                        failed = true;
                        break;
                    }
                }
            }

            if !failed {
                unsafe { out.unsafe_put_pixel(best_x, best_y, Luma([mi])) };
            }
        }
    }

    out
}

/// Returns all items which have the highest score in the
/// (2 * radius + 1) square block centred on them. Ties are resolved lexicographically.
pub fn local_maxima<T>(ts: &[T], radius: u32) -> Vec<T>
    where T: Position + Score + Copy
 {
    let mut ordered_ts = ts.to_vec();
    ordered_ts.sort_by(|c, d| {(c.y(), c.x()).cmp(&(d.y(), d.x()))});
    let height = match ordered_ts.last() {
        Some(t) => t.y(),
        None => 0
    };

    let mut ts_by_row = vec![vec![]; (height + 1) as usize];
    for t in ordered_ts.iter() {
        ts_by_row[t.y() as usize].push(t);
    }

    let mut max_ts = vec![];
    for t in ordered_ts.iter() {
        let cx = t.x();
        let cy = t.y();
        let cs = t.score();

        let mut is_max = true;
        let row_lower = if radius > cy {0} else {cy - radius};
        let row_upper = if cy + radius + 1 > height {height} else {cy + radius + 1};
        for y in row_lower..row_upper {
            for c in ts_by_row[y as usize].iter() {
                if c.x() + radius < cx {
                    continue;
                }
                if c.x() > cx + radius {
                    break;
                }
                if c.score() > cs {
                    is_max = false;
                    break;
                }
                if c.score() < cs {
                    continue;
                }
                // Break tiebreaks lexicographically
                if (c.y(), c.x()) < (cy, cx) {
                    is_max = false;
                    break;
                }
            }
            if !is_max {
                break;
            }
        }

        if is_max {
            max_ts.push(*t);
        }
    }

    max_ts
}

#[cfg(test)]
mod test {
    use super::{
        local_maxima,
        suppress_non_maximum
    };
    use definitions::{
        Position,
        Score
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma,
        Primitive
    };
    use noise::{
        gaussian_noise_mut
    };
    use std::cmp;
    use quickcheck::quickcheck;
    use utils::GrayTestImage;
    use test::Bencher;

    #[derive(PartialEq, Debug, Copy, Clone)]
    struct T {
        x: u32,
        y: u32,
        score: f32
    }

    impl T {
        fn new(x: u32, y: u32, score: f32) -> T {
            T { x: x, y: y, score: score}
        }
    }

    impl Position for T {
        fn x(&self) -> u32 { self.x }
        fn y(&self) -> u32 { self.y }
    }

    impl Score for T {
        fn score(&self) -> f32 { self.score }
    }

    #[test]
    fn test_local_maxima() {
        let ts = vec![
            // Suppress vertically
            T::new(0, 0, 8f32),
            T::new(0, 3, 10f32),
            T::new(0, 6, 9f32),
            // Suppress horizontally
            T::new(5, 5, 10f32),
            T::new(7, 5, 15f32),
            // Tiebreak
            T::new(12, 20, 10f32),
            T::new(13, 20, 10f32),
            T::new(13, 21, 10f32)
        ];

        let expected = vec![
            T::new(0, 3, 10f32),
            T::new(7, 5, 15f32),
            T::new(12, 20, 10f32)
        ];

        let max = local_maxima(&ts, 3);
        assert_eq!(max, expected);
    }

    #[bench]
    fn bench_local_maxima_dense(b: &mut Bencher) {
        let mut ts = vec![];
        for x in 0..20 {
            for y in 0..20 {
                let score = (x * y) % 15;
                ts.push(T::new(x, y, score as f32));
            }
        }
        b.iter(|| local_maxima(&ts, 15));
    }

    #[bench]
    fn bench_local_maxima_sparse(b: &mut Bencher) {
        let mut ts = vec![];
        for x in 0..20 {
            for y in 0..20 {
                ts.push(T::new(50 * x, 50 * y, 50f32));
            }
        }
        b.iter(|| local_maxima(&ts, 15));
    }

    #[test]
    fn test_suppress_non_maximum() {
        let mut image = GrayImage::new(25, 25);
        // Suppress vertically
        image.put_pixel(0, 0, Luma([8u8]));
        image.put_pixel(0, 3, Luma([10u8]));
        image.put_pixel(0, 6, Luma([9u8]));
        // Suppress horizontally
        image.put_pixel(5, 5, Luma([10u8]));
        image.put_pixel(7, 5, Luma([15u8]));
        // Tiebreak
        image.put_pixel(12, 20, Luma([10u8]));
        image.put_pixel(13, 20, Luma([10u8]));
        image.put_pixel(13, 21, Luma([10u8]));

        let mut expected = GrayImage::new(25, 25);
        expected.put_pixel(0, 3, Luma([10u8]));
        expected.put_pixel(7, 5, Luma([15u8]));
        expected.put_pixel(12, 20, Luma([10u8]));

        let actual = suppress_non_maximum(&image, 3);
        assert_pixels_eq!(actual, expected);
    }

    #[test]
    fn test_suppress_non_maximum_handles_radius_greater_than_image_side() {
        // Don't care about output pixels, just want to make sure that
        // we don't go out of bounds when radius exceeds width or height.
        let image = GrayImage::new(7, 3);
        let r = suppress_non_maximum(&image, 5);
        let image = GrayImage::new(3, 7);
        let s = suppress_non_maximum(&image, 5);
        // Use r and s to silence warnings about unused variables.
        assert!(r.width() == 7);
        assert!(s.width() == 3);
    }

    #[bench]
    fn bench_suppress_non_maximum_increasing_gradient(b: &mut Bencher) {
        // Increasing gradient in both directions. This can be a worst-case for
        // early-abort strategies.
        let img = ImageBuffer::from_fn(40, 20, |x, y| Luma([(x + y) as u8]));
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_decreasing_gradient(b: &mut Bencher) {
        let width = 40u32;
        let height = 20u32;
        let img = ImageBuffer::from_fn(width, height, |x, y| {
            Luma([((width - x) + (height - y)) as u8])
        });
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_7(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_3(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 3));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_1(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 1));
    }

    /// Reference implementation of suppress_non_maximum. Used to validate
    /// the (presumably faster) actual implementation.
    fn suppress_non_maximum_reference<I, C>(image: &I, radius: u32)
        -> ImageBuffer<Luma<C>, Vec<C>>
        where I: GenericImage<Pixel = Luma<C>>,
              C: Primitive + Ord + 'static
    {
        let (width, height) = image.dimensions();
        let mut out = ImageBuffer::new(width, height);
        out.copy_from(image, 0, 0);

        let iradius = radius as i32;
        let iheight = height as i32;
        let iwidth = width as i32;

        // We update zero values from out as we go, so to check intensities
        // we need to read values from the input image.
        for y in 0..height {
           for x in 0..width {
               let intensity = image.get_pixel(x, y)[0];
               let mut is_max = true;

               let y_lower = cmp::max(0, y as i32 - iradius);
               let y_upper = cmp::min(y as i32 + iradius + 1, iheight);
               let x_lower = cmp::max(0, x as i32 - iradius);
               let x_upper = cmp::min(x as i32 + iradius + 1, iwidth);

               for py in y_lower..y_upper {
                   for px in x_lower..x_upper {
                           let v = image.get_pixel(px as u32, py as u32)[0];
                           // Handle intensity tiebreaks lexicographically
                           let candidate_is_lexically_earlier = (px as u32, py as u32) < (x, y);
                           if v > intensity || (v == intensity && candidate_is_lexically_earlier) {
                               is_max = false;
                               break;
                           }
                   }
               }

               if !is_max {
                   out.put_pixel(x, y, Luma([C::zero()]));
               }
           }
        }

        out
    }

    #[test]
    fn test_suppress_non_maximum_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> bool {
            let expected = suppress_non_maximum_reference(&image.0, 3);
            let actual = suppress_non_maximum(&image.0, 3);
            actual.pixels().eq(expected.pixels())
        }
        quickcheck(prop as fn(GrayTestImage) -> bool);
    }
}
<commit_msg>Faster suppress_non_maximum, add comment explaining implementation<commit_after>//! Functions for suppressing non-maximal values.

use std::cmp;

use definitions::{
    Position,
    Score
};

use image::{
    GenericImage,
    ImageBuffer,
    Luma,
    Primitive
};

/// Returned image has zeroes for all inputs pixels which do not have the greatest
/// intensity in the (2 * radius + 1) square block centred on them.
/// Ties are resolved lexicographically.
pub fn suppress_non_maximum<I, C>(image: &I, radius: u32) -> ImageBuffer<Luma<C>, Vec<C>>
    where I: GenericImage<Pixel = Luma<C>>,
          C: Primitive + Ord + 'static
{
    let (width, height) = image.dimensions();
    let mut out: ImageBuffer<Luma<C>, Vec<C>> = ImageBuffer::new(width, height);
    if width == 0 || height == 0 {
        return out;
    }

    // We divide the image into a grid of blocks of size r * r. We find the maximum
    // value in each block, and then test whether this is in fact the maximum value
    // in the (2r + 1) * (2r + 1) block centered on it. Any pixel that's not maximal
    // within its r * r grid cell can't be a local maximum so we need only perform
    // the (2r + 1) * (2r + 1) search once per r * r grid cell (as opposed to once
    // per pixel in the naive implementation of this algorithm).

    for y in (0..height).step_by(radius + 1) {
        for x in (0..width).step_by(radius + 1) {
            let mut best_x = x;
            let mut best_y = y;
            let mut mi = image.get_pixel(x, y)[0];

            // These mins are necessary for when radius > min(width, height)
            for cy in y..cmp::min(height, y + radius + 1) {
                for cx in x..cmp::min(width, x + radius + 1) {
                    let ci = unsafe { image.unsafe_get_pixel(cx, cy)[0] };
                    if ci < mi {
                        continue;
                    }
                    if ci > mi || (cx, cy) < (best_x, best_y) {
                        best_x = cx;
                        best_y = cy;
                        mi = ci;
                    }
                }
            }

            let x0 = if radius >= best_x {0} else { best_x - radius };
            let x1 = x;
            let x2 = cmp::min(width, x + radius + 1);
            let x3 = cmp::min(width, best_x + radius + 1);

            let y0 = if radius >= best_y {0} else { best_y - radius };
            let y1 = y;
            let y2 = cmp::min(height, y + radius + 1);;
            let y3 = cmp::min(height, best_y + radius + 1);

            // Above initial r * r block
            let mut failed = contains_greater_value(image, best_x, best_y, mi, y0, y1, x0, x3);
            // Left of initial r * r block
            failed |= contains_greater_value(image, best_x, best_y, mi, y1, y2, x0, x1);
            // Right of initial r * r block
            failed |= contains_greater_value(image, best_x, best_y, mi, y1, y2, x2, x3);
            // Below initial r * r block
            failed |= contains_greater_value(image, best_x, best_y, mi, y2, y3, x0, x3);

            if !failed {
                unsafe { out.unsafe_put_pixel(best_x, best_y, Luma([mi])) };
            }
        }
    }

    out
}

/// Returns true if the given block contains a larger value than
/// the input, or contains an equal value with lexicographically
/// lesser coordinates.
#[inline(always)]
fn contains_greater_value<I, C>(
    image: &I,
    x: u32, y: u32, v: C,
    y_lower: u32, y_upper: u32,
    x_lower: u32, x_upper: u32) -> bool
    where I: GenericImage<Pixel = Luma<C>>,
          C: Primitive + Ord + 'static
{
    for cy in y_lower..y_upper {
        for cx in x_lower..x_upper {
            let ci = unsafe { image.unsafe_get_pixel(cx, cy)[0] };
            if ci < v {
                continue;
            }
            if ci > v || (cx, cy) < (x, y) {
                return true;
            }
        }
    }
    false
}

/// Returns all items which have the highest score in the
/// (2 * radius + 1) square block centred on them. Ties are resolved lexicographically.
pub fn local_maxima<T>(ts: &[T], radius: u32) -> Vec<T>
    where T: Position + Score + Copy
 {
    let mut ordered_ts = ts.to_vec();
    ordered_ts.sort_by(|c, d| {(c.y(), c.x()).cmp(&(d.y(), d.x()))});
    let height = match ordered_ts.last() {
        Some(t) => t.y(),
        None => 0
    };

    let mut ts_by_row = vec![vec![]; (height + 1) as usize];
    for t in ordered_ts.iter() {
        ts_by_row[t.y() as usize].push(t);
    }

    let mut max_ts = vec![];
    for t in ordered_ts.iter() {
        let cx = t.x();
        let cy = t.y();
        let cs = t.score();

        let mut is_max = true;
        let row_lower = if radius > cy {0} else {cy - radius};
        let row_upper = if cy + radius + 1 > height {height} else {cy + radius + 1};
        for y in row_lower..row_upper {
            for c in ts_by_row[y as usize].iter() {
                if c.x() + radius < cx {
                    continue;
                }
                if c.x() > cx + radius {
                    break;
                }
                if c.score() > cs {
                    is_max = false;
                    break;
                }
                if c.score() < cs {
                    continue;
                }
                // Break tiebreaks lexicographically
                if (c.y(), c.x()) < (cy, cx) {
                    is_max = false;
                    break;
                }
            }
            if !is_max {
                break;
            }
        }

        if is_max {
            max_ts.push(*t);
        }
    }

    max_ts
}

#[cfg(test)]
mod test {
    use super::{
        local_maxima,
        suppress_non_maximum
    };
    use definitions::{
        Position,
        Score
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma,
        Primitive
    };
    use noise::{
        gaussian_noise_mut
    };
    use std::cmp;
    use quickcheck::quickcheck;
    use utils::GrayTestImage;
    use test::Bencher;

    #[derive(PartialEq, Debug, Copy, Clone)]
    struct T {
        x: u32,
        y: u32,
        score: f32
    }

    impl T {
        fn new(x: u32, y: u32, score: f32) -> T {
            T { x: x, y: y, score: score}
        }
    }

    impl Position for T {
        fn x(&self) -> u32 { self.x }
        fn y(&self) -> u32 { self.y }
    }

    impl Score for T {
        fn score(&self) -> f32 { self.score }
    }

    #[test]
    fn test_local_maxima() {
        let ts = vec![
            // Suppress vertically
            T::new(0, 0, 8f32),
            T::new(0, 3, 10f32),
            T::new(0, 6, 9f32),
            // Suppress horizontally
            T::new(5, 5, 10f32),
            T::new(7, 5, 15f32),
            // Tiebreak
            T::new(12, 20, 10f32),
            T::new(13, 20, 10f32),
            T::new(13, 21, 10f32)
        ];

        let expected = vec![
            T::new(0, 3, 10f32),
            T::new(7, 5, 15f32),
            T::new(12, 20, 10f32)
        ];

        let max = local_maxima(&ts, 3);
        assert_eq!(max, expected);
    }

    #[bench]
    fn bench_local_maxima_dense(b: &mut Bencher) {
        let mut ts = vec![];
        for x in 0..20 {
            for y in 0..20 {
                let score = (x * y) % 15;
                ts.push(T::new(x, y, score as f32));
            }
        }
        b.iter(|| local_maxima(&ts, 15));
    }

    #[bench]
    fn bench_local_maxima_sparse(b: &mut Bencher) {
        let mut ts = vec![];
        for x in 0..20 {
            for y in 0..20 {
                ts.push(T::new(50 * x, 50 * y, 50f32));
            }
        }
        b.iter(|| local_maxima(&ts, 15));
    }

    #[test]
    fn test_suppress_non_maximum() {
        let mut image = GrayImage::new(25, 25);
        // Suppress vertically
        image.put_pixel(0, 0, Luma([8u8]));
        image.put_pixel(0, 3, Luma([10u8]));
        image.put_pixel(0, 6, Luma([9u8]));
        // Suppress horizontally
        image.put_pixel(5, 5, Luma([10u8]));
        image.put_pixel(7, 5, Luma([15u8]));
        // Tiebreak
        image.put_pixel(12, 20, Luma([10u8]));
        image.put_pixel(13, 20, Luma([10u8]));
        image.put_pixel(13, 21, Luma([10u8]));

        let mut expected = GrayImage::new(25, 25);
        expected.put_pixel(0, 3, Luma([10u8]));
        expected.put_pixel(7, 5, Luma([15u8]));
        expected.put_pixel(12, 20, Luma([10u8]));

        let actual = suppress_non_maximum(&image, 3);
        assert_pixels_eq!(actual, expected);
    }

    #[test]
    fn test_suppress_non_maximum_handles_radius_greater_than_image_side() {
        // Don't care about output pixels, just want to make sure that
        // we don't go out of bounds when radius exceeds width or height.
        let image = GrayImage::new(7, 3);
        let r = suppress_non_maximum(&image, 5);
        let image = GrayImage::new(3, 7);
        let s = suppress_non_maximum(&image, 5);
        // Use r and s to silence warnings about unused variables.
        assert!(r.width() == 7);
        assert!(s.width() == 3);
    }

    #[bench]
    fn bench_suppress_non_maximum_increasing_gradient(b: &mut Bencher) {
        // Increasing gradient in both directions. This can be a worst-case for
        // early-abort strategies.
        let img = ImageBuffer::from_fn(40, 20, |x, y| Luma([(x + y) as u8]));
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_decreasing_gradient(b: &mut Bencher) {
        let width = 40u32;
        let height = 20u32;
        let img = ImageBuffer::from_fn(width, height, |x, y| {
            Luma([((width - x) + (height - y)) as u8])
        });
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_7(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 7));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_3(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 3));
    }

    #[bench]
    fn bench_suppress_non_maximum_noise_1(b: &mut Bencher) {
        let mut img: GrayImage = ImageBuffer::new(40, 20);
        gaussian_noise_mut(&mut img, 128f64, 30f64, 1);
        b.iter(|| suppress_non_maximum(&img, 1));
    }

    /// Reference implementation of suppress_non_maximum. Used to validate
    /// the (presumably faster) actual implementation.
    fn suppress_non_maximum_reference<I, C>(image: &I, radius: u32)
        -> ImageBuffer<Luma<C>, Vec<C>>
        where I: GenericImage<Pixel = Luma<C>>,
              C: Primitive + Ord + 'static
    {
        let (width, height) = image.dimensions();
        let mut out = ImageBuffer::new(width, height);
        out.copy_from(image, 0, 0);

        let iradius = radius as i32;
        let iheight = height as i32;
        let iwidth = width as i32;

        // We update zero values from out as we go, so to check intensities
        // we need to read values from the input image.
        for y in 0..height {
           for x in 0..width {
               let intensity = image.get_pixel(x, y)[0];
               let mut is_max = true;

               let y_lower = cmp::max(0, y as i32 - iradius);
               let y_upper = cmp::min(y as i32 + iradius + 1, iheight);
               let x_lower = cmp::max(0, x as i32 - iradius);
               let x_upper = cmp::min(x as i32 + iradius + 1, iwidth);

               for py in y_lower..y_upper {
                   for px in x_lower..x_upper {
                           let v = image.get_pixel(px as u32, py as u32)[0];
                           // Handle intensity tiebreaks lexicographically
                           let candidate_is_lexically_earlier = (px as u32, py as u32) < (x, y);
                           if v > intensity || (v == intensity && candidate_is_lexically_earlier) {
                               is_max = false;
                               break;
                           }
                   }
               }

               if !is_max {
                   out.put_pixel(x, y, Luma([C::zero()]));
               }
           }
        }

        out
    }

    #[test]
    fn test_suppress_non_maximum_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> bool {
            let expected = suppress_non_maximum_reference(&image.0, 3);
            let actual = suppress_non_maximum(&image.0, 3);
            actual.pixels().eq(expected.pixels())
        }
        quickcheck(prop as fn(GrayTestImage) -> bool);
    }
}
<|endoftext|>


<commit_before>use hashbrown::HashMap;

use crate::constants::TEXT_TRIGRAMS_SIZE;
use crate::utils::is_stop_char;

const MAX_INITIAL_HASH_CAPACITY: usize = 2048;

#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Copy)]
pub struct Trigram(pub(crate) char, pub(crate) char, pub(crate) char);

#[allow(clippy::unnecessary_sort_by)]
pub fn get_trigrams_with_positions(text: &str) -> HashMap<Trigram, u32> {
    // Sort in descending order by number of occurrences and trigrams
    let mut count_vec: Vec<_> = count(text)
        .into_iter()
        .map(|(trigram, count)| (count, trigram))
        .collect();
    count_vec.sort_by(|a, b| b.cmp(a));

    count_vec
        .into_iter()
        .take(TEXT_TRIGRAMS_SIZE)
        .enumerate()
        .map(|(i, (_, trigram))| (trigram, i as u32))
        .collect()
}

fn count(text: &str) -> HashMap<Trigram, u32> {
    let hash_capacity = calculate_initial_hash_capacity(text);
    let mut counter_hash: HashMap<Trigram, u32> = HashMap::with_capacity(hash_capacity);

    // iterate through the string and count trigrams
    let mut chars_iter = text
        .chars()
        .map(to_trigram_char)
        .flat_map(char::to_lowercase)
        .chain(Some(' '));
    let mut c1 = ' ';
    // unwrap is safe, because we always chain a space character on the end of the iterator
    let mut c2 = chars_iter.next().unwrap();
    for cur_char in chars_iter {
        let c3 = cur_char;
        if !(c2 == ' ' && (c1 == ' ' || c3 == ' ')) {
            let trigram = Trigram(c1, c2, c3);
            // let mut trigram = String::with_capacity(c1.len_utf8() + c2.len_utf8() + c3.len_utf8());
            // trigram.push(c1);
            // trigram.push(c2);
            // trigram.push(c3);
            let count = counter_hash.entry(trigram).or_insert(0);
            *count += 1;
        }
        c1 = c2;
        c2 = c3;
    }

    counter_hash
}

// Convert punctuations and digits to a space.
#[inline]
fn to_trigram_char(ch: char) -> char {
    if is_stop_char(ch) {
        ' '
    } else {
        ch
    }
}

// In order to improve performance, define the initial capacity for trigrams hash map,
// based on the size of the input text.
fn calculate_initial_hash_capacity(text: &str) -> usize {
    let len = text.len();
    if len > MAX_INITIAL_HASH_CAPACITY {
        MAX_INITIAL_HASH_CAPACITY
    } else {
        len
    }
}

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

    fn assert_valuable_trigram_chars(chars: &[char]) {
        for &ch in chars.iter() {
            assert_eq!(to_trigram_char(ch), ch);
        }
    }

    fn assert_not_valuable_trigram_chars(chars: &[char]) {
        for &ch in chars.iter() {
            assert_eq!(to_trigram_char(ch), ' ');
        }
    }

    #[test]
    fn test_to_trigram_char() {
        // valuable chars, that matters
        assert_valuable_trigram_chars(&['a', 'z', 'A', 'Z', 'Ж', 'ß']);

        // punctuations, digits, etc..
        //
        // 0x00 - 0x40
        assert_not_valuable_trigram_chars(&['\t', '\n', ' ', '.', '0', '9', ',', '@']);
        // 0x5B - 0x60
        assert_not_valuable_trigram_chars(&['[', ']', '^', '\\', '`']);
        // 0x7B - 0x7E
        assert_not_valuable_trigram_chars(&['[', '|', '{', '}', '~']);
    }

    fn assert_count(text: &str, pairs: &[(&str, u32)]) {
        let result = count(text);
        for &(trigram_str, expected_n) in pairs.iter() {
            let chars: Vec<char> = trigram_str.clone().chars().collect();
            let trigram = Trigram(chars[0], chars[1], chars[2]);
            let actual_n = result[&trigram];
            assert_eq!(
                actual_n, expected_n,
                "trigram '{:?}' expected to occur {} times, got {}",
                trigram, expected_n, actual_n
            );
        }
        assert_eq!(result.len(), pairs.len());
    }

    #[test]
    fn test_count() {
        assert_count("", &[]);
        assert_count(",", &[]);
        assert_count("a", &[(" a ", 1)]);
        assert_count("-a-", &[(" a ", 1)]);
        assert_count("yes", &[(" ye", 1), ("yes", 1), ("es ", 1)]);
        assert_count(
            "Give - IT...",
            &[
                (" gi", 1),
                ("giv", 1),
                ("ive", 1),
                ("ve ", 1),
                (" it", 1),
                ("it ", 1),
            ],
        );
    }

    #[test]
    fn test_get_trigrams_with_positions() {
        let res = get_trigrams_with_positions("xaaaaabbbbd");
        assert_eq!(res[&Trigram('a', 'a', 'a')], 0);
        assert_eq!(res[&Trigram('b', 'b', 'b')], 1);
    }
}
<commit_msg>Remove comments<commit_after>use hashbrown::HashMap;

use crate::constants::TEXT_TRIGRAMS_SIZE;
use crate::utils::is_stop_char;

const MAX_INITIAL_HASH_CAPACITY: usize = 2048;

#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Copy)]
pub struct Trigram(pub(crate) char, pub(crate) char, pub(crate) char);

#[allow(clippy::unnecessary_sort_by)]
pub fn get_trigrams_with_positions(text: &str) -> HashMap<Trigram, u32> {
    // Sort in descending order by number of occurrences and trigrams
    let mut count_vec: Vec<_> = count(text)
        .into_iter()
        .map(|(trigram, count)| (count, trigram))
        .collect();
    count_vec.sort_by(|a, b| b.cmp(a));

    count_vec
        .into_iter()
        .take(TEXT_TRIGRAMS_SIZE)
        .enumerate()
        .map(|(i, (_, trigram))| (trigram, i as u32))
        .collect()
}

fn count(text: &str) -> HashMap<Trigram, u32> {
    let hash_capacity = calculate_initial_hash_capacity(text);
    let mut counter_hash: HashMap<Trigram, u32> = HashMap::with_capacity(hash_capacity);

    // iterate through the string and count trigrams
    let mut chars_iter = text
        .chars()
        .map(to_trigram_char)
        .flat_map(char::to_lowercase)
        .chain(Some(' '));
    let mut c1 = ' ';
    // unwrap is safe, because we always chain a space character on the end of the iterator
    let mut c2 = chars_iter.next().unwrap();
    for cur_char in chars_iter {
        let c3 = cur_char;
        if !(c2 == ' ' && (c1 == ' ' || c3 == ' ')) {
            let trigram = Trigram(c1, c2, c3);
            let count = counter_hash.entry(trigram).or_insert(0);
            *count += 1;
        }
        c1 = c2;
        c2 = c3;
    }

    counter_hash
}

// Convert punctuations and digits to a space.
#[inline]
fn to_trigram_char(ch: char) -> char {
    if is_stop_char(ch) {
        ' '
    } else {
        ch
    }
}

// In order to improve performance, define the initial capacity for trigrams hash map,
// based on the size of the input text.
fn calculate_initial_hash_capacity(text: &str) -> usize {
    let len = text.len();
    if len > MAX_INITIAL_HASH_CAPACITY {
        MAX_INITIAL_HASH_CAPACITY
    } else {
        len
    }
}

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

    fn assert_valuable_trigram_chars(chars: &[char]) {
        for &ch in chars.iter() {
            assert_eq!(to_trigram_char(ch), ch);
        }
    }

    fn assert_not_valuable_trigram_chars(chars: &[char]) {
        for &ch in chars.iter() {
            assert_eq!(to_trigram_char(ch), ' ');
        }
    }

    #[test]
    fn test_to_trigram_char() {
        // valuable chars, that matters
        assert_valuable_trigram_chars(&['a', 'z', 'A', 'Z', 'Ж', 'ß']);

        // punctuations, digits, etc..
        //
        // 0x00 - 0x40
        assert_not_valuable_trigram_chars(&['\t', '\n', ' ', '.', '0', '9', ',', '@']);
        // 0x5B - 0x60
        assert_not_valuable_trigram_chars(&['[', ']', '^', '\\', '`']);
        // 0x7B - 0x7E
        assert_not_valuable_trigram_chars(&['[', '|', '{', '}', '~']);
    }

    fn assert_count(text: &str, pairs: &[(&str, u32)]) {
        let result = count(text);
        for &(trigram_str, expected_n) in pairs.iter() {
            let chars: Vec<char> = trigram_str.clone().chars().collect();
            let trigram = Trigram(chars[0], chars[1], chars[2]);
            let actual_n = result[&trigram];
            assert_eq!(
                actual_n, expected_n,
                "trigram '{:?}' expected to occur {} times, got {}",
                trigram, expected_n, actual_n
            );
        }
        assert_eq!(result.len(), pairs.len());
    }

    #[test]
    fn test_count() {
        assert_count("", &[]);
        assert_count(",", &[]);
        assert_count("a", &[(" a ", 1)]);
        assert_count("-a-", &[(" a ", 1)]);
        assert_count("yes", &[(" ye", 1), ("yes", 1), ("es ", 1)]);
        assert_count(
            "Give - IT...",
            &[
                (" gi", 1),
                ("giv", 1),
                ("ive", 1),
                ("ve ", 1),
                (" it", 1),
                ("it ", 1),
            ],
        );
    }

    #[test]
    fn test_get_trigrams_with_positions() {
        let res = get_trigrams_with_positions("xaaaaabbbbd");
        assert_eq!(res[&Trigram('a', 'a', 'a')], 0);
        assert_eq!(res[&Trigram('b', 'b', 'b')], 1);
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types, non_snake_case)]
pub mod constants;
use self::constants::*;

use ncurses::{box_};
use ncurses::ll::{chtype, WINDOW, wattron, wattrset, ungetch};
use libc::c_int;
use input::Input;

pub fn _attron(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes as i32) }
}

pub fn _attroff(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes as i32) }
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as i32) }
}

pub fn _draw_box(w: WINDOW, verch: chtype, horch: chtype) -> i32 {
    box_(w, verch, horch)
}

pub fn _resize_term(_nlines: i32, _ncols: i32) -> i32 {
    error!("resize_term is not implemented in ncurses-rs");
    -1
}

pub fn _set_title(title: &str) {
    //Not supported
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Input {
    assert!(i >= KEY_OFFSET, format!("Input value less than expected: {:?}", i));
    if i > KEY_EVENT {
        Input::Unknown(i)
    } else {
        let i = if i <= KEY_F15 {
            i - KEY_OFFSET
        } else {
            i - KEY_OFFSET - 48
        };
        SPECIAL_KEY_CODES[i as usize]
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    let i = convert_input_to_c_int(input);
    unsafe { ungetch(i) }
}

fn convert_input_to_c_int(input: &Input) -> c_int {
    match *input {
        Input::Character(c) => c as c_int,
        Input::Unknown(i) => i,
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return result;
                    } else {
                        return result + 48;
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::convert_input_to_c_int;
    use super::*;
    use input::Input;
    use libc::c_int;

    #[test]
    fn test_key_dl_to_special_keycode() {
        let keyDl = 0o510;
        assert_eq!(Input::KeyDL, to_special_keycode(keyDl));
    }

    #[test]
    fn test_key_f15_to_input() {
        let keyF15 = 0o410 + 15;
        assert_eq!(Input::KeyF15, to_special_keycode(keyF15));
    }

    #[test]
    fn test_key_up_to_input() {
        let keyUp = 0o403;
        assert_eq!(Input::KeyUp, to_special_keycode(keyUp));
    }

    #[test]
    fn test_convert_input_to_c_int() {
        let i = convert_input_to_c_int(&Input::Character('a'));
        assert_eq!('a' as c_int, i);
    }

    #[test]
    fn test_convert_backspace_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeyBackspace);
        assert_eq!(0o407, i);
    }

    #[test]
    fn test_convert_sdl_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeySDL);
        assert_eq!(0o600, i);
    }

}
<commit_msg>Use wattroff<commit_after>#![allow(non_camel_case_types, non_snake_case)]
pub mod constants;
use self::constants::*;

use ncurses::{box_};
use ncurses::ll::{chtype, WINDOW, wattron, wattroff, wattrset, ungetch};
use libc::c_int;
use input::Input;

pub fn _attron(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes as i32) }
}

pub fn _attroff(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes as i32) }
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as i32) }
}

pub fn _draw_box(w: WINDOW, verch: chtype, horch: chtype) -> i32 {
    box_(w, verch, horch)
}

pub fn _resize_term(_nlines: i32, _ncols: i32) -> i32 {
    error!("resize_term is not implemented in ncurses-rs");
    -1
}

pub fn _set_title(title: &str) {
    //Not supported
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Input {
    assert!(i >= KEY_OFFSET, format!("Input value less than expected: {:?}", i));
    if i > KEY_EVENT {
        Input::Unknown(i)
    } else {
        let i = if i <= KEY_F15 {
            i - KEY_OFFSET
        } else {
            i - KEY_OFFSET - 48
        };
        SPECIAL_KEY_CODES[i as usize]
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    let i = convert_input_to_c_int(input);
    unsafe { ungetch(i) }
}

fn convert_input_to_c_int(input: &Input) -> c_int {
    match *input {
        Input::Character(c) => c as c_int,
        Input::Unknown(i) => i,
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return result;
                    } else {
                        return result + 48;
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::convert_input_to_c_int;
    use super::*;
    use input::Input;
    use libc::c_int;

    #[test]
    fn test_key_dl_to_special_keycode() {
        let keyDl = 0o510;
        assert_eq!(Input::KeyDL, to_special_keycode(keyDl));
    }

    #[test]
    fn test_key_f15_to_input() {
        let keyF15 = 0o410 + 15;
        assert_eq!(Input::KeyF15, to_special_keycode(keyF15));
    }

    #[test]
    fn test_key_up_to_input() {
        let keyUp = 0o403;
        assert_eq!(Input::KeyUp, to_special_keycode(keyUp));
    }

    #[test]
    fn test_convert_input_to_c_int() {
        let i = convert_input_to_c_int(&Input::Character('a'));
        assert_eq!('a' as c_int, i);
    }

    #[test]
    fn test_convert_backspace_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeyBackspace);
        assert_eq!(0o407, i);
    }

    #[test]
    fn test_convert_sdl_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeySDL);
        assert_eq!(0o600, i);
    }

}
<|endoftext|>


<commit_before>use chrono::{offset::Utc, DateTime};
use diesel::{self, pg::PgConnection};
use uuid::Uuid;

pub mod direct_post;
pub mod post;

use crate::{
    base_actor::BaseActor,
    base_post::direct_post::DirectPost,
    file::image::Image,
    generate_urls::GenerateUrls,
    schema::base_posts,
    sql_types::{Mime, PostVisibility},
};

#[derive(Debug, Queryable, QueryableByName)]
#[table_name = "base_posts"]
pub struct BasePost {
    id: i32,
    name: Option<String>, // max_length: 140
    media_type: Mime,     // max_length: 80
    posted_by: i32,       // foreign key to BaseActor
    icon: Option<i32>,    // foreign key to Image
    visibility: PostVisibility,
    created_at: DateTime<Utc>,
    updated_at: DateTime<Utc>,
    local_uuid: Option<Uuid>,
    activitypub_id: String,
}

impl BasePost {
    pub fn id(&self) -> i32 {
        self.id
    }

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|s| s.as_ref())
    }

    pub fn media_type(&self) -> &Mime {
        &self.media_type
    }

    pub fn posted_by(&self) -> i32 {
        self.posted_by
    }

    pub fn icon(&self) -> Option<i32> {
        self.icon
    }

    pub fn visibility(&self) -> PostVisibility {
        self.visibility
    }

    pub fn is_visible_by(
        &self,
        actor: &BaseActor,
        conn: &PgConnection,
    ) -> Result<bool, diesel::result::Error> {
        match self.visibility {
            PostVisibility::Public => Ok(true),
            PostVisibility::FollowersOnly => actor.is_following_id(self.posted_by, conn),
            PostVisibility::ListedPeopleOnly => DirectPost::exists(actor, self, conn),
            _ => Ok(false),
        }
    }
}

#[derive(Insertable)]
#[table_name = "base_posts"]
pub struct NewBasePost {
    name: Option<String>,
    media_type: Mime,
    posted_by: i32,
    icon: Option<i32>,
    visibility: PostVisibility,
    local_uuid: Option<Uuid>,
    activitypub_id: String,
}

impl NewBasePost {
    pub fn insert(self, conn: &PgConnection) -> Result<BasePost, diesel::result::Error> {
        use diesel::prelude::*;

        diesel::insert_into(base_posts::table)
            .values(&self)
            .get_result(conn)
    }

    pub fn local(
        name: Option<String>,
        media_type: Mime,
        posted_by: &BaseActor,
        icon: Option<&Image>,
        visibility: PostVisibility,
        generate_id: impl GenerateUrls,
    ) -> Self {
        let uuid = Uuid::new_v4();

        NewBasePost {
            name,
            media_type: media_type,
            posted_by: posted_by.id(),
            icon: icon.map(|i| i.id()),
            visibility,
            activitypub_id: generate_id.post_id(&posted_by, &uuid),
            local_uuid: Some(uuid),
        }
    }

    pub fn new(
        name: Option<String>,
        media_type: Mime,
        posted_by: &BaseActor,
        icon: Option<&Image>,
        visibility: PostVisibility,
        activitypub_id: String,
    ) -> Self {
        NewBasePost {
            name,
            media_type: media_type,
            posted_by: posted_by.id(),
            icon: icon.map(|i| i.id()),
            visibility,
            local_uuid: None,
            activitypub_id,
        }
    }
}

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

    #[test]
    fn create_base_post() {
        with_connection(|conn| {
            with_base_actor(conn, |posted_by| {
                with_base_post(conn, &posted_by, |_| Ok(()))
            })
        })
    }
}
<commit_msg>Clippy<commit_after>use chrono::{offset::Utc, DateTime};
use diesel::{self, pg::PgConnection};
use uuid::Uuid;

pub mod direct_post;
pub mod post;

use crate::{
    base_actor::BaseActor,
    base_post::direct_post::DirectPost,
    file::image::Image,
    generate_urls::GenerateUrls,
    schema::base_posts,
    sql_types::{Mime, PostVisibility},
};

#[derive(Debug, Queryable, QueryableByName)]
#[table_name = "base_posts"]
pub struct BasePost {
    id: i32,
    name: Option<String>, // max_length: 140
    media_type: Mime,     // max_length: 80
    posted_by: i32,       // foreign key to BaseActor
    icon: Option<i32>,    // foreign key to Image
    visibility: PostVisibility,
    created_at: DateTime<Utc>,
    updated_at: DateTime<Utc>,
    local_uuid: Option<Uuid>,
    activitypub_id: String,
}

impl BasePost {
    pub fn id(&self) -> i32 {
        self.id
    }

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|s| s.as_ref())
    }

    pub fn media_type(&self) -> &Mime {
        &self.media_type
    }

    pub fn posted_by(&self) -> i32 {
        self.posted_by
    }

    pub fn icon(&self) -> Option<i32> {
        self.icon
    }

    pub fn visibility(&self) -> PostVisibility {
        self.visibility
    }

    pub fn is_visible_by(
        &self,
        actor: &BaseActor,
        conn: &PgConnection,
    ) -> Result<bool, diesel::result::Error> {
        match self.visibility {
            PostVisibility::Public => Ok(true),
            PostVisibility::FollowersOnly => actor.is_following_id(self.posted_by, conn),
            PostVisibility::ListedPeopleOnly => DirectPost::exists(actor, self, conn),
            _ => Ok(false),
        }
    }
}

#[derive(Insertable)]
#[table_name = "base_posts"]
pub struct NewBasePost {
    name: Option<String>,
    media_type: Mime,
    posted_by: i32,
    icon: Option<i32>,
    visibility: PostVisibility,
    local_uuid: Option<Uuid>,
    activitypub_id: String,
}

impl NewBasePost {
    pub fn insert(self, conn: &PgConnection) -> Result<BasePost, diesel::result::Error> {
        use diesel::prelude::*;

        diesel::insert_into(base_posts::table)
            .values(&self)
            .get_result(conn)
    }

    pub fn local(
        name: Option<String>,
        media_type: Mime,
        posted_by: &BaseActor,
        icon: Option<&Image>,
        visibility: PostVisibility,
        generate_id: impl GenerateUrls,
    ) -> Self {
        let uuid = Uuid::new_v4();

        NewBasePost {
            name,
            media_type,
            posted_by: posted_by.id(),
            icon: icon.map(|i| i.id()),
            visibility,
            activitypub_id: generate_id.post_id(&posted_by, &uuid),
            local_uuid: Some(uuid),
        }
    }

    pub fn new(
        name: Option<String>,
        media_type: Mime,
        posted_by: &BaseActor,
        icon: Option<&Image>,
        visibility: PostVisibility,
        activitypub_id: String,
    ) -> Self {
        NewBasePost {
            name,
            media_type,
            posted_by: posted_by.id(),
            icon: icon.map(|i| i.id()),
            visibility,
            local_uuid: None,
            activitypub_id,
        }
    }
}

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

    #[test]
    fn create_base_post() {
        with_connection(|conn| {
            with_base_actor(conn, |posted_by| {
                with_base_post(conn, &posted_by, |_| Ok(()))
            })
        })
    }
}
<|endoftext|>


<commit_before>use casile::*;

use assert_cmd::prelude::*;
use predicates::prelude::*;
use std::process::Command;

static BIN_NAME: &str = "casile";

#[test]
fn outputs_version() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("--version");
    cmd.assert().stdout(predicate::str::starts_with("casile v"));
    Ok(())
}

#[test]
fn ouput_is_localized() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("-l").arg("tr").arg("setup");
    cmd.assert().stderr(predicate::str::contains("kurun artık"));
    Ok(())
}

#[test]
fn setup_path_exists() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("-p").arg("not_a_dir").arg("setup");
    cmd.assert()
        .failure()
        .stderr(predicate::str::contains("No such file or directory"));
    Ok(())
}

// #[test]
// fn fail_on_casile_sources() -> Result<()> {
//     let mut cmd = Command::cargo_bin(BIN_NAME)?;
//     cmd.arg("-p").arg("./").arg("setup");
//     cmd.assert()
//         .failure()
//         .stderr(predicate::str::contains("Make failed to parse or execute"));
//     Ok(())
// }
<commit_msg>test(i18n): Update check target with current expected localization<commit_after>use casile::*;

use assert_cmd::prelude::*;
use predicates::prelude::*;
use std::process::Command;

static BIN_NAME: &str = "casile";

#[test]
fn outputs_version() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("--version");
    cmd.assert().stdout(predicate::str::starts_with("casile v"));
    Ok(())
}

#[test]
fn ouput_is_localized() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("-l").arg("tr").arg("setup");
    cmd.assert()
        .stderr(predicate::str::contains("yapılandırılıyor"));
    Ok(())
}

#[test]
fn setup_path_exists() -> Result<()> {
    let mut cmd = Command::cargo_bin(BIN_NAME)?;
    cmd.arg("-p").arg("not_a_dir").arg("setup");
    cmd.assert()
        .failure()
        .stderr(predicate::str::contains("No such file or directory"));
    Ok(())
}

// #[test]
// fn fail_on_casile_sources() -> Result<()> {
//     let mut cmd = Command::cargo_bin(BIN_NAME)?;
//     cmd.arg("-p").arg("./").arg("setup");
//     cmd.assert()
//         .failure()
//         .stderr(predicate::str::contains("Make failed to parse or execute"));
//     Ok(())
// }
<|endoftext|>