<commit_before>extern crate gcc;
extern crate metadeps;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return
    }

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return
    }

    // Set up compiler options.
    let mut cflags = env::var("CFLAGS").unwrap_or_else(|_| String::new());
    if target.contains("i686") {
        cflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cflags.push_str(" -fPIC");
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    let mut config_opts = Vec::new();
    config_opts.push("--enable-static=yes".to_string());
    config_opts.push("--enable-shared=no".to_string());
    config_opts.push("--enable-optimize".to_string());
    config_opts.push(format!("--prefix={}", dst.display()));

    // Prepare.
    let src = env::current_dir().unwrap();
    run(
        Command::new("sh")
            .current_dir(&src.join("c-ares"))
            .arg("buildconf")
    );
    run(
        Command::new("sh")
            .env("CFLAGS", &cflags)
            .current_dir(&build)
            .arg("-c")
            .arg(
                format!(
                    "{} {}",
                    src.join("c-ares/configure").display(),
                    config_opts.join(" ")
                )
            )
    );

    // Compile.
    run(
        Command::new(make())
            .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
            .current_dir(&build)
    );

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(
        Command::new("cmd")
            .current_dir(c_ares_dir)
            .arg("/c")
            .arg("buildconf.bat")
    );

    // Compile.
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<commit_msg>work around cargo nonsense<commit_after>extern crate gcc;
extern crate metadeps;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return
    }

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return
    }

    // Set up compiler options.
    let mut cflags = env::var("CFLAGS").unwrap_or_else(|_| String::new());
    if target.contains("i686") {
        cflags.push_str(" -m32");
    } else if target.contains("x86_64") {
        cflags.push_str(" -m64");
    }
    if !target.contains("i686") {
        cflags.push_str(" -fPIC");
    }

    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let _ = fs::create_dir(&build);

    let mut config_opts = Vec::new();
    config_opts.push("--enable-static=yes".to_string());
    config_opts.push("--enable-shared=no".to_string());
    config_opts.push("--enable-optimize".to_string());
    config_opts.push(format!("--prefix={}", dst.display()));

    // Prepare.
    let src = env::current_dir().unwrap();
    run(
        Command::new("sh")
            .current_dir(&src.join("c-ares"))
            .arg("buildconf")
    );
    run(
        Command::new("sh")
            .env("CFLAGS", &cflags)
            .current_dir(&build)
            .arg("-c")
            .arg(
                format!(
                    "{} {}",
                    src.join("c-ares/configure").display(),
                    config_opts.join(" ")
                )
            )
    );

    // Compile.
    run(
        Command::new(make())
            .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
            .current_dir(&build)
    );

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn nmake(target: &str) -> Command {
    // cargo messes with the environment in a way that nmake does not like -
    // see https://github.com/rust-lang/cargo/issues/4156.  Explicitly remove
    // the unwanted variables.
    let mut cmd = gcc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS");
    cmd
}

fn build_msvc(target: &str) {
    // Prepare.
    let src = env::current_dir().unwrap();
    let c_ares_dir = &src.join("c-ares");
    run(
        Command::new("cmd")
            .current_dir(c_ares_dir)
            .arg("/c")
            .arg("buildconf.bat")
    );

    // Compile.
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dst.join("build");
    let mut cmd = nmake(target);
    cmd.current_dir(c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<|endoftext|>


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

use abi::{ArgAttribute, ArgType, CastTarget, FnType, LayoutExt, PassMode, Reg, RegKind, Uniform};
use context::CodegenCx;
use rustc::ty::layout::{self, Size};

fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
    // Always sign extend u32 values on 64-bit mips
    if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
        if let layout::Int(i, signed) = scalar.value {
            if !signed && i.size().bits() == 32 {
                if let PassMode::Direct(ref mut attrs) = arg.mode {
                    attrs.set(ArgAttribute::SExt);
                    return;
                }
            }
        }
    }

    arg.extend_integer_width_to(bits);
}

fn bits_to_int_reg(bits: u64) -> Reg {
    if bits <= 8 {
        Reg::i8()
    } else if bits <= 16 {
        Reg::i16()
    } else if bits <= 32 {
        Reg::i32()
    } else {
        Reg::i64()
    }
}

fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option<Reg> {
    match ret.layout.field(cx, i).abi {
        layout::Abi::Scalar(ref scalar) => match scalar.value {
            layout::F32 => Some(Reg::f32()),
            layout::F64 => Some(Reg::f64()),
            _ => None
        },
        _ => None
    }
}

fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
    if !ret.layout.is_aggregate() {
        extend_integer_width_mips(ret, 64);
        return;
    }

    let size = ret.layout.size;
    let bits = size.bits();
    if bits <= 128 {
        // Unlike other architectures which return aggregates in registers, MIPS n64 limits the
        // use of float registers to structures (not unions) containing exactly one or two
        // float fields.

        if let layout::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
            if ret.layout.fields.count() == 1 {
                if let Some(reg) = float_reg(cx, ret, 0) {
                    ret.cast_to(reg);
                    return;
                }
            } else if ret.layout.fields.count() == 2 {
                if let Some(reg0) = float_reg(cx, ret, 0) {
                    if let Some(reg1) = float_reg(cx, ret, 1) {
                        ret.cast_to(CastTarget::Pair(reg0, reg1));
                        return;
                    }
                }
            }
        }

        // Cast to a uniform int structure
        ret.cast_to(Uniform {
            unit: bits_to_int_reg(bits),
            total: size
        });
    } else {
        ret.make_indirect();
    }
}

fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
    if !arg.layout.is_aggregate() {
        extend_integer_width_mips(arg, 64);
        return;
    }

    let dl = &cx.tcx.data_layout;
    let size = arg.layout.size;
    let mut prefix = [RegKind::Integer; 8];
    let mut prefix_index = 0;

    match arg.layout.fields {
        layout::FieldPlacement::Array { .. } => {
            // Arrays are passed indirectly
            arg.make_indirect();
            return;
        }
        layout::FieldPlacement::Union(_) => {
            // Unions and are always treated as a series of 64-bit integer chunks
        },
        layout::FieldPlacement::Arbitrary { .. } => {
            // Structures are split up into a series of 64-bit integer chunks, but any aligned
            // doubles not part of another aggregate are passed as floats.
            let mut last_offset = Size::from_bytes(0);

            for i in 0..arg.layout.fields.count() {
                let field = arg.layout.field(cx, i);
                let offset = arg.layout.fields.offset(i);

                // We only care about aligned doubles
                if let layout::Abi::Scalar(ref scalar) = field.abi {
                    if let layout::F64 = scalar.value {
                        if offset.is_abi_aligned(dl.f64_align) {
                            // Skip over enough integers to cover [last_offset, offset)
                            assert!(last_offset.is_abi_aligned(dl.f64_align));
                            prefix_index += ((offset - last_offset).bits() / 64) as usize;

                            if prefix_index >= prefix.len() {
                                break;
                            }

                            prefix[prefix_index] = RegKind::Float;
                            prefix_index += 1;
                            last_offset = offset + Reg::f64().size;
                        }
                    }
                }
            }
        }
    };

    // Extract first 8 chunks as the prefix
    arg.cast_to(CastTarget::ChunkedPrefix {
        prefix: prefix,
        chunk: Size::from_bytes(8),
        total: size
    });
}

pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
    if !fty.ret.is_ignore() {
        classify_ret_ty(cx, &mut fty.ret);
    }

    for arg in &mut fty.args {
        if arg.is_ignore() { continue; }
        classify_arg_ty(cx, arg);
    }
}
<commit_msg>rustc_trans: adjust mips64 abi to use new CastTarget<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use abi::{ArgAttribute, ArgType, CastTarget, FnType, LayoutExt, PassMode, Reg, RegKind, Uniform};
use context::CodegenCx;
use rustc::ty::layout::{self, Size};

fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
    // Always sign extend u32 values on 64-bit mips
    if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
        if let layout::Int(i, signed) = scalar.value {
            if !signed && i.size().bits() == 32 {
                if let PassMode::Direct(ref mut attrs) = arg.mode {
                    attrs.set(ArgAttribute::SExt);
                    return;
                }
            }
        }
    }

    arg.extend_integer_width_to(bits);
}

fn bits_to_int_reg(bits: u64) -> Reg {
    if bits <= 8 {
        Reg::i8()
    } else if bits <= 16 {
        Reg::i16()
    } else if bits <= 32 {
        Reg::i32()
    } else {
        Reg::i64()
    }
}

fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option<Reg> {
    match ret.layout.field(cx, i).abi {
        layout::Abi::Scalar(ref scalar) => match scalar.value {
            layout::F32 => Some(Reg::f32()),
            layout::F64 => Some(Reg::f64()),
            _ => None
        },
        _ => None
    }
}

fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
    if !ret.layout.is_aggregate() {
        extend_integer_width_mips(ret, 64);
        return;
    }

    let size = ret.layout.size;
    let bits = size.bits();
    if bits <= 128 {
        // Unlike other architectures which return aggregates in registers, MIPS n64 limits the
        // use of float registers to structures (not unions) containing exactly one or two
        // float fields.

        if let layout::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
            if ret.layout.fields.count() == 1 {
                if let Some(reg) = float_reg(cx, ret, 0) {
                    ret.cast_to(reg);
                    return;
                }
            } else if ret.layout.fields.count() == 2 {
                if let Some(reg0) = float_reg(cx, ret, 0) {
                    if let Some(reg1) = float_reg(cx, ret, 1) {
                        ret.cast_to(CastTarget::pair(reg0, reg1));
                        return;
                    }
                }
            }
        }

        // Cast to a uniform int structure
        ret.cast_to(Uniform {
            unit: bits_to_int_reg(bits),
            total: size
        });
    } else {
        ret.make_indirect();
    }
}

fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
    if !arg.layout.is_aggregate() {
        extend_integer_width_mips(arg, 64);
        return;
    }

    let dl = &cx.tcx.data_layout;
    let size = arg.layout.size;
    let mut prefix = [None; 8];
    let mut prefix_index = 0;

    match arg.layout.fields {
        layout::FieldPlacement::Array { .. } => {
            // Arrays are passed indirectly
            arg.make_indirect();
            return;
        }
        layout::FieldPlacement::Union(_) => {
            // Unions and are always treated as a series of 64-bit integer chunks
        },
        layout::FieldPlacement::Arbitrary { .. } => {
            // Structures are split up into a series of 64-bit integer chunks, but any aligned
            // doubles not part of another aggregate are passed as floats.
            let mut last_offset = Size::from_bytes(0);

            for i in 0..arg.layout.fields.count() {
                let field = arg.layout.field(cx, i);
                let offset = arg.layout.fields.offset(i);

                // We only care about aligned doubles
                if let layout::Abi::Scalar(ref scalar) = field.abi {
                    if let layout::F64 = scalar.value {
                        if offset.is_abi_aligned(dl.f64_align) {
                            // Insert enough integers to cover [last_offset, offset)
                            assert!(last_offset.is_abi_aligned(dl.f64_align));
                            for _ in 0..((offset - last_offset).bits() / 64)
                                .min((prefix.len() - prefix_index) as u64) {

                                prefix[prefix_index] = Some(RegKind::Integer);
                                prefix_index += 1;
                            }

                            if prefix_index == prefix.len() {
                                break;
                            }

                            prefix[prefix_index] = Some(RegKind::Float);
                            prefix_index += 1;
                            last_offset = offset + Reg::f64().size;
                        }
                    }
                }
            }
        }
    };

    // Extract first 8 chunks as the prefix
    let rest_size = size - Size::from_bytes(8) * prefix_index as u64;
    arg.cast_to(CastTarget {
        prefix: prefix,
        prefix_chunk: Size::from_bytes(8),
        rest: Uniform { unit: Reg::i64(), total: rest_size }
    });
}

pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
    if !fty.ret.is_ignore() {
        classify_ret_ty(cx, &mut fty.ret);
    }

    for arg in &mut fty.args {
        if arg.is_ignore() { continue; }
        classify_arg_ty(cx, arg);
    }
}
<|endoftext|>


<commit_before>#[link(name = "bloomfilter", vers = "0.1", author = "bbrittain")];
#[crate_type = "lib"];

use std;
import bitv = std::bitv;
import sha1 = std::sha1;

#[doc = "Bloom Filter Type"]
type bloomfilter = @{storage: bitv::bitv, capacity: uint, mut count: uint};

fn bloomfilter(capacity: uint) -> bloomfilter {
    io::println("Capacity: " + uint::to_str(capacity, 10u));
    @{storage: bitv::bitv(capacity,false), capacity: capacity, mut count: 0u}
}

fn add(bloomfilter: bloomfilter, elem: str){
 //   log(error,bloomfilter.capacity);
    let sha1 = sha1::sha1();
    sha1.input_str(elem);
    let hashstr = sha1.result();
    sha1.reset();
    let mut i = 0u;
    while i < 20u {
        let loc = (hashstr[i] as uint) % (bloomfilter.capacity - 1u);
        i += 1u;
        bitv::set(bloomfilter.storage, loc, true);
    }
    bloomfilter.count += 1u;
    assert bloomfilter.count <= bloomfilter.capacity;
}

fn contains(bloomfilter: bloomfilter, elem: str) -> bool {
    let sha1 = sha1::sha1();
    sha1.input_str(elem);
    let hashstr = sha1.result();
    sha1.reset();
    let mut i = 0u;
    while i < 20u {
        let loc = (hashstr[i] as uint) % (bloomfilter.capacity - 1u);
        let val = bitv::get(bloomfilter.storage, loc);
        if val == false {
            ret false;
        }
        i += 1u;
    }
    ret true;
}

fn equal(bloomfilter_one: bloomfilter, bloomfilter_two: bloomfilter) -> bool {
    assert bloomfilter_one.capacity == bloomfilter_two.capacity;
    if bitv::equal(bloomfilter_one.storage,bloomfilter_two.storage){
        true
    } else {
        false
    }
}

fn union(bloomfilter_one: bloomfilter, bloomfilter_two: bloomfilter) -> bloomfilter {
    assert bloomfilter_one.capacity == bloomfilter_two.capacity;
    let bloomfilter_new = copy bloomfilter_one;
    bitv::union(bloomfilter_new.storage,bloomfilter_two.storage);
    let count_new = bloomfilter_one.count + bloomfilter_two.count;
    bloomfilter_new.count = count_new;
    bloomfilter_new
}
<commit_msg>allowing external hashing functions<commit_after>#[link(name = "bloomfilter", vers = "0.1", author = "bbrittain")];
#[crate_type = "lib"];

use std;
import bitv = std::bitv;
import sha1 = std::sha1;

#[doc = "Bloom Filter Type"]
type bloomfilter = @{storage: bitv::bitv, capacity: uint, mut count: uint, hash_funcs: [(fn@(str) -> [u8])]};

fn bloomfilter(capacity: uint, hash_funcs: [(fn@(str) -> [u8])]) -> bloomfilter {
    @{storage: bitv::bitv(capacity,false), capacity: capacity, mut count: 0u, hash_funcs: copy hash_funcs}
}

fn add(bloomfilter: bloomfilter, elem: str){
    for vec::each(bloomfilter.hash_funcs) {|func|
        let hashstr:[u8] = func(elem);
            for vec::each(hashstr) {|elm|
                let loc = (elm as uint) % (bloomfilter.capacity - 1u);
                bitv::set(bloomfilter.storage, loc, true);
            }
    }
    bloomfilter.count += 1u;
    assert bloomfilter.count <= bloomfilter.capacity;
}

fn contains(bloomfilter: bloomfilter, elem: str) -> bool {
    for vec::each(bloomfilter.hash_funcs) {|func|
        let hashstr:[u8] = func(elem);
            for vec::each(hashstr) {|elm|
                let loc = (elm as uint) % (bloomfilter.capacity - 1u);
                let val = bitv::get(bloomfilter.storage, loc);
                if val == false {
                    ret false;
                }
                bitv::set(bloomfilter.storage, loc, true);
            }
    }
    ret true;
}

fn equal(bloomfilter_one: bloomfilter, bloomfilter_two: bloomfilter) -> bool {
    assert bloomfilter_one.capacity == bloomfilter_two.capacity;
    if bitv::equal(bloomfilter_one.storage,bloomfilter_two.storage){
        true
    } else {
        false
    }
}

fn union(bloomfilter_one: bloomfilter, bloomfilter_two: bloomfilter) -> bloomfilter {
    assert bloomfilter_one.capacity == bloomfilter_two.capacity;
    let bloomfilter_new = copy bloomfilter_one;
    bitv::union(bloomfilter_new.storage,bloomfilter_two.storage);
    let count_new = bloomfilter_one.count + bloomfilter_two.count;
    bloomfilter_new.count = count_new;
    bloomfilter_new
}
<|endoftext|>


<commit_before>use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{iterators::Pixels, shared_surface::SharedImageSurface};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Input, PrimitiveWithInput};

/// Enumeration of the color channels the displacement map can source.
#[derive(Clone, Copy)]
enum ColorChannel {
    R,
    G,
    B,
    A,
}

/// The `feDisplacementMap` filter primitive.
pub struct FeDisplacementMap {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    scale: f64,
    x_channel_selector: ColorChannel,
    y_channel_selector: ColorChannel,
}

impl Default for FeDisplacementMap {
    /// Constructs a new `DisplacementMap` with empty properties.
    #[inline]
    fn default() -> FeDisplacementMap {
        FeDisplacementMap {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            scale: 0.0,
            x_channel_selector: ColorChannel::A,
            y_channel_selector: ColorChannel::A,
        }
    }
}

impl NodeTrait for FeDisplacementMap {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "in2") => self.in2 = Some(attr.parse(value)?),
                expanded_name!("", "scale") => self.scale = attr.parse(value)?,

                expanded_name!("", "xChannelSelector") => {
                    self.x_channel_selector = attr.parse(value)?
                }

                expanded_name!("", "yChannelSelector") => {
                    self.y_channel_selector = attr.parse(value)?
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeDisplacementMap {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let displacement_input = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&displacement_input)
            .into_irect(draw_ctx);

        // Displacement map's values need to be non-premultiplied.
        let displacement_surface = displacement_input.surface().unpremultiply(bounds)?;

        let (sx, sy) = ctx.paffine().transform_distance(self.scale, self.scale);

        let output_surface = cairo::ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        {
            let cr = cairo::Context::new(&output_surface);

            for (x, y, displacement_pixel) in Pixels::within(&displacement_surface, bounds) {
                let get_value = |channel| match channel {
                    ColorChannel::R => displacement_pixel.r,
                    ColorChannel::G => displacement_pixel.g,
                    ColorChannel::B => displacement_pixel.b,
                    ColorChannel::A => displacement_pixel.a,
                };

                let process = |x| f64::from(x) / 255.0 - 0.5;

                let dx = process(get_value(self.x_channel_selector));
                let dy = process(get_value(self.y_channel_selector));

                let x = f64::from(x);
                let y = f64::from(y);
                let ox = sx * dx;
                let oy = sy * dy;

                // Doing this in a loop doesn't look too bad performance wise, and allows not to
                // manually implement bilinear or other interpolation.
                cr.rectangle(x, y, 1.0, 1.0);
                cr.reset_clip();
                cr.clip();

                input.surface().set_as_source_surface(&cr, -ox, -oy);
                cr.paint();
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::wrap(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        // Performance TODO: this converts in back and forth to linear RGB while technically it's
        // only needed for in2.
        true
    }
}

impl Parse for ColorChannel {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "R" => ColorChannel::R,
            "G" => ColorChannel::G,
            "B" => ColorChannel::B,
            "A" => ColorChannel::A,
        )?)
    }
}
<commit_msg>filters: port displacement to ExclusiveImageSurface<commit_after>use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{iterators::Pixels, shared_surface::ExclusiveImageSurface};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Input, PrimitiveWithInput};

