<commit_before>use std::num::{Float};
use std::ops::{Add, Sub, Mul, Div, Neg};

use super::{Point3D, Direction3D, Matrix3D};

#[derive(PartialEq, PartialOrd, Clone, Show)]
pub struct Vector3D {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

static VECTOR3D_ZERO: Vector3D = Vector3D {
    x: 0.0,
    y: 0.0,
    z: 0.0
};

impl Vector3D {
    pub fn from_xyz(x: f32, y: f32, z: f32) -> Vector3D {
        Vector3D {
            x: x,
            y: y,
            z: z
        }
    }

    pub fn between_points(from: &Point3D, to: &Point3D) -> Vector3D {
        Vector3D::from_xyz(
            to.x - from.x,
            to.y - from.y,
            to.z - from.z
        )
    }

    pub fn from_point(point: &Point3D) -> Vector3D {
        Vector3D::from_xyz(
            point.x,
            point.y,
            point.z
        )
    }

    pub fn zero() -> &'static Vector3D {
        &VECTOR3D_ZERO
    }

    pub fn magnitude(&self) -> f32 {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn to_unit(&self) -> Direction3D {
        Direction3D::from_vector(self)
    }

    pub fn to_orthonormal_basis(&self) -> Matrix3D {
        Direction3D::from_vector(self).to_orthonormal_basis()
    }

    pub fn scale(&self, scale: f32) -> Vector3D {
        Vector3D::from_xyz(
            self.x * scale,
            self.y * scale,
            self.z * scale
        )
    }

    pub fn projection_dir(&self, direction: &Direction3D) -> Vector3D {
        direction * Vector3D::dot(self, direction)
    }

    pub fn projection_vec(&self, direction: &Vector3D) -> Vector3D {
        let denominator = Vector3D::dot(direction, direction);
        if denominator > 0.0 {
            direction * (Vector3D::dot(self, direction) / denominator)
        } else {
            Vector3D::zero().clone()
        }
    }

    pub fn rotate(&self, matrix: &Matrix3D) -> Vector3D
    {
        Vector3D::from_xyz(
            self.x * matrix.x.x + self.y * matrix.y.x + self.z * matrix.z.x,
            self.x * matrix.x.y + self.y * matrix.y.y + self.z * matrix.z.y,
            self.x * matrix.x.z + self.y * matrix.y.z + self.z * matrix.z.z
        )
    }

    pub fn eq_tol<T: AsVector>(&self, other: &T, tolerance: f32) -> bool {
        let v = other.as_vector();
        (self.x - v.x).abs() < tolerance &&
        (self.y - v.z).abs() < tolerance &&
        (self.y - v.z).abs() < tolerance
    }
}

//------------------------------------------------------------------------------

pub trait AsVector {
    fn as_vector<'a>(&'a self) -> &'a Vector3D;
}

impl Vector3D {
    pub fn dot<T: AsVector, U: AsVector>(vector1: &T, vector2: &U) -> f32
    {
        let v1 = vector1.as_vector();
        let v2 = vector2.as_vector();

        v1.x * v2.x +
        v1.y * v2.y +
        v1.z * v2.z
    }

    pub fn cross<T: AsVector, U: AsVector>(vector1: &T, vector2: &U) -> Vector3D
    {
        let v1 = vector1.as_vector();
        let v2 = vector2.as_vector();

        Vector3D::from_xyz(
            v1.y * v2.z - v1.z * v2.y,
            v1.z * v2.x - v1.x * v2.z,
            v1.x * v2.y - v1.y * v2.x
        )
    }
}

macro_rules! as_vector_add {
    ($T:ty) => (
        impl<'a, 'b, U: AsVector> Add<&'a U> for &'b $T {
            type Output = Vector3D;

            fn add(self, other: &U) -> Vector3D {
                let v1 = self.as_vector();
                let v2 = other.as_vector();

                Vector3D::from_xyz(
                    v1.x + v2.x,
                    v1.y + v2.y,
                    v1.z + v2.z
                )
            }
        }

        impl<'a, U: AsVector> Add<&'a U> for $T {
            type Output = Vector3D;

            fn add(self, other: &U) -> Vector3D {
                &self + other
            }
        }

        impl<'a, U: AsVector> Add<U> for &'a $T {
            type Output = Vector3D;

            fn add(self, other: U) -> Vector3D {
                self + &other
            }
        }

        impl<U: AsVector> Add<U> for $T {
            type Output = Vector3D;

            fn add(self, other: U) -> Vector3D {
                &self + &other
            }
        }
    )
}

macro_rules! as_vector_sub {
    ($T:ty) => (
        impl<'a, 'b, U: AsVector> Sub<&'a U> for &'b $T {
            type Output = Vector3D;

            fn sub(self, other: &U) -> Vector3D {
                let v1 = self.as_vector();
                let v2 = other.as_vector();

                Vector3D::from_xyz(
                    v1.x - v2.x,
                    v1.y - v2.y,
                    v1.z - v2.z
                )
            }
        }

        impl<'a, U: AsVector> Sub<&'a U> for $T {
            type Output = Vector3D;

            fn sub(self, other: &U) -> Vector3D {
                &self - other
            }
        }

        impl<'a, U: AsVector> Sub<U> for &'a $T {
            type Output = Vector3D;

            fn sub(self, other: U) -> Vector3D {
                self - &other
            }
        }

        impl<U: AsVector> Sub<U> for $T {
            type Output = Vector3D;

            fn sub(self, other: U) -> Vector3D {
                &self - &other
            }
        }
    )
}

macro_rules! as_vector_mul {
    ($T:ty) => (
        impl<'a> Mul<f32> for &'a $T {
            type Output = Vector3D;

            fn mul(self, scale: f32) -> Vector3D {
                self.as_vector().scale(scale)
            }
        }

        impl Mul<f32> for $T {
            type Output = Vector3D;

            fn mul(self, scale: f32) -> Vector3D {
                &self * scale
            }
        }
    )
}

macro_rules! as_vector_div {
    ($T:ty) => (
        impl<'a> Div<f32> for &'a $T {
            type Output = Vector3D;

            fn div(self, scale: f32) -> Vector3D {
                let inv_scale = 1.0 / scale;
                self.as_vector().scale(inv_scale)
            }
        }

        impl Div<f32> for $T {
            type Output = Vector3D;

            fn div(self, scale: f32) -> Vector3D {
                &self / scale
            }
        }
    )
}

//------------------------------------------------------------------------------

impl AsVector for Vector3D {
    fn as_vector<'a>(&'a self) -> &'a Vector3D {
        self
    }
}

as_vector_add!(Vector3D);
as_vector_sub!(Vector3D);
as_vector_mul!(Vector3D);
as_vector_div!(Vector3D);

impl<'a> Neg for &'a Vector3D {
    type Output = Vector3D;

    fn neg(self) -> Vector3D {
        Vector3D::from_xyz(
            -self.x,
            -self.y,
            -self.z
        )
    }
}

impl Neg for Vector3D {
    type Output = Vector3D;

    fn neg(self) -> Vector3D {
        -&self
    }
}
<commit_msg>Adds `macro_export` for the `AsVector` macros.<commit_after>use std::num::{Float};
use std::ops::{Add, Sub, Mul, Div, Neg};

use super::{Point3D, Direction3D, Matrix3D};

#[derive(PartialEq, PartialOrd, Clone, Show)]
pub struct Vector3D {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

static VECTOR3D_ZERO: Vector3D = Vector3D {
    x: 0.0,
    y: 0.0,
    z: 0.0
};

impl Vector3D {
    pub fn from_xyz(x: f32, y: f32, z: f32) -> Vector3D {
        Vector3D {
            x: x,
            y: y,
            z: z
        }
    }

    pub fn between_points(from: &Point3D, to: &Point3D) -> Vector3D {
        Vector3D::from_xyz(
            to.x - from.x,
            to.y - from.y,
            to.z - from.z
        )
    }

    pub fn from_point(point: &Point3D) -> Vector3D {
        Vector3D::from_xyz(
            point.x,
            point.y,
            point.z
        )
    }

    pub fn zero() -> &'static Vector3D {
        &VECTOR3D_ZERO
    }

    pub fn magnitude(&self) -> f32 {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn to_unit(&self) -> Direction3D {
        Direction3D::from_vector(self)
    }

    pub fn to_orthonormal_basis(&self) -> Matrix3D {
        Direction3D::from_vector(self).to_orthonormal_basis()
    }

    pub fn scale(&self, scale: f32) -> Vector3D {
        Vector3D::from_xyz(
            self.x * scale,
            self.y * scale,
            self.z * scale
        )
    }

    pub fn projection_dir(&self, direction: &Direction3D) -> Vector3D {
        direction * Vector3D::dot(self, direction)
    }

    pub fn projection_vec(&self, direction: &Vector3D) -> Vector3D {
        let denominator = Vector3D::dot(direction, direction);
        if denominator > 0.0 {
            direction * (Vector3D::dot(self, direction) / denominator)
        } else {
            Vector3D::zero().clone()
        }
    }

    pub fn rotate(&self, matrix: &Matrix3D) -> Vector3D
    {
        Vector3D::from_xyz(
            self.x * matrix.x.x + self.y * matrix.y.x + self.z * matrix.z.x,
            self.x * matrix.x.y + self.y * matrix.y.y + self.z * matrix.z.y,
            self.x * matrix.x.z + self.y * matrix.y.z + self.z * matrix.z.z
        )
    }

    pub fn eq_tol<T: AsVector>(&self, other: &T, tolerance: f32) -> bool {
        let v = other.as_vector();
        (self.x - v.x).abs() < tolerance &&
        (self.y - v.z).abs() < tolerance &&
        (self.y - v.z).abs() < tolerance
    }
}

//------------------------------------------------------------------------------

pub trait AsVector {
    fn as_vector<'a>(&'a self) -> &'a Vector3D;
}

impl Vector3D {
    pub fn dot<T: AsVector, U: AsVector>(vector1: &T, vector2: &U) -> f32
    {
        let v1 = vector1.as_vector();
        let v2 = vector2.as_vector();

        v1.x * v2.x +
        v1.y * v2.y +
        v1.z * v2.z
    }

    pub fn cross<T: AsVector, U: AsVector>(vector1: &T, vector2: &U) -> Vector3D
    {
        let v1 = vector1.as_vector();
        let v2 = vector2.as_vector();

        Vector3D::from_xyz(
            v1.y * v2.z - v1.z * v2.y,
            v1.z * v2.x - v1.x * v2.z,
            v1.x * v2.y - v1.y * v2.x
        )
    }
}

#[macro_export]
macro_rules! as_vector_add {
    ($T:ty) => (
        impl<'a, 'b, U: AsVector> Add<&'a U> for &'b $T {
            type Output = Vector3D;

            fn add(self, other: &U) -> Vector3D {
                let v1 = self.as_vector();
                let v2 = other.as_vector();

                Vector3D::from_xyz(
                    v1.x + v2.x,
                    v1.y + v2.y,
                    v1.z + v2.z
                )
            }
        }

        impl<'a, U: AsVector> Add<&'a U> for $T {
            type Output = Vector3D;

            fn add(self, other: &U) -> Vector3D {
                &self + other
            }
        }

        impl<'a, U: AsVector> Add<U> for &'a $T {
            type Output = Vector3D;

            fn add(self, other: U) -> Vector3D {
                self + &other
            }
        }

        impl<U: AsVector> Add<U> for $T {
            type Output = Vector3D;

            fn add(self, other: U) -> Vector3D {
                &self + &other
            }
        }
    )
}

#[macro_export]
macro_rules! as_vector_sub {
    ($T:ty) => (
        impl<'a, 'b, U: AsVector> Sub<&'a U> for &'b $T {
            type Output = Vector3D;

            fn sub(self, other: &U) -> Vector3D {
                let v1 = self.as_vector();
                let v2 = other.as_vector();

                Vector3D::from_xyz(
                    v1.x - v2.x,
                    v1.y - v2.y,
                    v1.z - v2.z
                )
            }
        }

        impl<'a, U: AsVector> Sub<&'a U> for $T {
            type Output = Vector3D;

            fn sub(self, other: &U) -> Vector3D {
                &self - other
            }
        }

        impl<'a, U: AsVector> Sub<U> for &'a $T {
            type Output = Vector3D;

            fn sub(self, other: U) -> Vector3D {
                self - &other
            }
        }

        impl<U: AsVector> Sub<U> for $T {
            type Output = Vector3D;

            fn sub(self, other: U) -> Vector3D {
                &self - &other
            }
        }
    )
}

#[macro_export]
macro_rules! as_vector_mul {
    ($T:ty) => (
        impl<'a> Mul<f32> for &'a $T {
            type Output = Vector3D;

            fn mul(self, scale: f32) -> Vector3D {
                self.as_vector().scale(scale)
            }
        }

        impl Mul<f32> for $T {
            type Output = Vector3D;

            fn mul(self, scale: f32) -> Vector3D {
                &self * scale
            }
        }
    )
}

#[macro_export]
macro_rules! as_vector_div {
    ($T:ty) => (
        impl<'a> Div<f32> for &'a $T {
            type Output = Vector3D;

            fn div(self, scale: f32) -> Vector3D {
                let inv_scale = 1.0 / scale;
                self.as_vector().scale(inv_scale)
            }
        }

        impl Div<f32> for $T {
            type Output = Vector3D;

            fn div(self, scale: f32) -> Vector3D {
                &self / scale
            }
        }
    )
}

//------------------------------------------------------------------------------

impl AsVector for Vector3D {
    fn as_vector<'a>(&'a self) -> &'a Vector3D {
        self
    }
}

as_vector_add!(Vector3D);
as_vector_sub!(Vector3D);
as_vector_mul!(Vector3D);
as_vector_div!(Vector3D);

impl<'a> Neg for &'a Vector3D {
    type Output = Vector3D;

    fn neg(self) -> Vector3D {
        Vector3D::from_xyz(
            -self.x,
            -self.y,
            -self.z
        )
    }
}

impl Neg for Vector3D {
    type Output = Vector3D;

    fn neg(self) -> Vector3D {
        -&self
    }
}
<|endoftext|>


<commit_before>use hir::{self, ModPath};
use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode};

use crate::{
    utils::{find_insert_use_container, insert_use_statement},
    AssistContext, AssistId, Assists,
};
use either::Either;

// Assist: replace_qualified_name_with_use
//
// Adds a use statement for a given fully-qualified name.
//
// ```
// fn process(map: std::collections::<|>HashMap<String, String>) {}
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn process(map: HashMap<String, String>) {}
// ```
pub(crate) fn replace_qualified_name_with_use(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let path: ast::Path = ctx.find_node_at_offset()?;
    // We don't want to mess with use statements
    if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }

    let hir_path = ctx.sema.lower_path(&path)?;
    let segments = collect_hir_path_segments(&hir_path)?;
    if segments.len() < 2 {
        return None;
    }

    let target = path.syntax().text_range();
    acc.add(
        AssistId("replace_qualified_name_with_use"),
        "Replace qualified path with use",
        target,
        |builder| {
            let path_to_import = hir_path.mod_path().clone();
            let container = match find_insert_use_container(path.syntax(), ctx) {
                Some(c) => c,
                None => return,
            };
            insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder());

            // Now that we've brought the name into scope, re-qualify all paths that could be
            // affected (that is, all paths inside the node we added the `use` to).
            let hir_path = match hir::Path::from_ast(path.clone()) {
                Some(p) => p,
                None => return,
            };
            let mut rewriter = SyntaxRewriter::default();
            match container {
                Either::Left(l) => {
                    shorten_paths(&mut rewriter, l.syntax().clone(), hir_path.mod_path());
                }
                Either::Right(r) => {
                    shorten_paths(&mut rewriter, r.syntax().clone(), hir_path.mod_path());
                }
            }
            builder.rewrite(rewriter);
        },
    )
}

fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
    let mut ps = Vec::<SmolStr>::with_capacity(10);
    match path.kind() {
        hir::PathKind::Abs => ps.push("".into()),
        hir::PathKind::Crate => ps.push("crate".into()),
        hir::PathKind::Plain => {}
        hir::PathKind::Super(0) => ps.push("self".into()),
        hir::PathKind::Super(lvl) => {
            let mut chain = "super".to_string();
            for _ in 0..*lvl {
                chain += "::super";
            }
            ps.push(chain.into());
        }
        hir::PathKind::DollarCrate(_) => return None,
    }
    ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
    Some(ps)
}

/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
fn shorten_paths(re: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ModPath) {
    for child in node.children() {
        match_ast! {
            match child {
                // Don't modify `use` items, as this can break the `use` item when injecting a new
                // import into the use tree.
                ast::UseItem(_it) => continue,
                // Don't descend into submodules, they don't have the same `use` items in scope.
                ast::Module(_it) => continue,

                ast::Path(p) => {
                    match maybe_replace_path(re, &p, path) {
                        Some(()) => {},
                        None => shorten_paths(re, p.syntax().clone(), path),
                    }
                },
                _ => shorten_paths(re, child, path),
            }
        }
    }
}

fn maybe_replace_path(
    re: &mut SyntaxRewriter<'static>,
    p: &ast::Path,
    path: &ModPath,
) -> Option<()> {
    let hir_path = hir::Path::from_ast(p.clone())?;

    if hir_path.mod_path() != path {
        return None;
    }

    // Replace path with its last "plain" segment.
    let mut mod_path = hir_path.mod_path().clone();
    let last = mod_path.segments.len() - 1;
    mod_path.segments.swap(0, last);
    mod_path.segments.truncate(1);
    mod_path.kind = hir::PathKind::Plain;

    let mut new_path = crate::ast_transform::path_to_ast(mod_path);

    let type_args = p.segment().and_then(|s| s.type_arg_list());
    if let Some(type_args) = type_args {
        let last_segment = new_path.segment().unwrap();
        new_path = new_path.with_segment(last_segment.with_type_args(type_args));
    }

    re.replace(p.syntax(), new_path.syntax());
    Some(())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_replace_add_use_no_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt::Debug<|>
    ",
            r"
use std::fmt::Debug;

Debug
    ",
        );
    }
    #[test]
    fn test_replace_add_use_no_anchor_with_item_below() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt::Debug<|>

fn main() {
}
    ",
            r"
use std::fmt::Debug;

Debug

fn main() {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_with_item_above() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
}

std::fmt::Debug<|>
    ",
            r"
use std::fmt::Debug;

fn main() {
}

Debug
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_2seg() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt<|>::Debug
    ",
            r"
use std::fmt;

fmt::Debug
    ",
        );
    }

    #[test]
    fn test_replace_add_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use stdx;

impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use stdx;
use std::fmt::Debug;

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_file_use_other_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use std::fmt::Debug;

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_use_other_anchor_indent() {
        check_assist(
            replace_qualified_name_with_use,
            r"
    impl std::fmt::Debug<|> for Foo {
    }
    ",
            r"
    use std::fmt::Debug;

    impl Debug for Foo {
    }
    ",
        );
    }

    #[test]
    fn test_replace_split_different() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt;

impl std::io<|> for Foo {
}
    ",
            r"
use std::{io, fmt};

impl io for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_split_self_for_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt;

impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use std::fmt::{self, Debug, };

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_split_self_for_target() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Debug;

impl std::fmt<|> for Foo {
}
    ",
            r"
use std::fmt::{self, Debug};

impl fmt for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_to_nested_self_nested() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{Display}};

impl std::fmt::nested<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{Display, self}};

impl nested for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_add_to_nested_self_already_included() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{self, Display}};

impl std::fmt::nested<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{self, Display}};

impl nested for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_add_to_nested_nested() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{Display}};

impl std::fmt::nested::Debug<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{Display, Debug}};

impl Debug for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_split_common_target_longer() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Debug;

impl std::fmt::nested::Display<|> for Foo {
}
",
            r"
use std::fmt::{nested::Display, Debug};

impl Display for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_split_common_use_longer() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::nested::Debug;

impl std::fmt::Display<|> for Foo {
}
",
            r"
use std::fmt::{Display, nested::Debug};

impl Display for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_use_nested_import() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use crate::{
    ty::{Substs, Ty},
    AssocItem,
};

fn foo() { crate::ty::lower<|>::trait_env() }
",
            r"
use crate::{
    ty::{Substs, Ty, lower},
    AssocItem,
};

fn foo() { lower::trait_env() }
",
        );
    }

    #[test]
    fn test_replace_alias() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt as foo;

impl foo::Debug<|> for Foo {
}
",
            r"
use std::fmt as foo;

impl Debug for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_not_applicable_one_segment() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
impl foo<|> for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_not_applicable_in_use() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
use std::fmt<|>;
",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_in_mod_mod() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod foo {
    mod bar {
        std::fmt::Debug<|>
    }
}
    ",
            r"
mod foo {
    mod bar {
        use std::fmt::Debug;

        Debug
    }
}
    ",
        );
    }

    #[test]
    fn inserts_imports_after_inner_attributes() {
        check_assist(
            replace_qualified_name_with_use,
            r"
#![allow(dead_code)]

fn main() {
    std::fmt::Debug<|>
}
    ",
            r"
#![allow(dead_code)]
use std::fmt::Debug;

fn main() {
    Debug
}
    ",
        );
    }

    #[test]
    fn replaces_all_affected_paths() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
    std::fmt::Debug<|>;
    let x: std::fmt::Debug = std::fmt::Debug;
}
    ",
            r"
use std::fmt::Debug;

fn main() {
    Debug;
    let x: Debug = Debug;
}
    ",
        );
    }

    #[test]
    fn replaces_all_affected_paths_mod() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod m {
    fn f() {
        std::fmt::Debug<|>;
        let x: std::fmt::Debug = std::fmt::Debug;
    }
    fn g() {
        std::fmt::Debug;
    }
}

fn f() {
    std::fmt::Debug;
}
    ",
            r"
mod m {
    use std::fmt::Debug;

    fn f() {
        Debug;
        let x: Debug = Debug;
    }
    fn g() {
        Debug;
    }
}

fn f() {
    std::fmt::Debug;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_submodules() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
    std::fmt::Debug<|>;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
            r"
use std::fmt::Debug;

fn main() {
    Debug;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Display;

fn main() {
    std::fmt<|>;
}
    ",
            r"
use std::fmt::{self, Display};

fn main() {
    fmt;
}
    ",
        );
    }
}
<commit_msg>Simplify<commit_after>use hir::{self, ModPath};
use ra_syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SmolStr, SyntaxNode};

use crate::{
    utils::{find_insert_use_container, insert_use_statement},
    AssistContext, AssistId, Assists,
};