/// Enumeration of the color channels the displacement map can source.
#[derive(Clone, Copy)]
enum ColorChannel {
    R,
    G,
    B,
    A,
}

/// The `feDisplacementMap` filter primitive.
pub struct FeDisplacementMap {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    scale: f64,
    x_channel_selector: ColorChannel,
    y_channel_selector: ColorChannel,
}

impl Default for FeDisplacementMap {
    /// Constructs a new `DisplacementMap` with empty properties.
    #[inline]
    fn default() -> FeDisplacementMap {
        FeDisplacementMap {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            scale: 0.0,
            x_channel_selector: ColorChannel::A,
            y_channel_selector: ColorChannel::A,
        }
    }
}

impl NodeTrait for FeDisplacementMap {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!("", "in2") => self.in2 = Some(attr.parse(value)?),
                expanded_name!("", "scale") => self.scale = attr.parse(value)?,

                expanded_name!("", "xChannelSelector") => {
                    self.x_channel_selector = attr.parse(value)?
                }

                expanded_name!("", "yChannelSelector") => {
                    self.y_channel_selector = attr.parse(value)?
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeDisplacementMap {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let displacement_input = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&displacement_input)
            .into_irect(draw_ctx);

        // Displacement map's values need to be non-premultiplied.
        let displacement_surface = displacement_input.surface().unpremultiply(bounds)?;

        let (sx, sy) = ctx.paffine().transform_distance(self.scale, self.scale);

        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        surface.draw(&mut |cr| {
            for (x, y, displacement_pixel) in Pixels::within(&displacement_surface, bounds) {
                let get_value = |channel| match channel {
                    ColorChannel::R => displacement_pixel.r,
                    ColorChannel::G => displacement_pixel.g,
                    ColorChannel::B => displacement_pixel.b,
                    ColorChannel::A => displacement_pixel.a,
                };

                let process = |x| f64::from(x) / 255.0 - 0.5;

                let dx = process(get_value(self.x_channel_selector));
                let dy = process(get_value(self.y_channel_selector));

                let x = f64::from(x);
                let y = f64::from(y);
                let ox = sx * dx;
                let oy = sy * dy;

                // Doing this in a loop doesn't look too bad performance wise, and allows not to
                // manually implement bilinear or other interpolation.
                cr.rectangle(x, y, 1.0, 1.0);
                cr.reset_clip();
                cr.clip();

                input.surface().set_as_source_surface(&cr, -ox, -oy);
                cr.paint();
            }

            Ok(())
        })?;

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        // Performance TODO: this converts in back and forth to linear RGB while technically it's
        // only needed for in2.
        true
    }
}

impl Parse for ColorChannel {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "R" => ColorChannel::R,
            "G" => ColorChannel::G,
            "B" => ColorChannel::B,
            "A" => ColorChannel::A,
        )?)
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};
use std::path::Path;
use std::str::FromStr;

use anyhow::{anyhow, bail, Context, Result};
use regex::Regex;
use serde::de::Visitor;
use serde::{Deserialize, Serialize, Serializer};

// Note that this type assumes there's no such thing as a relative label;
// `:foo` is assumed to be relative to the repo root, and parses out to equivalent to `//:foo`.
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Label {
    pub repository: Option<String>,
    pub package: Option<String>,
    pub target: String,
}

impl FromStr for Label {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let re = Regex::new(r"^(@[\w\d\-_\.]*)?/{0,2}([\w\d\-_\./]+)?:?([\+\w\d\-_\./]+)$")?;
        let cap = re
            .captures(s)
            .with_context(|| format!("Failed to parse label from string: {}", s))?;

        let repository = cap
            .get(1)
            .map(|m| m.as_str().trim_start_matches('@').to_owned());
        let package = cap.get(2).map(|m| m.as_str().to_owned());
        let mut target = cap.get(3).map(|m| m.as_str().to_owned());

        if target.is_none() {
            if let Some(pkg) = &package {
                target = Some(pkg.clone());
            } else if let Some(repo) = &repository {
                target = Some(repo.clone())
            } else {
                bail!("The label is missing a label")
            }
        }

        // The target should be set at this point
        let target = target.unwrap();

        Ok(Self {
            repository,
            package,
            target,
        })
    }
}

impl Display for Label {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Add the repository
        if let Some(repo) = &self.repository {
            write!(f, "@{}", repo)?;
        }

        write!(f, "//")?;

        // Add the package
        if let Some(pkg) = &self.package {
            write!(f, "{}", pkg)?;
        }

        write!(f, ":{}", self.target)?;

        Ok(())
    }
}

impl Label {
    /// Generates a label appropriate for the passed Path by walking the filesystem to identify its
    /// workspace and package.
    pub fn from_absolute_path(p: &Path) -> Result<Self, anyhow::Error> {
        let mut workspace_root = None;
        let mut package_root = None;
        for ancestor in p.ancestors().skip(1) {
            if package_root.is_none()
                && (ancestor.join("BUILD").exists() || ancestor.join("BUILD.bazel").exists())
            {
                package_root = Some(ancestor);
            }
            if workspace_root.is_none()
                && (ancestor.join("WORKSPACE").exists()
                    || ancestor.join("WORKSPACE.bazel").exists())
            {
                workspace_root = Some(ancestor);
                break;
            }
        }
        match (workspace_root, package_root) {
            (Some(workspace_root), Some(package_root)) => {
                // These unwraps are safe by construction of the ancestors and prefix calls which set up these paths.
                let target = p.strip_prefix(package_root).unwrap();
                let workspace_relative = p.strip_prefix(workspace_root).unwrap();
                let mut package_path = workspace_relative.to_path_buf();
                for _ in target.components() {
                    package_path.pop();
                }

                let package = if package_path.components().count() > 0 {
                    Some(path_to_label_part(&package_path)?)
                } else {
                    None
                };
                let target = path_to_label_part(target)?;

                Ok(Label {
                    repository: None,
                    package,
                    target,
                })
            }
            (Some(_workspace_root), None) => {
                bail!(
                    "Could not identify package for path {}. Maybe you need to add a BUILD.bazel file.",
                    p.display()
                );
            }
            _ => {
                bail!("Could not identify workspace for path {}", p.display());
            }
        }
    }
}

/// Converts a path to a forward-slash-delimited label-appropriate path string.
fn path_to_label_part(path: &Path) -> Result<String, anyhow::Error> {
    let components: Result<Vec<_>, _> = path
        .components()
        .map(|c| {
            c.as_os_str().to_str().ok_or_else(|| {
                anyhow!(
                    "Found non-UTF8 component turning path into label: {}",
                    path.display()
                )
            })
        })
        .collect();
    Ok(components?.join("/"))
}

impl Serialize for Label {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.repr())
    }
}

struct LabelVisitor;
impl<'de> Visitor<'de> for LabelVisitor {
    type Value = Label;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("Expected string value of `{name} {version}`.")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Label::from_str(v).map_err(E::custom)
    }
}

impl<'de> Deserialize<'de> for Label {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_str(LabelVisitor)
    }
}

impl Label {
    pub fn repr(&self) -> String {
        self.to_string()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use spectral::prelude::*;
    use std::fs::{create_dir_all, File};
    use tempfile::tempdir;

    #[test]
    fn full_label() {
        let label = Label::from_str("@repo//package/sub_package:target").unwrap();
        assert_eq!(label.to_string(), "@repo//package/sub_package:target");
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package.unwrap(), "package/sub_package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn no_repository() {
        let label = Label::from_str("//package:target").unwrap();
        assert_eq!(label.to_string(), "//package:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn no_slashes() {
        let label = Label::from_str("package:target").unwrap();
        assert_eq!(label.to_string(), "//package:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label() {
        let label = Label::from_str("@repo//:target").unwrap();
        assert_eq!(label.to_string(), "@repo//:target");
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label_no_repository() {
        let label = Label::from_str("//:target").unwrap();
        assert_eq!(label.to_string(), "//:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label_no_slashes() {
        let label = Label::from_str(":target").unwrap();
        assert_eq!(label.to_string(), "//:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn full_label_with_slash_after_colon() {
        let label = Label::from_str("@repo//package/sub_package:subdir/target").unwrap();
        assert_eq!(
            label.to_string(),
            "@repo//package/sub_package:subdir/target"
        );
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package.unwrap(), "package/sub_package");
        assert_eq!(label.target, "subdir/target");
    }

    #[test]
    fn invalid_double_colon() {
        assert!(Label::from_str("::target").is_err());
    }

    #[test]
    fn invalid_double_at() {
        assert!(Label::from_str("@@repo//pkg:target").is_err());
    }

    #[test]
    #[ignore = "This currently fails. The Label parsing logic needs to be updated"]
    fn invalid_no_double_slash() {
        assert!(Label::from_str("@repo:target").is_err());
    }

    #[test]
    fn from_absolute_path_exists() {
        let dir = tempdir().unwrap();
        let workspace = dir.path().join("WORKSPACE.bazel");
        let build_file = dir.path().join("parent").join("child").join("BUILD.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&workspace).unwrap();
            File::create(&build_file).unwrap();
            File::create(&actual_file).unwrap();
        }
        let label = Label::from_absolute_path(&actual_file).unwrap();
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "parent/child");
        assert_eq!(label.target, "grandchild/greatgrandchild")
    }

    #[test]
    fn from_absolute_path_no_workspace() {
        let dir = tempdir().unwrap();
        let build_file = dir.path().join("parent").join("child").join("BUILD.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&build_file).unwrap();
            File::create(&actual_file).unwrap();
        }
        let err = Label::from_absolute_path(&actual_file)
            .unwrap_err()
            .to_string();
        assert_that(&err).contains("Could not identify workspace");
        assert_that(&err).contains(format!("{}", actual_file.display()).as_str());
    }

    #[test]
    fn from_absolute_path_no_build_file() {
        let dir = tempdir().unwrap();
        let workspace = dir.path().join("WORKSPACE.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&workspace).unwrap();
            File::create(&actual_file).unwrap();
        }
        let err = Label::from_absolute_path(&actual_file)
            .unwrap_err()
            .to_string();
        assert_that(&err).contains("Could not identify package");
        assert_that(&err).contains("Maybe you need to add a BUILD.bazel file");
        assert_that(&err).contains(format!("{}", actual_file.display()).as_str());
    }
}
<commit_msg>fix: Fix issue with wasi-0.11.0+wasi-snapshot-preview1 (#1632)<commit_after>use std::fmt::{self, Display};
use std::path::Path;
use std::str::FromStr;

use anyhow::{anyhow, bail, Context, Result};
use regex::Regex;
use serde::de::Visitor;
use serde::{Deserialize, Serialize, Serializer};

// Note that this type assumes there's no such thing as a relative label;
// `:foo` is assumed to be relative to the repo root, and parses out to equivalent to `//:foo`.
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Label {
    pub repository: Option<String>,
    pub package: Option<String>,
    pub target: String,
}

impl FromStr for Label {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let re = Regex::new(r"^(@[\w\d\-_\.]*)?/{0,2}([\w\d\-_\./+]+)?(:([\+\w\d\-_\./]+))?$")?;
        let cap = re
            .captures(s)
            .with_context(|| format!("Failed to parse label from string: {}", s))?;

        let repository = cap
            .get(1)
            .map(|m| m.as_str().trim_start_matches('@').to_owned());

        let package = cap.get(2).map(|m| m.as_str().to_owned());
        let mut target = cap.get(4).map(|m| m.as_str().to_owned());

        if target.is_none() {
            if let Some(pkg) = &package {
                target = Some(pkg.clone());
            } else if let Some(repo) = &repository {
                target = Some(repo.clone())
            } else {
                bail!("The label is missing a label")
            }
        }

        // The target should be set at this point
        let target = target.unwrap();

        Ok(Self {
            repository,
            package,
            target,
        })
    }
}

impl Display for Label {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Add the repository
        if let Some(repo) = &self.repository {
            write!(f, "@{}", repo)?;
        }

        write!(f, "//")?;

        // Add the package
        if let Some(pkg) = &self.package {
            write!(f, "{}", pkg)?;
        }

        write!(f, ":{}", self.target)?;

        Ok(())
    }
}

impl Label {
    /// Generates a label appropriate for the passed Path by walking the filesystem to identify its
    /// workspace and package.
    pub fn from_absolute_path(p: &Path) -> Result<Self, anyhow::Error> {
        let mut workspace_root = None;
        let mut package_root = None;
        for ancestor in p.ancestors().skip(1) {
            if package_root.is_none()
                && (ancestor.join("BUILD").exists() || ancestor.join("BUILD.bazel").exists())
            {
                package_root = Some(ancestor);
            }
            if workspace_root.is_none()
                && (ancestor.join("WORKSPACE").exists()
                    || ancestor.join("WORKSPACE.bazel").exists())
            {
                workspace_root = Some(ancestor);
                break;
            }
        }
        match (workspace_root, package_root) {
            (Some(workspace_root), Some(package_root)) => {
                // These unwraps are safe by construction of the ancestors and prefix calls which set up these paths.
                let target = p.strip_prefix(package_root).unwrap();
                let workspace_relative = p.strip_prefix(workspace_root).unwrap();
                let mut package_path = workspace_relative.to_path_buf();
                for _ in target.components() {
                    package_path.pop();
                }

                let package = if package_path.components().count() > 0 {
                    Some(path_to_label_part(&package_path)?)
                } else {
                    None
                };
                let target = path_to_label_part(target)?;

                Ok(Label {
                    repository: None,
                    package,
                    target,
                })
            }
            (Some(_workspace_root), None) => {
                bail!(
                    "Could not identify package for path {}. Maybe you need to add a BUILD.bazel file.",
                    p.display()
                );
            }
            _ => {
                bail!("Could not identify workspace for path {}", p.display());
            }
        }
    }
}

/// Converts a path to a forward-slash-delimited label-appropriate path string.
fn path_to_label_part(path: &Path) -> Result<String, anyhow::Error> {
    let components: Result<Vec<_>, _> = path
        .components()
        .map(|c| {
            c.as_os_str().to_str().ok_or_else(|| {
                anyhow!(
                    "Found non-UTF8 component turning path into label: {}",
                    path.display()
                )
            })
        })
        .collect();
    Ok(components?.join("/"))
}

impl Serialize for Label {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.repr())
    }
}

struct LabelVisitor;
impl<'de> Visitor<'de> for LabelVisitor {
    type Value = Label;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("Expected string value of `{name} {version}`.")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Label::from_str(v).map_err(E::custom)
    }
}

impl<'de> Deserialize<'de> for Label {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_str(LabelVisitor)
    }
}