// Assist: replace_qualified_name_with_use
//
// Adds a use statement for a given fully-qualified name.
//
// ```
// fn process(map: std::collections::<|>HashMap<String, String>) {}
// ```
// ->
// ```
// use std::collections::HashMap;
//
// fn process(map: HashMap<String, String>) {}
// ```
pub(crate) fn replace_qualified_name_with_use(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let path: ast::Path = ctx.find_node_at_offset()?;
    // We don't want to mess with use statements
    if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
        return None;
    }

    let hir_path = ctx.sema.lower_path(&path)?;
    let segments = collect_hir_path_segments(&hir_path)?;
    if segments.len() < 2 {
        return None;
    }

    let target = path.syntax().text_range();
    acc.add(
        AssistId("replace_qualified_name_with_use"),
        "Replace qualified path with use",
        target,
        |builder| {
            let path_to_import = hir_path.mod_path().clone();
            let container = match find_insert_use_container(path.syntax(), ctx) {
                Some(c) => c,
                None => return,
            };
            insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder());

            // Now that we've brought the name into scope, re-qualify all paths that could be
            // affected (that is, all paths inside the node we added the `use` to).
            let hir_path = match hir::Path::from_ast(path.clone()) {
                Some(p) => p,
                None => return,
            };
            let mut rewriter = SyntaxRewriter::default();
            let syntax = container.either(|l| l.syntax().clone(), |r| r.syntax().clone());
            shorten_paths(&mut rewriter, syntax, hir_path.mod_path());
            builder.rewrite(rewriter);
        },
    )
}

fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
    let mut ps = Vec::<SmolStr>::with_capacity(10);
    match path.kind() {
        hir::PathKind::Abs => ps.push("".into()),
        hir::PathKind::Crate => ps.push("crate".into()),
        hir::PathKind::Plain => {}
        hir::PathKind::Super(0) => ps.push("self".into()),
        hir::PathKind::Super(lvl) => {
            let mut chain = "super".to_string();
            for _ in 0..*lvl {
                chain += "::super";
            }
            ps.push(chain.into());
        }
        hir::PathKind::DollarCrate(_) => return None,
    }
    ps.extend(path.segments().iter().map(|it| it.name.to_string().into()));
    Some(ps)
}

/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ModPath) {
    for child in node.children() {
        match_ast! {
            match child {
                // Don't modify `use` items, as this can break the `use` item when injecting a new
                // import into the use tree.
                ast::UseItem(_it) => continue,
                // Don't descend into submodules, they don't have the same `use` items in scope.
                ast::Module(_it) => continue,

                ast::Path(p) => {
                    match maybe_replace_path(rewriter, &p, path) {
                        Some(()) => {},
                        None => shorten_paths(rewriter, p.syntax().clone(), path),
                    }
                },
                _ => shorten_paths(rewriter, child, path),
            }
        }
    }
}

fn maybe_replace_path(
    re: &mut SyntaxRewriter<'static>,
    p: &ast::Path,
    path: &ModPath,
) -> Option<()> {
    let hir_path = hir::Path::from_ast(p.clone())?;

    if hir_path.mod_path() != path {
        return None;
    }

    // Replace path with its last "plain" segment.
    let mut mod_path = hir_path.mod_path().clone();
    let last = mod_path.segments.len() - 1;
    mod_path.segments.swap(0, last);
    mod_path.segments.truncate(1);
    mod_path.kind = hir::PathKind::Plain;

    let mut new_path = crate::ast_transform::path_to_ast(mod_path);

    let type_args = p.segment().and_then(|s| s.type_arg_list());
    if let Some(type_args) = type_args {
        let last_segment = new_path.segment().unwrap();
        new_path = new_path.with_segment(last_segment.with_type_args(type_args));
    }

    re.replace(p.syntax(), new_path.syntax());
    Some(())
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_replace_add_use_no_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt::Debug<|>
    ",
            r"
use std::fmt::Debug;

Debug
    ",
        );
    }
    #[test]
    fn test_replace_add_use_no_anchor_with_item_below() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt::Debug<|>

fn main() {
}
    ",
            r"
use std::fmt::Debug;

Debug

fn main() {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_with_item_above() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
}

std::fmt::Debug<|>
    ",
            r"
use std::fmt::Debug;

fn main() {
}

Debug
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_2seg() {
        check_assist(
            replace_qualified_name_with_use,
            r"
std::fmt<|>::Debug
    ",
            r"
use std::fmt;

fmt::Debug
    ",
        );
    }

    #[test]
    fn test_replace_add_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use stdx;

impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use stdx;
use std::fmt::Debug;

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_file_use_other_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use std::fmt::Debug;

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_use_other_anchor_indent() {
        check_assist(
            replace_qualified_name_with_use,
            r"
    impl std::fmt::Debug<|> for Foo {
    }
    ",
            r"
    use std::fmt::Debug;

    impl Debug for Foo {
    }
    ",
        );
    }

    #[test]
    fn test_replace_split_different() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt;

impl std::io<|> for Foo {
}
    ",
            r"
use std::{io, fmt};

impl io for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_split_self_for_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt;

impl std::fmt::Debug<|> for Foo {
}
    ",
            r"
use std::fmt::{self, Debug, };

impl Debug for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_split_self_for_target() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Debug;

impl std::fmt<|> for Foo {
}
    ",
            r"
use std::fmt::{self, Debug};

impl fmt for Foo {
}
    ",
        );
    }

    #[test]
    fn test_replace_add_to_nested_self_nested() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{Display}};

impl std::fmt::nested<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{Display, self}};

impl nested for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_add_to_nested_self_already_included() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{self, Display}};

impl std::fmt::nested<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{self, Display}};

impl nested for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_add_to_nested_nested() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::{Debug, nested::{Display}};

impl std::fmt::nested::Debug<|> for Foo {
}
",
            r"
use std::fmt::{Debug, nested::{Display, Debug}};

impl Debug for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_split_common_target_longer() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Debug;

impl std::fmt::nested::Display<|> for Foo {
}
",
            r"
use std::fmt::{nested::Display, Debug};

impl Display for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_split_common_use_longer() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::nested::Debug;

impl std::fmt::Display<|> for Foo {
}
",
            r"
use std::fmt::{Display, nested::Debug};

impl Display for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_use_nested_import() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use crate::{
    ty::{Substs, Ty},
    AssocItem,
};

fn foo() { crate::ty::lower<|>::trait_env() }
",
            r"
use crate::{
    ty::{Substs, Ty, lower},
    AssocItem,
};

fn foo() { lower::trait_env() }
",
        );
    }

    #[test]
    fn test_replace_alias() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt as foo;

impl foo::Debug<|> for Foo {
}
",
            r"
use std::fmt as foo;

impl Debug for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_not_applicable_one_segment() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
impl foo<|> for Foo {
}
",
        );
    }

    #[test]
    fn test_replace_not_applicable_in_use() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
use std::fmt<|>;
",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_in_mod_mod() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod foo {
    mod bar {
        std::fmt::Debug<|>
    }
}
    ",
            r"
mod foo {
    mod bar {
        use std::fmt::Debug;

        Debug
    }
}
    ",
        );
    }

    #[test]
    fn inserts_imports_after_inner_attributes() {
        check_assist(
            replace_qualified_name_with_use,
            r"
#![allow(dead_code)]

fn main() {
    std::fmt::Debug<|>
}
    ",
            r"
#![allow(dead_code)]
use std::fmt::Debug;

fn main() {
    Debug
}
    ",
        );
    }

    #[test]
    fn replaces_all_affected_paths() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
    std::fmt::Debug<|>;
    let x: std::fmt::Debug = std::fmt::Debug;
}
    ",
            r"
use std::fmt::Debug;