impl Label {
    pub fn repr(&self) -> String {
        self.to_string()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use spectral::prelude::*;
    use std::fs::{create_dir_all, File};
    use tempfile::tempdir;

    #[test]
    fn full_label() {
        let label = Label::from_str("@repo//package/sub_package:target").unwrap();
        assert_eq!(label.to_string(), "@repo//package/sub_package:target");
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package.unwrap(), "package/sub_package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn no_repository() {
        let label = Label::from_str("//package:target").unwrap();
        assert_eq!(label.to_string(), "//package:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn no_slashes() {
        let label = Label::from_str("package:target").unwrap();
        assert_eq!(label.to_string(), "//package:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "package");
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label() {
        let label = Label::from_str("@repo//:target").unwrap();
        assert_eq!(label.to_string(), "@repo//:target");
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label_no_repository() {
        let label = Label::from_str("//:target").unwrap();
        assert_eq!(label.to_string(), "//:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn root_label_no_slashes() {
        let label = Label::from_str(":target").unwrap();
        assert_eq!(label.to_string(), "//:target");
        assert_eq!(label.repository, None);
        assert_eq!(label.package, None);
        assert_eq!(label.target, "target");
    }

    #[test]
    fn full_label_with_slash_after_colon() {
        let label = Label::from_str("@repo//package/sub_package:subdir/target").unwrap();
        assert_eq!(
            label.to_string(),
            "@repo//package/sub_package:subdir/target"
        );
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(label.package.unwrap(), "package/sub_package");
        assert_eq!(label.target, "subdir/target");
    }

    #[test]
    fn label_contains_plus() {
        let label = Label::from_str("@repo//vendor/wasi-0.11.0+wasi-snapshot-preview1:BUILD.bazel")
            .unwrap();
        assert_eq!(label.repository.unwrap(), "repo");
        assert_eq!(
            label.package.unwrap(),
            "vendor/wasi-0.11.0+wasi-snapshot-preview1"
        );
        assert_eq!(label.target, "BUILD.bazel");
    }

    #[test]
    fn invalid_double_colon() {
        assert!(Label::from_str("::target").is_err());
    }

    #[test]
    fn invalid_double_at() {
        assert!(Label::from_str("@@repo//pkg:target").is_err());
    }

    #[test]
    #[ignore = "This currently fails. The Label parsing logic needs to be updated"]
    fn invalid_no_double_slash() {
        assert!(Label::from_str("@repo:target").is_err());
    }

    #[test]
    fn from_absolute_path_exists() {
        let dir = tempdir().unwrap();
        let workspace = dir.path().join("WORKSPACE.bazel");
        let build_file = dir.path().join("parent").join("child").join("BUILD.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&workspace).unwrap();
            File::create(&build_file).unwrap();
            File::create(&actual_file).unwrap();
        }
        let label = Label::from_absolute_path(&actual_file).unwrap();
        assert_eq!(label.repository, None);
        assert_eq!(label.package.unwrap(), "parent/child");
        assert_eq!(label.target, "grandchild/greatgrandchild")
    }

    #[test]
    fn from_absolute_path_no_workspace() {
        let dir = tempdir().unwrap();
        let build_file = dir.path().join("parent").join("child").join("BUILD.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&build_file).unwrap();
            File::create(&actual_file).unwrap();
        }
        let err = Label::from_absolute_path(&actual_file)
            .unwrap_err()
            .to_string();
        assert_that(&err).contains("Could not identify workspace");
        assert_that(&err).contains(format!("{}", actual_file.display()).as_str());
    }

    #[test]
    fn from_absolute_path_no_build_file() {
        let dir = tempdir().unwrap();
        let workspace = dir.path().join("WORKSPACE.bazel");
        let subdir = dir.path().join("parent").join("child").join("grandchild");
        let actual_file = subdir.join("greatgrandchild");
        create_dir_all(subdir).unwrap();
        {
            File::create(&workspace).unwrap();
            File::create(&actual_file).unwrap();
        }
        let err = Label::from_absolute_path(&actual_file)
            .unwrap_err()
            .to_string();
        assert_that(&err).contains("Could not identify package");
        assert_that(&err).contains("Maybe you need to add a BUILD.bazel file");
        assert_that(&err).contains(format!("{}", actual_file.display()).as_str());
    }
}
<|endoftext|>


<commit_before>//! Renderer for macro invocations.

use hir::HasSource;
use ide_db::SymbolKind;
use syntax::display::macro_label;

use crate::{
    context::CallKind,
    item::{CompletionItem, CompletionKind, ImportEdit},
    render::RenderContext,
};

pub(crate) fn render_macro(
    ctx: RenderContext<'_>,
    import_to_add: Option<ImportEdit>,
    name: hir::Name,
    macro_: hir::MacroDef,
) -> Option<CompletionItem> {
    let _p = profile::span("render_macro");
    MacroRender::new(ctx, name, macro_).render(import_to_add)
}

#[derive(Debug)]
struct MacroRender<'a> {
    ctx: RenderContext<'a>,
    name: String,
    macro_: hir::MacroDef,
    docs: Option<hir::Documentation>,
    bra: &'static str,
    ket: &'static str,
}

impl<'a> MacroRender<'a> {
    fn new(ctx: RenderContext<'a>, name: hir::Name, macro_: hir::MacroDef) -> MacroRender<'a> {
        let name = name.to_string();
        let docs = ctx.docs(macro_);
        let docs_str = docs.as_ref().map_or("", |s| s.as_str());
        let (bra, ket) = guess_macro_braces(&name, docs_str);

        MacroRender { ctx, name, macro_, docs, bra, ket }
    }

    fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
        let mut item =
            CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label());
        item.kind(SymbolKind::Macro)
            .set_documentation(self.docs.clone())
            .set_deprecated(self.ctx.is_deprecated(self.macro_))
            .add_import(import_to_add)
            .set_detail(self.detail());

        let needs_bang = self.needs_bang();
        match self.ctx.snippet_cap() {
            Some(cap) if needs_bang => {
                let snippet = self.snippet();
                let lookup = self.lookup();
                item.insert_snippet(cap, snippet).lookup_by(lookup);
            }
            None if needs_bang => {
                item.insert_text(self.banged_name());
            }
            _ => {
                cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
                item.insert_text(&self.name);
            }
        };

        Some(item.build())
    }

    fn needs_bang(&self) -> bool {
        !self.ctx.completion.in_use_tree()
            && !matches!(self.ctx.completion.path_call_kind(), Some(CallKind::Mac))
    }

    fn label(&self) -> String {
        if self.needs_bang() && self.ctx.snippet_cap().is_some() {
            format!("{}!{}…{}", self.name, self.bra, self.ket)
        } else if self.macro_.kind() == hir::MacroKind::Derive {
            self.name.to_string()
        } else {
            self.banged_name()
        }
    }

    fn snippet(&self) -> String {
        format!("{}!{}$0{}", self.name, self.bra, self.ket)
    }

    fn lookup(&self) -> String {
        self.banged_name()
    }

    fn banged_name(&self) -> String {
        format!("{}!", self.name)
    }

    fn detail(&self) -> Option<String> {
        let ast_node = self.macro_.source(self.ctx.db())?.value.left()?;
        Some(macro_label(&ast_node))
    }
}

fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) {
    let mut votes = [0, 0, 0];
    for (idx, s) in docs.match_indices(&macro_name) {
        let (before, after) = (&docs[..idx], &docs[idx + s.len()..]);
        // Ensure to match the full word
        if after.starts_with('!')
            && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric())
        {
            // It may have spaces before the braces like `foo! {}`
            match after[1..].chars().find(|&c| !c.is_whitespace()) {
                Some('{') => votes[0] += 1,
                Some('[') => votes[1] += 1,
                Some('(') => votes[2] += 1,
                _ => {}
            }
        }
    }

    // Insert a space before `{}`.
    // We prefer the last one when some votes equal.
    let (_vote, (bra, ket)) = votes
        .iter()
        .zip(&[(" {", "}"), ("[", "]"), ("(", ")")])
        .max_by_key(|&(&vote, _)| vote)
        .unwrap();
    (*bra, *ket)
}

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

    #[test]
    fn dont_insert_macro_call_parens_unncessary() {
        cov_mark::check!(dont_insert_macro_call_parens_unncessary);
        check_edit(
            "frobnicate!",
            r#"
//- /main.rs crate:main deps:foo
use foo::$0;
//- /foo/lib.rs crate:foo
#[macro_export]
macro_rules! frobnicate { () => () }
"#,
            r#"
use foo::frobnicate;
"#,
        );

        check_edit(
            "frobnicate!",
            r#"
macro_rules! frobnicate { () => () }
fn main() { frob$0!(); }
"#,
            r#"
macro_rules! frobnicate { () => () }
fn main() { frobnicate!(); }
"#,
        );
    }

    #[test]
    fn guesses_macro_braces() {
        check_edit(
            "vec!",
            r#"
/// Creates a [`Vec`] containing the arguments.
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
macro_rules! vec { () => {} }

fn main() { v$0 }
"#,
            r#"
/// Creates a [`Vec`] containing the arguments.
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
macro_rules! vec { () => {} }

fn main() { vec![$0] }
"#,
        );

        check_edit(
            "foo!",
            r#"
/// Foo
///
/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
/// call as `let _=foo!  { hello world };`
macro_rules! foo { () => {} }
fn main() { $0 }
"#,
            r#"
/// Foo
///
/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
/// call as `let _=foo!  { hello world };`
macro_rules! foo { () => {} }
fn main() { foo! {$0} }
"#,
        )
    }
}
<commit_msg>fix: add `!` to macro completions with existing arg<commit_after>//! Renderer for macro invocations.

use hir::HasSource;
use ide_db::SymbolKind;
use syntax::display::macro_label;

use crate::{
    context::CallKind,
    item::{CompletionItem, CompletionKind, ImportEdit},
    render::RenderContext,
};

pub(crate) fn render_macro(
    ctx: RenderContext<'_>,
    import_to_add: Option<ImportEdit>,
    name: hir::Name,
    macro_: hir::MacroDef,
) -> Option<CompletionItem> {
    let _p = profile::span("render_macro");
    MacroRender::new(ctx, name, macro_).render(import_to_add)
}

#[derive(Debug)]
struct MacroRender<'a> {
    ctx: RenderContext<'a>,
    name: String,
    macro_: hir::MacroDef,
    docs: Option<hir::Documentation>,
    bra: &'static str,
    ket: &'static str,
}

impl<'a> MacroRender<'a> {
    fn new(ctx: RenderContext<'a>, name: hir::Name, macro_: hir::MacroDef) -> MacroRender<'a> {
        let name = name.to_string();
        let docs = ctx.docs(macro_);
        let docs_str = docs.as_ref().map_or("", |s| s.as_str());
        let (bra, ket) = guess_macro_braces(&name, docs_str);

        MacroRender { ctx, name, macro_, docs, bra, ket }
    }

    fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
        let mut item =
            CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label());
        item.kind(SymbolKind::Macro)
            .set_documentation(self.docs.clone())
            .set_deprecated(self.ctx.is_deprecated(self.macro_))
            .add_import(import_to_add)
            .set_detail(self.detail());

        let needs_bang = !(self.ctx.completion.in_use_tree()
            || matches!(self.ctx.completion.path_call_kind(), Some(CallKind::Mac)));
        let has_parens = self.ctx.completion.path_call_kind().is_some();

        match self.ctx.snippet_cap() {
            Some(cap) if needs_bang && !has_parens => {
                let snippet = format!("{}!{}$0{}", self.name, self.bra, self.ket);
                let lookup = self.banged_name();
                item.insert_snippet(cap, snippet).lookup_by(lookup);
            }
            _ if needs_bang => {
                let lookup = self.banged_name();
                item.insert_text(self.banged_name()).lookup_by(lookup);
            }
            _ => {
                cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
                item.insert_text(&self.name);
            }
        };

        Some(item.build())
    }

    fn needs_bang(&self) -> bool {
        !self.ctx.completion.in_use_tree()
            && !matches!(self.ctx.completion.path_call_kind(), Some(CallKind::Mac))
    }

    fn label(&self) -> String {
        if self.needs_bang() && self.ctx.snippet_cap().is_some() {
            format!("{}!{}…{}", self.name, self.bra, self.ket)
        } else if self.macro_.kind() == hir::MacroKind::Derive {
            self.name.to_string()
        } else {
            self.banged_name()
        }
    }

    fn banged_name(&self) -> String {
        format!("{}!", self.name)
    }

    fn detail(&self) -> Option<String> {
        let ast_node = self.macro_.source(self.ctx.db())?.value.left()?;
        Some(macro_label(&ast_node))
    }
}

fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) {
    let mut votes = [0, 0, 0];
    for (idx, s) in docs.match_indices(&macro_name) {
        let (before, after) = (&docs[..idx], &docs[idx + s.len()..]);
        // Ensure to match the full word
        if after.starts_with('!')
            && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric())
        {
            // It may have spaces before the braces like `foo! {}`
            match after[1..].chars().find(|&c| !c.is_whitespace()) {
                Some('{') => votes[0] += 1,
                Some('[') => votes[1] += 1,
                Some('(') => votes[2] += 1,
                _ => {}
            }
        }
    }

    // Insert a space before `{}`.
    // We prefer the last one when some votes equal.
    let (_vote, (bra, ket)) = votes
        .iter()
        .zip(&[(" {", "}"), ("[", "]"), ("(", ")")])
        .max_by_key(|&(&vote, _)| vote)
        .unwrap();
    (*bra, *ket)
}

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

    #[test]
    fn dont_insert_macro_call_parens_unncessary() {
        cov_mark::check!(dont_insert_macro_call_parens_unncessary);
        check_edit(
            "frobnicate!",
            r#"
//- /main.rs crate:main deps:foo
use foo::$0;
//- /foo/lib.rs crate:foo
#[macro_export]
macro_rules! frobnicate { () => () }
"#,
            r#"
use foo::frobnicate;
"#,
        );

        check_edit(
            "frobnicate!",
            r#"
macro_rules! frobnicate { () => () }
fn main() { frob$0!(); }
"#,
            r#"
macro_rules! frobnicate { () => () }
fn main() { frobnicate!(); }
"#,
        );
    }

    #[test]
    fn add_bang_to_parens() {
        check_edit(
            "frobnicate!",
            r#"
macro_rules! frobnicate { () => () }
fn main() {
    frob$0()
}
"#,
            r#"
macro_rules! frobnicate { () => () }
fn main() {
    frobnicate!()
}
"#,
        );
    }

    #[test]
    fn guesses_macro_braces() {
        check_edit(
            "vec!",
            r#"
/// Creates a [`Vec`] containing the arguments.
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
macro_rules! vec { () => {} }

fn main() { v$0 }
"#,
            r#"
/// Creates a [`Vec`] containing the arguments.
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
macro_rules! vec { () => {} }

fn main() { vec![$0] }
"#,
        );

        check_edit(
            "foo!",
            r#"
/// Foo
///
/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
/// call as `let _=foo!  { hello world };`
macro_rules! foo { () => {} }
fn main() { $0 }
"#,
            r#"
/// Foo
///
/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
/// call as `let _=foo!  { hello world };`
macro_rules! foo { () => {} }
fn main() { foo! {$0} }
"#,
        )
    }
}
<|endoftext|>


<commit_before>use super::*;

/// New vec is bigger than old vec.
fn grow_merkle_cache(
    old_bytes: &[u8],
    old_flags: &[bool],
    from_height: usize,
    to_height: usize,
) -> Option<Vec<u8>> {
    let to_nodes = (1 << to_height.next_power_of_two()) - 1;

    // Determine the size of our new tree. It is not just a simple `1 << to_height` as there can be
    // an arbitrary number of bytes in `old_bytes` leaves.
    let new_byte_count = {
        let additional_from_nodes = old_bytes.len() / HASHSIZE - ((1 << from_height) - 1);
        ((1 << to_height + additional_from_nodes) - 1) * HASHSIZE
    };
    dbg!(new_byte_count / 32);

    let mut bytes = vec![0; new_byte_count];
    let mut flags = vec![true; to_nodes];

    let leaf_level = from_height - 1;

    // Loop through all internal levels of the tree (skipping the final, leaves level).
    for i in 0..from_height - 1 as usize {
        dbg!(i);
        dbg!(bytes.len());
        // If we're on the leaf slice, grab the first byte and all the of the bytes after that.
        // This is required because we can have an arbitrary number of bytes at the leaf level
        // (e.g., the case where there are subtrees as leaves).
        //
        // If we're not on a leaf level, the number of nodes is fixed and known.
        let old_slice = if i == leaf_level {
            old_bytes.get(first_byte_at_height(i)..)
        } else {
            old_bytes.get(byte_range_at_height(i))
        }?;

        dbg!(byte_range_at_height(i + to_height - from_height));

        let new_slice = bytes
            .get_mut(byte_range_at_height(i + to_height - from_height))?
            .get_mut(0..old_slice.len())?;

        new_slice.copy_from_slice(old_slice);
    }

    Some(bytes)
}

fn byte_range_at_height(h: usize) -> Range<usize> {
    first_byte_at_height(h)..last_node_at_height(h) * HASHSIZE
}

fn first_byte_at_height(h: usize) -> usize {
    first_node_at_height(h) * HASHSIZE
}

fn first_node_at_height(h: usize) -> usize {
    (1 << h) - 1
}

fn last_node_at_height(h: usize) -> usize {
    (1 << (h + 1)) - 1
}

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

    #[test]
    fn can_grow() {
        let from: usize = 7;
        let to: usize = 15;

        let old_bytes = vec![42; from * HASHSIZE];
        let old_flags = vec![false; from];

        let new = grow_merkle_cache(
            &old_bytes,
            &old_flags,
            (from + 1).trailing_zeros() as usize,
            (to + 1).trailing_zeros() as usize,
        )
        .unwrap();

        println!("{:?}", new);
        let mut expected = vec![];
        // First level
        expected.append(&mut vec![0; 32]);
        // Second level
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![0; 32]);
        // Third level
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        // Fourth level
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);

        assert_eq!(expected, new);
    }
}
<commit_msg>Tidy, remove debug prints<commit_after>use super::*;

/// New vec is bigger than old vec.
fn grow_merkle_cache(
    old_bytes: &[u8],
    old_flags: &[bool],
    from_height: usize,
    to_height: usize,
) -> Option<Vec<u8>> {
    let to_nodes = (1 << to_height.next_power_of_two()) - 1;

    // Determine the size of our new tree. It is not just a simple `1 << to_height` as there can be
    // an arbitrary number of bytes in `old_bytes` leaves.
    let new_byte_count = {
        let additional_from_nodes = old_bytes.len() / HASHSIZE - ((1 << from_height) - 1);
        ((1 << to_height + additional_from_nodes) - 1) * HASHSIZE
    };
    dbg!(new_byte_count / 32);

    let mut bytes = vec![0; new_byte_count];
    let mut flags = vec![true; to_nodes];

    let leaf_level = from_height - 1;

    // Loop through all internal levels of the tree (skipping the final, leaves level).
    for i in 0..from_height - 1 as usize {
        // If we're on the leaf slice, grab the first byte and all the of the bytes after that.
        // This is required because we can have an arbitrary number of bytes at the leaf level
        // (e.g., the case where there are subtrees as leaves).
        //
        // If we're not on a leaf level, the number of nodes is fixed and known.
        let old_slice = if i == leaf_level {
            old_bytes.get(first_byte_at_height(i)..)
        } else {
            old_bytes.get(byte_range_at_height(i))
        }?;

        let new_slice = bytes
            .get_mut(byte_range_at_height(i + to_height - from_height))?
            .get_mut(0..old_slice.len())?;

        new_slice.copy_from_slice(old_slice);
    }

    Some(bytes)
}

/*
fn copy_bytes(
    from_range: Range<usize>,
    to_range: Range<usize>,
    from: &[u8],
    to: &mut Vec<u8>,
) -> Option<()> {
    let from_slice = from.get(node_range_to_byte_range(from_range));

    let to_slice = to
        .get_mut(byte_range_at_height(i + to_height - from_height))?
        .get_mut(0..old_slice.len())?;

    Ok(())
}
*/

fn node_range_to_byte_range(node_range: Range<usize>) -> Range<usize> {
    node_range.start * HASHSIZE..node_range.end * HASHSIZE
}

fn byte_range_at_height(h: usize) -> Range<usize> {
    first_byte_at_height(h)..last_node_at_height(h) * HASHSIZE
}

fn first_byte_at_height(h: usize) -> usize {
    first_node_at_height(h) * HASHSIZE
}

fn first_node_at_height(h: usize) -> usize {
    (1 << h) - 1
}

fn last_node_at_height(h: usize) -> usize {
    (1 << (h + 1)) - 1
}

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

    #[test]
    fn can_grow() {
        let from: usize = 7;
        let to: usize = 15;

        let old_bytes = vec![42; from * HASHSIZE];
        let old_flags = vec![false; from];

        let new = grow_merkle_cache(
            &old_bytes,
            &old_flags,
            (from + 1).trailing_zeros() as usize,
            (to + 1).trailing_zeros() as usize,
        )
        .unwrap();

        println!("{:?}", new);
        let mut expected = vec![];
        // First level
        expected.append(&mut vec![0; 32]);
        // Second level
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![0; 32]);
        // Third level
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![42; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        // Fourth level
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);
        expected.append(&mut vec![0; 32]);

        assert_eq!(expected, new);
    }
}
<|endoftext|>


<commit_before><commit_msg>factor::miller_rabin::tests: small_composites → small_semiprimes<commit_after><|endoftext|>


<commit_before>use std::fmt::{Display, Error, Formatter};
use board;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Coordinate {
    pub row: usize,
    pub col: usize,
}

impl Coordinate {
    pub fn move_in(&self, dir: Direction, delta: usize) -> Option<Coordinate> {
        match dir {
            Direction::Up => if self.row >= delta { Some(Coordinate{row: self.row - delta, col: self.col}) } else { None },
            Direction::Down => if self.row + delta < board::NUM_ROWS { Some(Coordinate{row: self.row + delta, col: self.col}) } else { None },
            Direction::Left => if self.col >= delta { Some(Coordinate{row: self.row, col: self.col - delta}) } else { None },
            Direction::Right => if self.col + delta < board::NUM_COLS { Some(Coordinate{row: self.row, col: self.col + delta}) } else { None },
        }
    }

    fn unchecked_move_in(&self, dir: Direction, delta: usize) -> Coordinate {
        match dir {
            Direction::Up => Coordinate{row: self.row - delta, col: self.col},
            Direction::Down => Coordinate{row: self.row + delta, col: self.col},
            Direction::Left => Coordinate{row: self.row, col: self.col - delta},
            Direction::Right => Coordinate{row: self.row, col: self.col + delta},
        }
    }

    pub fn induces_board_type(&self) -> bool {
        // The lower left corner of the board.
        self.col < 2 && self.row >= 1
    }
}

#[derive(Copy, Clone)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}
pub const POSSIBLE_DIRECTIONS: [Direction; 4] = [
    Direction::Up,
    Direction::Down,
    Direction::Left,
    Direction::Right,
];

#[derive(Copy, Clone, Debug)]
pub enum MoveType {
    Single,
    OneUp,
    OneDown,
    OneLeft,
    OneRight,
    TwoUp,
    TwoDown,
    TwoLeft,
    TwoRight,
    UpAndDown,
    LeftAndRight,
}
pub const POSSIBLE_MOVE_TYPES: [MoveType; 11] = [
    MoveType::Single,
    MoveType::OneUp,
    MoveType::OneDown,
    MoveType::OneLeft,
    MoveType::OneRight,
    MoveType::TwoUp,
    MoveType::TwoDown,
    MoveType::TwoLeft,
    MoveType::TwoRight,
    MoveType::UpAndDown,
    MoveType::LeftAndRight,
];

#[derive(Copy, Clone)]
pub struct Move {
    pub coord: Coordinate,
    move_type: MoveType,
    pub old_board_type: Option<board::BoardType>,
    pub new_board_type: Option<board::BoardType>,
}

impl Move {
    pub fn new(coord: Coordinate, move_type: MoveType, old_board_type: Option<board::BoardType>) -> Option<Move> {
        let c = Move{coord: coord, move_type: move_type, old_board_type: old_board_type, new_board_type: None};
        if c.in_bounds() { Some(c) } else { None }
    }

    pub fn with_board_type(&self, new_board_type: board::BoardType) -> Move {
        Move{new_board_type: Some(new_board_type), .. *self}
    }

    pub fn in_bounds(&self) -> bool {
        match self.move_type {
            MoveType::Single => true,
            MoveType::OneUp => self.coord.row >= 1,
            MoveType::OneDown => self.coord.row < board::NUM_ROWS - 1,
            MoveType::OneLeft => self.coord.col >= 1,
            MoveType::OneRight => self.coord.col < board::NUM_COLS - 1,
            MoveType::TwoUp => self.coord.row >= 2,
            MoveType::TwoDown => self.coord.row < board::NUM_ROWS - 2,
            MoveType::TwoLeft => self.coord.col >= 2,
            MoveType::TwoRight => self.coord.col < board::NUM_COLS - 2,
            MoveType::UpAndDown => self.coord.row >= 1 && self.coord.row < board::NUM_ROWS - 1,
            MoveType::LeftAndRight => self.coord.col >= 1 && self.coord.col < board::NUM_COLS - 1,
        }
    }

    pub fn extensions(&self) -> Vec<Coordinate> {
        match self.move_type {
            MoveType::Single => vec![],
            MoveType::OneUp => vec![self.coord.unchecked_move_in(Direction::Up, 1)],
            MoveType::OneDown => vec![self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::OneLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1)],
            MoveType::OneRight => vec![self.coord.unchecked_move_in(Direction::Right, 1)],
            MoveType::TwoUp => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Up, 2)],
            MoveType::TwoDown => vec![self.coord.unchecked_move_in(Direction::Down, 1), self.coord.unchecked_move_in(Direction::Down, 2)],
            MoveType::TwoLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Left, 2)],
            MoveType::TwoRight => vec![self.coord.unchecked_move_in(Direction::Right, 1), self.coord.unchecked_move_in(Direction::Right, 2)],
            MoveType::UpAndDown => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::LeftAndRight => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Right, 1)],
        }
    }
}

impl Display for Move {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
        match self.new_board_type {
            Some(bt) => write!(formatter, "{:?} at {:?} (Board type {:?})", self.move_type, self.coord, bt),
            None => write!(formatter, "{:?} at {:?}", self.move_type, self.coord),
        }
    }
}
<commit_msg>Coordinate: Implement Display<commit_after>use std::fmt::{Display, Error, Formatter};
use board;

#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Coordinate {
    pub row: usize,
    pub col: usize,
}

impl Coordinate {
    pub fn move_in(&self, dir: Direction, delta: usize) -> Option<Coordinate> {
        match dir {
            Direction::Up => if self.row >= delta { Some(Coordinate{row: self.row - delta, col: self.col}) } else { None },
            Direction::Down => if self.row + delta < board::NUM_ROWS { Some(Coordinate{row: self.row + delta, col: self.col}) } else { None },
            Direction::Left => if self.col >= delta { Some(Coordinate{row: self.row, col: self.col - delta}) } else { None },
            Direction::Right => if self.col + delta < board::NUM_COLS { Some(Coordinate{row: self.row, col: self.col + delta}) } else { None },
        }
    }

    fn unchecked_move_in(&self, dir: Direction, delta: usize) -> Coordinate {
        match dir {
            Direction::Up => Coordinate{row: self.row - delta, col: self.col},
            Direction::Down => Coordinate{row: self.row + delta, col: self.col},
            Direction::Left => Coordinate{row: self.row, col: self.col - delta},
            Direction::Right => Coordinate{row: self.row, col: self.col + delta},
        }
    }

    pub fn induces_board_type(&self) -> bool {
        // The lower left corner of the board.
        self.col < 2 && self.row >= 1
    }
}

impl Display for Coordinate {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
        write!(formatter, "(row {}, col {})", self.row, self.col)
    }
}

#[derive(Copy, Clone)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}
pub const POSSIBLE_DIRECTIONS: [Direction; 4] = [
    Direction::Up,
    Direction::Down,
    Direction::Left,
    Direction::Right,
];

#[derive(Copy, Clone, Debug)]
pub enum MoveType {
    Single,
    OneUp,
    OneDown,
    OneLeft,
    OneRight,
    TwoUp,
    TwoDown,
    TwoLeft,
    TwoRight,
    UpAndDown,
    LeftAndRight,
}
pub const POSSIBLE_MOVE_TYPES: [MoveType; 11] = [
    MoveType::Single,
    MoveType::OneUp,
    MoveType::OneDown,
    MoveType::OneLeft,
    MoveType::OneRight,
    MoveType::TwoUp,
    MoveType::TwoDown,
    MoveType::TwoLeft,
    MoveType::TwoRight,
    MoveType::UpAndDown,
    MoveType::LeftAndRight,
];

#[derive(Copy, Clone)]
pub struct Move {
    pub coord: Coordinate,
    move_type: MoveType,
    pub old_board_type: Option<board::BoardType>,
    pub new_board_type: Option<board::BoardType>,
}

impl Move {
    pub fn new(coord: Coordinate, move_type: MoveType, old_board_type: Option<board::BoardType>) -> Option<Move> {
        let c = Move{coord: coord, move_type: move_type, old_board_type: old_board_type, new_board_type: None};
        if c.in_bounds() { Some(c) } else { None }
    }

    pub fn with_board_type(&self, new_board_type: board::BoardType) -> Move {
        Move{new_board_type: Some(new_board_type), .. *self}
    }

    pub fn in_bounds(&self) -> bool {
        match self.move_type {
            MoveType::Single => true,
            MoveType::OneUp => self.coord.row >= 1,
            MoveType::OneDown => self.coord.row < board::NUM_ROWS - 1,
            MoveType::OneLeft => self.coord.col >= 1,
            MoveType::OneRight => self.coord.col < board::NUM_COLS - 1,
            MoveType::TwoUp => self.coord.row >= 2,
            MoveType::TwoDown => self.coord.row < board::NUM_ROWS - 2,
            MoveType::TwoLeft => self.coord.col >= 2,
            MoveType::TwoRight => self.coord.col < board::NUM_COLS - 2,
            MoveType::UpAndDown => self.coord.row >= 1 && self.coord.row < board::NUM_ROWS - 1,
            MoveType::LeftAndRight => self.coord.col >= 1 && self.coord.col < board::NUM_COLS - 1,
        }
    }

    pub fn extensions(&self) -> Vec<Coordinate> {
        match self.move_type {
            MoveType::Single => vec![],
            MoveType::OneUp => vec![self.coord.unchecked_move_in(Direction::Up, 1)],
            MoveType::OneDown => vec![self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::OneLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1)],
            MoveType::OneRight => vec![self.coord.unchecked_move_in(Direction::Right, 1)],
            MoveType::TwoUp => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Up, 2)],
            MoveType::TwoDown => vec![self.coord.unchecked_move_in(Direction::Down, 1), self.coord.unchecked_move_in(Direction::Down, 2)],
            MoveType::TwoLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Left, 2)],
            MoveType::TwoRight => vec![self.coord.unchecked_move_in(Direction::Right, 1), self.coord.unchecked_move_in(Direction::Right, 2)],
            MoveType::UpAndDown => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::LeftAndRight => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Right, 1)],
        }
    }
}