fn main() {
    Debug;
    let x: Debug = Debug;
}
    ",
        );
    }

    #[test]
    fn replaces_all_affected_paths_mod() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod m {
    fn f() {
        std::fmt::Debug<|>;
        let x: std::fmt::Debug = std::fmt::Debug;
    }
    fn g() {
        std::fmt::Debug;
    }
}

fn f() {
    std::fmt::Debug;
}
    ",
            r"
mod m {
    use std::fmt::Debug;

    fn f() {
        Debug;
        let x: Debug = Debug;
    }
    fn g() {
        Debug;
    }
}

fn f() {
    std::fmt::Debug;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_submodules() {
        check_assist(
            replace_qualified_name_with_use,
            r"
fn main() {
    std::fmt::Debug<|>;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
            r"
use std::fmt::Debug;

fn main() {
    Debug;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
use std::fmt::Display;

fn main() {
    std::fmt<|>;
}
    ",
            r"
use std::fmt::{self, Display};

fn main() {
    fmt;
}
    ",
        );
    }
}
<|endoftext|>


<commit_before>use fitsio::FitsFile;
use std::path::Path;

#[test]
fn test_reading_bit_data_type() {
    let source_file = Path::new("tests/fixtures/1065880128_01.mwaf");
    let mut f = FitsFile::open(source_file).unwrap();

    let table_hdu = f.hdu(1).unwrap();
    let flags: Vec<u32> = table_hdu.read_col(&mut f, "FLAGS").unwrap();
    assert_eq!(flags.len(), 1_849_344);
}
<commit_msg>Adds test for writing data<commit_after>use fitsio::tables::{ColumnDataType, ColumnDescription};
use fitsio::FitsFile;
use std::path::Path;
use tempfile::Builder;

#[test]
fn test_reading_bit_data_type() {
    let source_file = Path::new("tests/fixtures/1065880128_01.mwaf");
    let mut f = FitsFile::open(source_file).unwrap();

    let table_hdu = f.hdu(1).unwrap();
    let flags: Vec<u32> = table_hdu.read_col(&mut f, "FLAGS").unwrap();
    assert_eq!(flags.len(), 1_849_344);
}

#[test]
fn test_writing_bit_data_type() {
    /* Create a temporary directory to work from */
    let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap();
    let file_path = tmp_dir.path().join("example.fits");

    {
        let mut fitsfile = FitsFile::create(&file_path).open().unwrap();

        let data: Vec<u32> = (0..64).collect();
        let col = ColumnDescription::new("BITMASK")
            .with_type(ColumnDataType::Bit)
            .create()
            .unwrap();
        let columns = &[col];
        let table_hdu = fitsfile.create_table("DATA", columns).unwrap();
        table_hdu
            .write_col(&mut fitsfile, "BITMASK", &data)
            .unwrap();
    }

    let mut f = FitsFile::open(file_path).unwrap();

    let table_hdu = f.hdu("DATA").unwrap();
    let flags: Vec<u32> = dbg!(table_hdu.read_col(&mut f, "BITMASK").unwrap());
    assert_eq!(flags.len(), 64);
}
<|endoftext|>


<commit_before>use collections::HashMap;
use core;
use {CargoResult};

#[allow(dead_code)]
pub fn resolve(deps: &Vec<core::Dependency>, registry: &core::Registry) -> CargoResult<Vec<core::Package>> {
  let mut remaining = deps.clone();
  let mut resolve = HashMap::<&str, &core::Package>::new();

  loop {
    let curr = match remaining.pop() {
      Some(curr) => curr,
      None => return Ok(resolve.values().map(|v| (*v).clone()).collect())
    };

    let opts = registry.query(curr.get_name());

    assert!(!resolve.contains_key_equiv(&curr.get_name()), "already traversed {}", curr.get_name());
    // Temporary, but we must have exactly one option to satisfy the dep
    assert!(opts.len() == 1, "invalid num of results {}", opts.len());

    let pkg = opts.get(0);
    resolve.insert(pkg.get_name(), *pkg);
  }
}

#[cfg(test)]
mod test {

  use hamcrest::{
    assert_that,
    equal_to,
    of_len,
    contains
  };

  use core::{
    MemRegistry,
    Dependency,
    Package
  };

  use super::{
    resolve
  };

  fn pkg(name: &str) -> Package {
    Package::new(name, &Vec::<Dependency>::new())
  }

  fn dep(name: &str) -> Dependency {
    Dependency::new(name)
  }

  fn registry(pkgs: Vec<Package>) -> MemRegistry {
    MemRegistry::new(&pkgs)
  }

  #[test]
  pub fn test_resolving_empty_dependency_list() {
    let res = resolve(&vec!(), &registry(vec!())).unwrap();

    assert_that(&res, equal_to(&Vec::<Package>::new()));
  }

  #[test]
  pub fn test_resolving_only_package() {
    let reg = registry(vec!(pkg("foo")));
    let res = resolve(&vec!(dep("foo")), &reg);

    assert_that(&res.unwrap(), equal_to(&vec!(pkg("foo"))));
  }

  #[test]
  pub fn test_resolving_one_dep() {
    let reg = registry(vec!(pkg("foo"), pkg("bar")));
    let res = resolve(&vec!(dep("foo")), &reg);

    assert_that(&res.unwrap(), equal_to(&vec!(pkg("foo"))));
  }

  #[test]
  pub fn test_resolving_multiple_deps() {
    let reg = registry(vec!(pkg("foo"), pkg("bar"), pkg("baz")));
    let res = resolve(&vec!(dep("foo"), dep("baz")), &reg).unwrap();

    assert_that(&res, of_len(2));
    assert_that(&res, contains(vec!(pkg("foo"), pkg("baz"))).exactly());
  }
}
<commit_msg>Whitespace<commit_after>use collections::HashMap;
use core;
use {CargoResult};

#[allow(dead_code)]
pub fn resolve(deps: &Vec<core::Dependency>, registry: &core::Registry) -> CargoResult<Vec<core::Package>> {
    let mut remaining = deps.clone();
    let mut resolve = HashMap::<&str, &core::Package>::new();

    loop {
        let curr = match remaining.pop() {
            Some(curr) => curr,
            None => return Ok(resolve.values().map(|v| (*v).clone()).collect())
        };

        let opts = registry.query(curr.get_name());

        assert!(!resolve.contains_key_equiv(&curr.get_name()), "already traversed {}", curr.get_name());
        // Temporary, but we must have exactly one option to satisfy the dep
        assert!(opts.len() == 1, "invalid num of results {}", opts.len());

        let pkg = opts.get(0);
        resolve.insert(pkg.get_name(), *pkg);
    }
}

#[cfg(test)]
mod test {

    use hamcrest::{
        assert_that,
        equal_to,
        of_len,
        contains
    };

    use core::{
        MemRegistry,
        Dependency,
        Package
    };

    use super::{
        resolve
    };

    fn pkg(name: &str) -> Package {
        Package::new(name, &Vec::<Dependency>::new())
    }

    fn dep(name: &str) -> Dependency {
        Dependency::new(name)
    }

    fn registry(pkgs: Vec<Package>) -> MemRegistry {
        MemRegistry::new(&pkgs)
    }

    #[test]
    pub fn test_resolving_empty_dependency_list() {
        let res = resolve(&vec!(), &registry(vec!())).unwrap();

        assert_that(&res, equal_to(&Vec::<Package>::new()));
    }

    #[test]
    pub fn test_resolving_only_package() {
        let reg = registry(vec!(pkg("foo")));
        let res = resolve(&vec!(dep("foo")), &reg);

        assert_that(&res.unwrap(), equal_to(&vec!(pkg("foo"))));
    }

    #[test]
    pub fn test_resolving_one_dep() {
        let reg = registry(vec!(pkg("foo"), pkg("bar")));
        let res = resolve(&vec!(dep("foo")), &reg);

        assert_that(&res.unwrap(), equal_to(&vec!(pkg("foo"))));
    }

    #[test]
    pub fn test_resolving_multiple_deps() {
        let reg = registry(vec!(pkg("foo"), pkg("bar"), pkg("baz")));
        let res = resolve(&vec!(dep("foo"), dep("baz")), &reg).unwrap();

        assert_that(&res, of_len(2));
        assert_that(&res, contains(vec!(pkg("foo"), pkg("baz"))).exactly());
    }

    #[test]
    pub fn test_resolving_transitive_deps() {
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::marker::PhantomData;

use crate::{
    context::{Has, HasMut},
    GameError, GameResult,
};

use super::{
    context::GraphicsContext,
    gpu::{
        arc::{ArcBindGroup, ArcBindGroupLayout, ArcBuffer, ArcShaderModule},
        bind_group::BindGroupBuilder,
    },
    image::Image,
    sampler::Sampler,
};
use crevice::std140::Std140;
use wgpu::util::DeviceExt;

#[derive(Debug)]
enum ShaderSource<'a> {
    None,
    Path(&'a str),
    Code(&'a str),
}

/// Builder pattern for assembling shaders.
#[derive(Debug)]
pub struct ShaderBuilder<'a> {
    fragment_path: ShaderSource<'a>,
    vertex_path: ShaderSource<'a>,
}

impl<'a> ShaderBuilder<'a> {
    /// Create a new builder with no associated shader code.
    pub fn new_wgsl() -> Self {
        ShaderBuilder {
            fragment_path: ShaderSource::None,
            vertex_path: ShaderSource::None,
        }
    }

    /// Use this wgsl shader code for the fragment shader.
    pub fn fragment_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: ShaderSource::Code(source),
            vertex_path: self.vertex_path,
        }
    }
    /// Use this wgsl code resource path for the fragment shader.
    pub fn fragment_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: ShaderSource::Path(path),
            vertex_path: self.vertex_path,
        }
    }

    /// Use this wgsl shader code for the vertex shader.
    pub fn vertex_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: self.vertex_path,
            vertex_path: ShaderSource::Code(source),
        }
    }

    /// Use this wgsl code resource path for the vertex shader.
    pub fn vertex_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: self.vertex_path,
            vertex_path: ShaderSource::Path(path),
        }
    }

    /// Use this wgsl code as both a vertex and fragment shader.
    pub fn combined_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: ShaderSource::Code(source),
            vertex_path: ShaderSource::Code(source),
        }
    }

    /// Use a single wgsl resource as both a vertex and fragment shader.
    pub fn combined_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fragment_path: ShaderSource::Path(path),
            vertex_path: ShaderSource::Path(path),
        }
    }

    /// Create a Shader from the builder.
    pub fn build(self, gfx: &impl Has<GraphicsContext>) -> GameResult<Shader> {
        let gfx = gfx.retrieve();
        let load = |s: &str| {
            Some(ArcShaderModule::new(gfx.wgpu.device.create_shader_module(
                wgpu::ShaderModuleDescriptor {
                    label: None,
                    source: wgpu::ShaderSource::Wgsl(s.into()),
                },
            )))
        };
        let load_resource = |path: &str| -> GameResult<Option<ArcShaderModule>> {
            let mut encoded = Vec::new();
            _ = gfx.fs.open(path)?.read_to_end(&mut encoded)?;
            Ok(load(
                &String::from_utf8(encoded).map_err(|e| GameError::ShaderEncodingError(e))?,
            ))
        };
        let load_any = |source| -> GameResult<Option<ArcShaderModule>> {
            Ok(match source {
                ShaderSource::Code(source) => load(source),
                ShaderSource::Path(source) => load_resource(source)?,
                ShaderSource::None => None,
            })
        };
        Ok(match (self.vertex_path, self.fragment_path) {
            (ShaderSource::Code(vs), ShaderSource::Code(fs)) => {
                if vs == fs {
                    let module = load(vs);
                    Shader {
                        vs_module: module.clone(),
                        fs_module: module,
                    }
                } else {
                    Shader {
                        vs_module: load(vs),
                        fs_module: load(fs),
                    }
                }
            }
            (ShaderSource::Path(vs), ShaderSource::Path(fs)) => {
                if vs == fs {
                    let module = load_resource(vs)?;
                    Shader {
                        vs_module: module.clone(),
                        fs_module: module,
                    }
                } else {
                    Shader {
                        vs_module: load_resource(vs)?,
                        fs_module: load_resource(fs)?,
                    }
                }
            }
            (vs, fs) => Shader {
                vs_module: load_any(vs)?,
                fs_module: load_any(fs)?,
            },
        })
    }
}

/// A custom fragment shader that can be used to render with shader effects.
///
/// The program may have a user specified vertex shader, fragment shader, both,
/// or neither. The fragment shader entry point must be named fs_main. The
/// vertex shader entry point must be named vs_main. The vertex shader must
/// have an output of type
/// ```wgsl
/// struct VertexOutput {
///     @builtin(position) position: vec4<f32>,
///     @location(0) uv: vec2<f32>,
///     @location(1) color: vec4<f32>,
/// }
/// ```
/// if the fragment shader is left unspecified.
///
/// Produce a Shader using ShaderBuilder.
///
/// Adapted from the `shader.rs` example:
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// #[derive(AsStd140)]
/// struct Dim {
///     rate: f32,
/// }
///
/// struct MainState {}
///
/// impl event::EventHandler for MainState {
/// #   fn update(&mut self, _ctx: &mut Context) -> Result<(), GameError> { Ok(()) }
///     fn draw(&mut self, ctx: &mut Context) -> GameResult {
///         let mut canvas = graphics::Canvas::from_frame(ctx, Color::BLACK);
///         let dim = Dim { rate: 0.5 };
///         // NOTE: This is for simplicity; do not recreate your shader every frame like this!
///         //       For more info look at the full example.
///         let shader = ShaderBuilder::new_wgsl()
///             .fragment_code(include_str!("../../resources/dimmer.wgsl"))
///             .build(&mut ctx.gfx);
///         let params = ShaderParams::new(ctx, &dim, &[], &[]);
///         params.set_uniforms(ctx, &dim);
///
///         canvas.set_shader(shader);
///         canvas.set_shader_params(params);
///         // draw something...
///         canvas.finish(ctx)
///     }
///
///     /* ... */
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Shader {
    pub(crate) vs_module: Option<ArcShaderModule>,
    pub(crate) fs_module: Option<ArcShaderModule>,
}

pub use crevice::std140::AsStd140;

/// Parameters that can be passed to a custom shader, including uniforms, images, and samplers.
///
/// These parameters are bound to group 3. With WGSL, for example,
/// ```rust,ignore
/// ggez::graphics::ShaderParams::new(ctx, &my_uniforms, &[&image1, &image2], &[sampler1])
/// ```
/// Corresponds to...
/// ```ignore
/// @group(4) @binding(0)
/// var<uniform> my_uniforms: MyUniforms;
/// @group(4) @binding(1)
/// var image1: texture_2d<f32>;
/// @group(4) @binding(2)
/// var image2: texture_2d<f32>;
/// @group(4) @binding(3)
/// var sampler1: sampler;
/// ```
#[derive(Debug, PartialEq, Eq)]
pub struct ShaderParams<Uniforms: AsStd140> {
    pub(crate) uniforms: ArcBuffer,
    pub(crate) layout: ArcBindGroupLayout,
    pub(crate) bind_group: ArcBindGroup,
    _marker: PhantomData<Uniforms>,
}