impl Display for Move {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
        match self.new_board_type {
            Some(bt) => write!(formatter, "{:?} at {} (Board type {:?})", self.move_type, self.coord, bt),
            None => write!(formatter, "{:?} at {}", self.move_type, self.coord),
        }
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

pub mod not_bash;
pub mod install;
pub mod pre_commit;

pub mod codegen;
mod ast_src;

use anyhow::Context;
use std::{
    env,
    io::Write,
    path::{Path, PathBuf},
    process::{Command, Stdio},
};

use crate::{
    codegen::Mode,
    not_bash::{fs2, pushd, rm_rf, run},
};

pub use anyhow::Result;

const TOOLCHAIN: &str = "stable";

pub fn project_root() -> PathBuf {
    Path::new(
        &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
    )
    .ancestors()
    .nth(1)
    .unwrap()
    .to_path_buf()
}

pub fn run_rustfmt(mode: Mode) -> Result<()> {
    ensure_rustfmt()?;

    if mode == Mode::Verify {
        run!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN)?;
    } else {
        run!("rustup run {} -- cargo fmt", TOOLCHAIN)?;
    }
    Ok(())
}

fn reformat(text: impl std::fmt::Display) -> Result<String> {
    ensure_rustfmt()?;
    let mut rustfmt = Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"])
        .arg(project_root().join("rustfmt.toml"))
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;
    write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
    let output = rustfmt.wait_with_output()?;
    let stdout = String::from_utf8(output.stdout)?;
    let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
    Ok(format!("//! {}\n\n{}", preamble, stdout))
}

fn ensure_rustfmt() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => return Ok(()),
        _ => (),
    };
    run!("rustup toolchain install {}", TOOLCHAIN)?;
    run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?;
    Ok(())
}

pub fn run_clippy() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_clippy().context("install clippy")?,
    };

    let allowed_lints = [
        "clippy::collapsible_if",
        "clippy::map_clone", // FIXME: remove when Iterator::copied stabilizes (1.36.0)
        "clippy::needless_pass_by_value",
        "clippy::nonminimal_bool",
        "clippy::redundant_pattern_matching",
    ];
    run!(
        "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
        TOOLCHAIN,
        allowed_lints.join(" -A ")
    )?;
    Ok(())
}

fn install_clippy() -> Result<()> {
    run!("rustup toolchain install {}", TOOLCHAIN)?;
    run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?;
    Ok(())
}

pub fn run_fuzzer() -> Result<()> {
    let _d = pushd("./crates/ra_syntax");
    match run!("cargo fuzz --help") {
        Ok(_) => (),
        _ => {
            run!("cargo install cargo-fuzz")?;
        }
    };

    run!("rustup run nightly -- cargo fuzz run parser")?;
    Ok(())
}

/// Cleans the `./target` dir after the build such that only
/// dependencies are cached on CI.
pub fn run_pre_cache() -> Result<()> {
    let slow_tests_cookie = Path::new("./target/.slow_tests_cookie");
    if !slow_tests_cookie.exists() {
        panic!("slow tests were skipped on CI!")
    }
    rm_rf(slow_tests_cookie)?;

    for entry in Path::new("./target/debug").read_dir()? {
        let entry = entry?;
        if entry.file_type().map(|it| it.is_file()).ok() == Some(true) {
            // Can't delete yourself on windows :-(
            if !entry.path().ends_with("xtask.exe") {
                rm_rf(&entry.path())?
            }
        }
    }

    fs2::remove_file("./target/.rustc_info.json")?;
    let to_delete = ["ra_", "heavy_test"];
    for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() {
        for entry in Path::new(dir).read_dir()? {
            let entry = entry?;
            if to_delete.iter().any(|&it| entry.path().display().to_string().contains(it)) {
                rm_rf(&entry.path())?
            }
        }
    }

    Ok(())
}

pub fn run_release(dry_run: bool) -> Result<()> {
    if !dry_run {
        run!("git switch release")?;
        run!("git fetch upstream")?;
        run!("git reset --hard upstream/master")?;
        run!("git push")?;
    }

    let website_root = project_root().join("../rust-analyzer.github.io");
    let changelog_dir = website_root.join("./thisweek/_posts");

    let today = run!("date --iso")?;
    let commit = run!("git rev-parse HEAD")?;
    let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count();

    let contents = format!(
        "\
= Changelog #{}
:sectanchors:
:page-layout: post

Commit: commit:{}[] +
Release: release:{}[]

== New Features

* pr:[] .

== Fixes

== Internal Improvements
",
        changelog_n, commit, today
    );

    let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
    fs2::write(&path, &contents)?;

    fs2::copy(project_root().join("./docs/user/readme.adoc"), website_root.join("manual.adoc"))?;

    Ok(())
}
<commit_msg>Simplify<commit_after>//! FIXME: write short doc here

pub mod not_bash;
pub mod install;
pub mod pre_commit;

pub mod codegen;
mod ast_src;

use anyhow::Context;
use std::{
    env,
    io::Write,
    path::{Path, PathBuf},
    process::{Command, Stdio},
};

use crate::{
    codegen::Mode,
    not_bash::{fs2, pushd, rm_rf, run},
};

pub use anyhow::Result;

const TOOLCHAIN: &str = "stable";

pub fn project_root() -> PathBuf {
    Path::new(
        &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
    )
    .ancestors()
    .nth(1)
    .unwrap()
    .to_path_buf()
}

pub fn run_rustfmt(mode: Mode) -> Result<()> {
    ensure_rustfmt()?;

    if mode == Mode::Verify {
        run!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN)?;
    } else {
        run!("rustup run {} -- cargo fmt", TOOLCHAIN)?;
    }
    Ok(())
}

fn reformat(text: impl std::fmt::Display) -> Result<String> {
    ensure_rustfmt()?;
    let mut rustfmt = Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"])
        .arg(project_root().join("rustfmt.toml"))
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;
    write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
    let output = rustfmt.wait_with_output()?;
    let stdout = String::from_utf8(output.stdout)?;
    let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
    Ok(format!("//! {}\n\n{}", preamble, stdout))
}

fn ensure_rustfmt() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => return Ok(()),
        _ => (),
    };
    run!("rustup toolchain install {}", TOOLCHAIN)?;
    run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?;
    Ok(())
}

pub fn run_clippy() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_clippy().context("install clippy")?,
    };

    let allowed_lints = [
        "clippy::collapsible_if",
        "clippy::map_clone", // FIXME: remove when Iterator::copied stabilizes (1.36.0)
        "clippy::needless_pass_by_value",
        "clippy::nonminimal_bool",
        "clippy::redundant_pattern_matching",
    ];
    run!(
        "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
        TOOLCHAIN,
        allowed_lints.join(" -A ")
    )?;
    Ok(())
}

fn install_clippy() -> Result<()> {
    run!("rustup toolchain install {}", TOOLCHAIN)?;
    run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?;
    Ok(())
}

pub fn run_fuzzer() -> Result<()> {
    let _d = pushd("./crates/ra_syntax");
    if run!("cargo fuzz --help").is_err() {
        run!("cargo install cargo-fuzz")?;
    };

    run!("rustup run nightly -- cargo fuzz run parser")?;
    Ok(())
}

/// Cleans the `./target` dir after the build such that only
/// dependencies are cached on CI.
pub fn run_pre_cache() -> Result<()> {
    let slow_tests_cookie = Path::new("./target/.slow_tests_cookie");
    if !slow_tests_cookie.exists() {
        panic!("slow tests were skipped on CI!")
    }
    rm_rf(slow_tests_cookie)?;

    for entry in Path::new("./target/debug").read_dir()? {
        let entry = entry?;
        if entry.file_type().map(|it| it.is_file()).ok() == Some(true) {
            // Can't delete yourself on windows :-(
            if !entry.path().ends_with("xtask.exe") {
                rm_rf(&entry.path())?
            }
        }
    }

    fs2::remove_file("./target/.rustc_info.json")?;
    let to_delete = ["ra_", "heavy_test"];
    for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() {
        for entry in Path::new(dir).read_dir()? {
            let entry = entry?;
            if to_delete.iter().any(|&it| entry.path().display().to_string().contains(it)) {
                rm_rf(&entry.path())?
            }
        }
    }

    Ok(())
}

pub fn run_release(dry_run: bool) -> Result<()> {
    if !dry_run {
        run!("git switch release")?;
        run!("git fetch upstream")?;
        run!("git reset --hard upstream/master")?;
        run!("git push")?;
    }

    let website_root = project_root().join("../rust-analyzer.github.io");
    let changelog_dir = website_root.join("./thisweek/_posts");

    let today = run!("date --iso")?;
    let commit = run!("git rev-parse HEAD")?;
    let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count();

    let contents = format!(
        "\
= Changelog #{}
:sectanchors:
:page-layout: post

Commit: commit:{}[] +
Release: release:{}[]

== New Features

* pr:[] .

== Fixes

== Internal Improvements
",
        changelog_n, commit, today
    );

    let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
    fs2::write(&path, &contents)?;

    fs2::copy(project_root().join("./docs/user/readme.adoc"), website_root.join("manual.adoc"))?;

    Ok(())
}
<|endoftext|>