impl<Uniforms: AsStd140> ShaderParams<Uniforms> {
    /// Creates a new [ShaderParams], initialized with the given uniforms, images, and samplers.
    pub fn new(
        gfx: &mut impl HasMut<GraphicsContext>,
        uniforms: &Uniforms,
        images: &[&Image],
        samplers: &[Sampler],
    ) -> Self {
        let gfx = gfx.retrieve_mut();
        let uniforms = ArcBuffer::new(gfx.wgpu.device.create_buffer_init(
            &wgpu::util::BufferInitDescriptor {
                label: None,
                usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                contents: uniforms.as_std140().as_bytes(),
            },
        ));

        let samplers = samplers
            .iter()
            .map(|&sampler| gfx.sampler_cache.get(&gfx.wgpu.device, sampler))
            .collect::<Vec<_>>();

        let mut builder = BindGroupBuilder::new();
        builder = builder.buffer(
            &uniforms,
            0,
            wgpu::ShaderStages::VERTEX_FRAGMENT,
            wgpu::BufferBindingType::Uniform,
            false,
            None,
        );

        for image in images {
            builder = builder.image(&image.view, wgpu::ShaderStages::FRAGMENT);
        }

        for sampler in &samplers {
            builder = builder.sampler(sampler, wgpu::ShaderStages::FRAGMENT);
        }

        let (bind_group, layout) = builder.create_uncached(&gfx.wgpu.device);

        ShaderParams {
            uniforms,
            layout,
            bind_group,
            _marker: PhantomData,
        }
    }

    /// Updates the uniform data.
    pub fn set_uniforms(&self, gfx: &impl Has<GraphicsContext>, uniforms: &Uniforms) {
        let gfx = gfx.retrieve();
        gfx.wgpu
            .queue
            .write_buffer(&self.uniforms, 0, uniforms.as_std140().as_bytes());
    }
}

impl<Uniforms: AsStd140> Clone for ShaderParams<Uniforms> {
    fn clone(&self) -> Self {
        Self {
            uniforms: self.uniforms.clone(),
            layout: self.layout.clone(),
            bind_group: self.bind_group.clone(),
            _marker: PhantomData,
        }
    }
}

pub use wgpu::{BlendComponent, BlendFactor, BlendOperation};

/// Describes the blend mode used when drawing images.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlendMode {
    /// The blend mode for the color channels.
    pub color: BlendComponent,
    /// The blend mode for the alpha channel.
    pub alpha: BlendComponent,
}

impl BlendMode {
    /// When combining two fragments, add their values together, saturating
    /// at 1.0
    pub const ADD: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the source value from the
    /// destination value
    pub const SUBTRACT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::ReverseSubtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, add the value of the source times its
    /// alpha channel with the value of the destination multiplied by the inverse
    /// of the source alpha channel. Has the usual transparency effect: mixes the
    /// two colors using a fraction of each one specified by the alpha of the source.
    pub const ALPHA: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the destination color from a constant
    /// color using the source color as weight. Has an invert effect with the constant
    /// color as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert. The output
    /// alpha is same as destination alpha.
    pub const INVERT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Constant,
            dst_factor: BlendFactor::Src,
            operation: BlendOperation::Subtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, multiply their values together (including alpha)
    pub const MULTIPLY: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Dst,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::DstAlpha,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the source value (including source alpha)
    pub const REPLACE: Self = BlendMode {
        color: wgpu::BlendState::REPLACE.color,
        alpha: wgpu::BlendState::REPLACE.alpha,
    };

    /// When combining two fragments, choose the lighter value
    pub const LIGHTEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Max,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the darker value
    pub const DARKEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Min,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When using premultiplied alpha, use this.
    ///
    /// You usually want to use this blend mode for drawing canvases
    /// containing semi-transparent imagery.
    /// For an explanation on this see: <https://github.com/ggez/ggez/issues/694#issuecomment-853724926>
    pub const PREMULTIPLIED: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::One,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };
}
<commit_msg>Simplify builder logic more<commit_after>use std::io::Read;
use std::marker::PhantomData;

use crate::{
    context::{Has, HasMut},
    GameError, GameResult,
};

use super::{
    context::GraphicsContext,
    gpu::{
        arc::{ArcBindGroup, ArcBindGroupLayout, ArcBuffer, ArcShaderModule},
        bind_group::BindGroupBuilder,
    },
    image::Image,
    sampler::Sampler,
};
use crevice::std140::Std140;
use wgpu::util::DeviceExt;

#[derive(Debug, PartialEq, Eq)]
enum ShaderSource<'a> {
    None,
    Path(&'a str),
    Code(&'a str),
}

/// Builder pattern for assembling shaders.
#[derive(Debug)]
pub struct ShaderBuilder<'a> {
    fs: ShaderSource<'a>,
    vs: ShaderSource<'a>,
}

impl<'a> ShaderBuilder<'a> {
    /// Create a new builder with no associated shader code.
    pub fn new_wgsl() -> Self {
        ShaderBuilder {
            fs: ShaderSource::None,
            vs: ShaderSource::None,
        }
    }

    /// Use this wgsl shader code for the fragment shader.
    pub fn fragment_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fs: ShaderSource::Code(source),
            vs: self.vs,
        }
    }
    /// Use this wgsl code resource path for the fragment shader.
    pub fn fragment_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fs: ShaderSource::Path(path),
            vs: self.vs,
        }
    }

    /// Use this wgsl shader code for the vertex shader.
    pub fn vertex_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fs: self.vs,
            vs: ShaderSource::Code(source),
        }
    }

    /// Use this wgsl code resource path for the vertex shader.
    pub fn vertex_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fs: self.vs,
            vs: ShaderSource::Path(path),
        }
    }

    /// Use this wgsl code as both a vertex and fragment shader.
    pub fn combined_code(self, source: &'a str) -> Self {
        ShaderBuilder {
            fs: ShaderSource::Code(source),
            vs: ShaderSource::Code(source),
        }
    }

    /// Use a single wgsl resource as both a vertex and fragment shader.
    pub fn combined_path(self, path: &'a str) -> Self {
        ShaderBuilder {
            fs: ShaderSource::Path(path),
            vs: ShaderSource::Path(path),
        }
    }

    /// Create a Shader from the builder.
    pub fn build(self, gfx: &impl Has<GraphicsContext>) -> GameResult<Shader> {
        let gfx = gfx.retrieve();
        let load = |s: &str| {
            Some(ArcShaderModule::new(gfx.wgpu.device.create_shader_module(
                wgpu::ShaderModuleDescriptor {
                    label: None,
                    source: wgpu::ShaderSource::Wgsl(s.into()),
                },
            )))
        };
        let load_resource = |path: &str| -> GameResult<Option<ArcShaderModule>> {
            let mut encoded = Vec::new();
            _ = gfx.fs.open(path)?.read_to_end(&mut encoded)?;
            Ok(load(
                &String::from_utf8(encoded).map_err(|e| GameError::ShaderEncodingError(e))?,
            ))
        };
        let load_any = |source| -> GameResult<Option<ArcShaderModule>> {
            Ok(match source {
                ShaderSource::Code(source) => load(source),
                ShaderSource::Path(source) => load_resource(source)?,
                ShaderSource::None => None,
            })
        };
        Ok(if self.vs == self.fs {
            let module = load_any(self.vs)?;
            Shader {
                vs_module: module.clone(),
                fs_module: module,
            }
        } else {
            Shader {
                vs_module: load_any(self.vs)?,
                fs_module: load_any(self.fs)?,
            }
        })
    }
}

/// A custom fragment shader that can be used to render with shader effects.
///
/// The program may have a user specified vertex shader, fragment shader, both,
/// or neither. The fragment shader entry point must be named fs_main. The
/// vertex shader entry point must be named vs_main. The vertex shader must
/// have an output of type
/// ```wgsl
/// struct VertexOutput {
///     @builtin(position) position: vec4<f32>,
///     @location(0) uv: vec2<f32>,
///     @location(1) color: vec4<f32>,
/// }
/// ```
/// if the fragment shader is left unspecified.
///
/// Produce a Shader using ShaderBuilder.
///
/// Adapted from the `shader.rs` example:
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// #[derive(AsStd140)]
/// struct Dim {
///     rate: f32,
/// }
///
/// struct MainState {}
///
/// impl event::EventHandler for MainState {
/// #   fn update(&mut self, _ctx: &mut Context) -> Result<(), GameError> { Ok(()) }
///     fn draw(&mut self, ctx: &mut Context) -> GameResult {
///         let mut canvas = graphics::Canvas::from_frame(ctx, Color::BLACK);
///         let dim = Dim { rate: 0.5 };
///         // NOTE: This is for simplicity; do not recreate your shader every frame like this!
///         //       For more info look at the full example.
///         let shader = ShaderBuilder::new_wgsl()
///             .fragment_code(include_str!("../../resources/dimmer.wgsl"))
///             .build(&mut ctx.gfx);
///         let params = ShaderParams::new(ctx, &dim, &[], &[]);
///         params.set_uniforms(ctx, &dim);
///
///         canvas.set_shader(shader);
///         canvas.set_shader_params(params);
///         // draw something...
///         canvas.finish(ctx)
///     }
///
///     /* ... */
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Shader {
    pub(crate) vs_module: Option<ArcShaderModule>,
    pub(crate) fs_module: Option<ArcShaderModule>,
}

pub use crevice::std140::AsStd140;

/// Parameters that can be passed to a custom shader, including uniforms, images, and samplers.
///
/// These parameters are bound to group 3. With WGSL, for example,
/// ```rust,ignore
/// ggez::graphics::ShaderParams::new(ctx, &my_uniforms, &[&image1, &image2], &[sampler1])
/// ```
/// Corresponds to...
/// ```ignore
/// @group(4) @binding(0)
/// var<uniform> my_uniforms: MyUniforms;
/// @group(4) @binding(1)
/// var image1: texture_2d<f32>;
/// @group(4) @binding(2)
/// var image2: texture_2d<f32>;
/// @group(4) @binding(3)
/// var sampler1: sampler;
/// ```
#[derive(Debug, PartialEq, Eq)]
pub struct ShaderParams<Uniforms: AsStd140> {
    pub(crate) uniforms: ArcBuffer,
    pub(crate) layout: ArcBindGroupLayout,
    pub(crate) bind_group: ArcBindGroup,
    _marker: PhantomData<Uniforms>,
}

impl<Uniforms: AsStd140> ShaderParams<Uniforms> {
    /// Creates a new [ShaderParams], initialized with the given uniforms, images, and samplers.
    pub fn new(
        gfx: &mut impl HasMut<GraphicsContext>,
        uniforms: &Uniforms,
        images: &[&Image],
        samplers: &[Sampler],
    ) -> Self {
        let gfx = gfx.retrieve_mut();
        let uniforms = ArcBuffer::new(gfx.wgpu.device.create_buffer_init(
            &wgpu::util::BufferInitDescriptor {
                label: None,
                usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                contents: uniforms.as_std140().as_bytes(),
            },
        ));

        let samplers = samplers
            .iter()
            .map(|&sampler| gfx.sampler_cache.get(&gfx.wgpu.device, sampler))
            .collect::<Vec<_>>();

        let mut builder = BindGroupBuilder::new();
        builder = builder.buffer(
            &uniforms,
            0,
            wgpu::ShaderStages::VERTEX_FRAGMENT,
            wgpu::BufferBindingType::Uniform,
            false,
            None,
        );

        for image in images {
            builder = builder.image(&image.view, wgpu::ShaderStages::FRAGMENT);
        }

        for sampler in &samplers {
            builder = builder.sampler(sampler, wgpu::ShaderStages::FRAGMENT);
        }

        let (bind_group, layout) = builder.create_uncached(&gfx.wgpu.device);

        ShaderParams {
            uniforms,
            layout,
            bind_group,
            _marker: PhantomData,
        }
    }

    /// Updates the uniform data.
    pub fn set_uniforms(&self, gfx: &impl Has<GraphicsContext>, uniforms: &Uniforms) {
        let gfx = gfx.retrieve();
        gfx.wgpu
            .queue
            .write_buffer(&self.uniforms, 0, uniforms.as_std140().as_bytes());
    }
}

impl<Uniforms: AsStd140> Clone for ShaderParams<Uniforms> {
    fn clone(&self) -> Self {
        Self {
            uniforms: self.uniforms.clone(),
            layout: self.layout.clone(),
            bind_group: self.bind_group.clone(),
            _marker: PhantomData,
        }
    }
}

pub use wgpu::{BlendComponent, BlendFactor, BlendOperation};

/// Describes the blend mode used when drawing images.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlendMode {
    /// The blend mode for the color channels.
    pub color: BlendComponent,
    /// The blend mode for the alpha channel.
    pub alpha: BlendComponent,
}

impl BlendMode {
    /// When combining two fragments, add their values together, saturating
    /// at 1.0
    pub const ADD: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the source value from the
    /// destination value
    pub const SUBTRACT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::ReverseSubtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, add the value of the source times its
    /// alpha channel with the value of the destination multiplied by the inverse
    /// of the source alpha channel. Has the usual transparency effect: mixes the
    /// two colors using a fraction of each one specified by the alpha of the source.
    pub const ALPHA: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the destination color from a constant
    /// color using the source color as weight. Has an invert effect with the constant
    /// color as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert. The output
    /// alpha is same as destination alpha.
    pub const INVERT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Constant,
            dst_factor: BlendFactor::Src,
            operation: BlendOperation::Subtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, multiply their values together (including alpha)
    pub const MULTIPLY: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Dst,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::DstAlpha,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the source value (including source alpha)
    pub const REPLACE: Self = BlendMode {
        color: wgpu::BlendState::REPLACE.color,
        alpha: wgpu::BlendState::REPLACE.alpha,
    };

    /// When combining two fragments, choose the lighter value
    pub const LIGHTEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Max,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the darker value
    pub const DARKEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Min,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When using premultiplied alpha, use this.
    ///
    /// You usually want to use this blend mode for drawing canvases
    /// containing semi-transparent imagery.
    /// For an explanation on this see: <https://github.com/ggez/ggez/issues/694#issuecomment-853724926>
    pub const PREMULTIPLIED: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::One,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };
}
<|endoftext|>


<commit_before>//! Densely numbered entity references as mapping keys.
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::slice;
use std::vec::Vec;
use {EntityRef, Iter, IterMut, Keys};

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

impl<K, V> Deref for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Target = [V];

    fn deref(&self) -> &Self::Target {
        &self.elems
    }
}

impl<K, V> DerefMut for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn deref_mut(&mut self) -> &mut [V] {
        &mut self.elems
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }

    #[test]
    fn deref() {
        let mut m = PrimaryMap::<E, isize>::new();
        let _: &[isize] = m.as_ref();
        let _: &mut [isize] = m.as_mut();
        let _: &[isize] = &m;
        let _: &mut [isize] = &mut m;
    }
}
<commit_msg>Implementing Deref in PrimaryMap turns out to be error-prone, so remove it.<commit_after>//! Densely numbered entity references as mapping keys.
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec::Vec;
use {EntityRef, Iter, IterMut, Keys};

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
///
/// Note that `PrimaryMap` doesn't implement `Deref` or `DerefMut`, which would allow
/// `&PrimaryMap<K, V>` to convert to `&[V]`. One of the main advantages of `PrimaryMap` is
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
/// plain slice would make it easier to use incorrectly.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }
}
<|endoftext|>