<commit_before>extern crate vec_arena;

use vec_arena::Arena;

/// The null index, akin to null pointers.
///
/// Just like a null pointer indicates an address no object is ever stored at,
/// the null index indicates an index no object is ever stored at.
///
/// Number `!0` is the largest possible value representable by `usize`.
const NULL: usize = !0;

struct Node<T> {
    /// Parent node.
    parent: usize,

    /// Left and right child.
    children: [usize; 2],

    /// Actual value stored in node.
    value: T,
}

impl<T> Node<T> {
    fn new(value: T) -> Node<T> {
        Node {
            parent: NULL,
            children: [NULL, NULL],
            value: value,
        }
    }
}

struct Splay<T> {
    /// This is where nodes are stored.
    arena: Arena<Node<T>>,

    /// The root node.
    root: usize,
}

impl<T> Splay<T> where T: Ord {
    /// Constructs a new, empty splay tree.
    fn new() -> Splay<T> {
        Splay {
            arena: Arena::with_capacity(1000000),
            root: NULL,
        }
    }

    /// Links nodes `p` and `c` as parent and child with the specified direction.
    #[inline(always)]
    fn link(&mut self, p: usize, c: usize, dir: usize) {
        self.arena[p].children[dir] = c;
        if c != NULL {
            self.arena[c].parent = p;
        }
    }

    /// Performs a rotation on node `c`, whose parent is node `p`.
    #[inline(always)]
    fn rotate(&mut self, p: usize, c: usize) {
        // Variables:
        // - `c` is the child node
        // - `p` is it's parent
        // - `g` is it's grandparent

        // Find the grandparent.
        let g = self.arena[p].parent;

        // The direction of p-c relationship.
        let dir = if self.arena[p].children[0] == c { 0 } else { 1 };

        // This is the child of `c` that needs to be reassigned to `p`.
        let t = self.arena[c].children[dir ^ 1];

        self.link(p, t, dir);
        self.link(c, p, dir ^ 1);

        if g == NULL {
            // There is no grandparent, so `c` becomes the root.
            self.root = c;
            self.arena[c].parent = NULL;
        } else {
            // Link `g` and `c` together.
            let dir = if self.arena[g].children[0] == p { 0 } else { 1 };
            self.link(g, c, dir);
        }
    }

    /// Splays a node, rebalancing the tree in process.
    fn splay(&mut self, c: usize) {
        loop {
            // Variables:
            // - `c` is the current node
            // - `p` is it's parent
            // - `g` is it's grandparent

            // Find the parent.
            let p = self.arena[c].parent;
            if p == NULL {
                // There is no parent. That means `c` is the root.
                break;
            }

            // Find the grandparent.
            let g = self.arena[p].parent;
            if g == NULL {
                // There is no grandparent. Just one more rotation is left.
                // Zig step.
                self.rotate(p, c);
                break;
            }

            if (self.arena[g].children[0] == p) == (self.arena[p].children[0] == c) {
                // Zig-zig step.
                self.rotate(g, p);
                self.rotate(p, c);
            } else {
                // Zig-zag step.
                self.rotate(p, c);
                self.rotate(g, c);
            }
        }
    }

    /// Inserts a new node with specified `value`.
    fn insert(&mut self, value: T) {
        // Variables:
        // - `n` is the new node
        // - `p` will be it's parent
        // - `c` is the present child of `p`

        let n = self.arena.insert(Node::new(value));

        if self.root == NULL {
            self.root = n;
        } else {
            let mut p = self.root;
            loop {
                // Decide whether to go left or right.
                let dir = if self.arena[n].value < self.arena[p].value { 0 } else { 1 };
                let c = self.arena[p].children[dir];

                if c == NULL {
                    self.link(p, n, dir);
                    self.splay(n);
                    break;
                }
                p = c;
            }
        }
    }

    /// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces.
    fn print(&self, node: usize, indent: usize) where T: std::fmt::Display {
        if node != NULL {
            // Print the left subtree.
            self.print(self.arena[node].children[0], indent + 3);

            // Print the current node.
            println!("{:width$}{}", "", self.arena[node].value, width = indent);

            // Print the right subtree.
            self.print(self.arena[node].children[1], indent + 3);
        }
    }
}

fn main() {
    let mut splay = Splay::new();

    // Insert a bunch of pseudorandom numbers.
    let mut num = 1u32;
    for _ in 0..30 {
        num = num.wrapping_mul(17).wrapping_add(255);
        splay.insert(num);
    }

    // Display the whole splay tree.
    splay.print(splay.root, 0);
}
<commit_msg>Don't specify capacity in splay tree<commit_after>extern crate vec_arena;

use vec_arena::Arena;

/// The null index, akin to null pointers.
///
/// Just like a null pointer indicates an address no object is ever stored at,
/// the null index indicates an index no object is ever stored at.
///
/// Number `!0` is the largest possible value representable by `usize`.
const NULL: usize = !0;

struct Node<T> {
    /// Parent node.
    parent: usize,

    /// Left and right child.
    children: [usize; 2],

    /// Actual value stored in node.
    value: T,
}

impl<T> Node<T> {
    fn new(value: T) -> Node<T> {
        Node {
            parent: NULL,
            children: [NULL, NULL],
            value: value,
        }
    }
}

struct Splay<T> {
    /// This is where nodes are stored.
    arena: Arena<Node<T>>,

    /// The root node.
    root: usize,
}

impl<T> Splay<T> where T: Ord {
    /// Constructs a new, empty splay tree.
    fn new() -> Splay<T> {
        Splay {
            arena: Arena::new(),
            root: NULL,
        }
    }

    /// Links nodes `p` and `c` as parent and child with the specified direction.
    #[inline(always)]
    fn link(&mut self, p: usize, c: usize, dir: usize) {
        self.arena[p].children[dir] = c;
        if c != NULL {
            self.arena[c].parent = p;
        }
    }

    /// Performs a rotation on node `c`, whose parent is node `p`.
    #[inline(always)]
    fn rotate(&mut self, p: usize, c: usize) {
        // Variables:
        // - `c` is the child node
        // - `p` is it's parent
        // - `g` is it's grandparent

        // Find the grandparent.
        let g = self.arena[p].parent;

        // The direction of p-c relationship.
        let dir = if self.arena[p].children[0] == c { 0 } else { 1 };

        // This is the child of `c` that needs to be reassigned to `p`.
        let t = self.arena[c].children[dir ^ 1];

        self.link(p, t, dir);
        self.link(c, p, dir ^ 1);

        if g == NULL {
            // There is no grandparent, so `c` becomes the root.
            self.root = c;
            self.arena[c].parent = NULL;
        } else {
            // Link `g` and `c` together.
            let dir = if self.arena[g].children[0] == p { 0 } else { 1 };
            self.link(g, c, dir);
        }
    }

    /// Splays a node, rebalancing the tree in process.
    fn splay(&mut self, c: usize) {
        loop {
            // Variables:
            // - `c` is the current node
            // - `p` is it's parent
            // - `g` is it's grandparent

            // Find the parent.
            let p = self.arena[c].parent;
            if p == NULL {
                // There is no parent. That means `c` is the root.
                break;
            }

            // Find the grandparent.
            let g = self.arena[p].parent;
            if g == NULL {
                // There is no grandparent. Just one more rotation is left.
                // Zig step.
                self.rotate(p, c);
                break;
            }

            if (self.arena[g].children[0] == p) == (self.arena[p].children[0] == c) {
                // Zig-zig step.
                self.rotate(g, p);
                self.rotate(p, c);
            } else {
                // Zig-zag step.
                self.rotate(p, c);
                self.rotate(g, c);
            }
        }
    }

    /// Inserts a new node with specified `value`.
    fn insert(&mut self, value: T) {
        // Variables:
        // - `n` is the new node
        // - `p` will be it's parent
        // - `c` is the present child of `p`

        let n = self.arena.insert(Node::new(value));

        if self.root == NULL {
            self.root = n;
        } else {
            let mut p = self.root;
            loop {
                // Decide whether to go left or right.
                let dir = if self.arena[n].value < self.arena[p].value { 0 } else { 1 };
                let c = self.arena[p].children[dir];

                if c == NULL {
                    self.link(p, n, dir);
                    self.splay(n);
                    break;
                }
                p = c;
            }
        }
    }

    /// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces.
    fn print(&self, node: usize, indent: usize) where T: std::fmt::Display {
        if node != NULL {
            // Print the left subtree.
            self.print(self.arena[node].children[0], indent + 3);

            // Print the current node.
            println!("{:width$}{}", "", self.arena[node].value, width = indent);

            // Print the right subtree.
            self.print(self.arena[node].children[1], indent + 3);
        }
    }
}

fn main() {
    let mut splay = Splay::new();

    // Insert a bunch of pseudorandom numbers.
    let mut num = 1u32;
    for _ in 0..30 {
        num = num.wrapping_mul(17).wrapping_add(255);
        splay.insert(num);
    }

    // Display the whole splay tree.
    splay.print(splay.root, 0);
}
<|endoftext|>


<commit_before>//! Support library for `cargo xtask` command.
//!
//! See https://github.com/matklad/cargo-xtask/

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(())
}
<commit_msg>Print log on release<commit_after>//! Support library for `cargo xtask` command.
//!
//! See https://github.com/matklad/cargo-xtask/

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"))?;

    let tags = run!("git tag --list"; echo = false)?;
    let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

    println!("\n    git log {}..HEAD --merges --reverse", prev_tag);

    Ok(())
}

fn is_release_tag(tag: &str) -> bool {
    tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit())
}
<|endoftext|>


<commit_before>use crate::grammar::ast::FuncCallExpression;
use crate::grammar::model::Fragment;
use crate::grammar::parsers::testing::setup;

fn test_call(s: &'static str, should_err: bool) {
    let (f, h) = setup(s);
    let fr = Fragment::new(&f, h);
    let r = FuncCallExpression::parse(fr);
    if should_err {
        assert!(r.is_err());
        r.map_err(|e| {
            e.map(|t| {
                let fr: Fragment = t.0;
                assert_eq!(fr.source(), s);
            })
        })
        .unwrap_err();
    } else {
        assert!(r.is_ok());
        let o = r.unwrap();
        assert_eq!(o.0.len(), 0);
        assert_eq!(o.1.frag.source(), s);
    }
}

#[test]
fn test_empty() {
    test_call("", true);
}

#[test]
fn test_underscore() {
    test_call("_()", true);
}

#[test]
fn test_reserved() {
    test_call("true()", true);
}

#[test]
fn test_calls() {
    ["abc()", "a_bc(1, \"abc\")", "n0(a, b, c)", "xd(e)"]
        .iter()
        .for_each(|s| test_call(s, false))
}
<commit_msg>func call tests: fix error<commit_after>use crate::grammar::ast::FuncCallExpression;
use crate::grammar::model::Fragment;
use crate::grammar::parsers::testing::setup;

fn test_call(s: &'static str, should_err: bool) {
    let (f, h) = setup(s);
    let fr = Fragment::new(&f, h);
    let r = FuncCallExpression::parse(fr);
    if should_err {
        assert!(r.is_err());
        r.map_err(|e| {
            e.map(|t| {
                let fr: Fragment = t.0;
                assert_eq!(fr.source(), s);
            })
        })
        .unwrap_err();
    } else {
        assert!(r.is_ok());
        let o = r.unwrap();
        assert_eq!(o.0.len(), 0);
        assert_eq!(o.1.frag.source(), s);
    }
}

#[test]
fn test_empty() {
    test_call("", true);
}

#[test]
fn test_underscore() {
    test_call("_()", true);
}

#[test]
fn test_true() {
    test_call("true()", false);
}

#[test]
fn test_calls() {
    ["abc()", "a_bc(1, \"abc\")", "n0(a, b, c)", "xd(e)"]
        .iter()
        .for_each(|s| test_call(s, false))
}
<|endoftext|>


<commit_before>use hir::{self, HasCrate, HirDisplay};
use syntax::ast::{self, make, AstNode, HasName, HasVisibility};

use crate::{
    utils::{find_struct_impl, render_snippet, Cursor},
    AssistContext, AssistId, AssistKind, Assists, GroupLabel,
};

// Assist: generate_setter
//
// Generate a setter method.
//
// ```
// struct Person {
//     nam$0e: String,
// }
// ```
// ->
// ```
// struct Person {
//     name: String,
// }
//
// impl Person {
//     /// Set the person's name.
//     fn set_name(&mut self, name: String) {
//         self.name = name;
//     }
// }
// ```
pub(crate) fn generate_delegate(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let strukt_name = strukt.name()?;

    let field = ctx.find_node_at_offset::<ast::RecordField>()?;
    let field_ty = field.ty()?;

    let sema_field_ty = ctx.sema.resolve_type(&field_ty)?;
    let krate = sema_field_ty.krate(ctx.db());
    let mut methods = vec![];
    sema_field_ty.iterate_assoc_items(ctx.db(), krate, |item| {
        if let hir::AssocItem::Function(f) = item {
            if f.self_param(ctx.db()).is_some() {
                methods.push(f)
            }
        }
        Some(())
    });

    let target = field_ty.syntax().text_range();
    for method in methods {
        let impl_def = find_struct_impl(
            ctx,
            &ast::Adt::Struct(strukt.clone()),
            &method.name(ctx.db()).to_string(),
        )?;
        acc.add_group(
            &GroupLabel("Generate delegate".to_owned()),
            AssistId("generate_delegate", AssistKind::Generate),
            format!("Generate a delegate method for '{}'", method.name(ctx.db())),
            target,
            |builder| {
                // make function
                let vis = strukt.visibility();
                let name = make::name(&method.name(ctx.db()).to_string());
                let type_params = None;
                let params = make::param_list(None, []);
                let body = make::block_expr([], None);
                let ret_type = &method.ret_type(ctx.db()).display(ctx.db()).to_string();
                let ret_type = Some(make::ret_type(make::ty(ret_type)));
                let is_async = false;
                let f = make::fn_(vis, name, type_params, params, body, ret_type, is_async);

                let cursor = Cursor::Before(f.syntax());
                let cap = ctx.config.snippet_cap.unwrap(); // FIXME.

                match impl_def {
                    Some(impl_def) => {
                        let impl_def = impl_def.clone_for_update();
                        let old_range = impl_def.syntax().text_range();
                        let assoc_items = impl_def.get_or_create_assoc_item_list();
                        assoc_items.add_item(f.clone().into());
                        let snippet = render_snippet(cap, impl_def.syntax(), cursor);
                        builder.replace_snippet(cap, old_range, snippet);
                    }
                    None => {
                        let name = &strukt_name.to_string();
                        let impl_def = make::impl_(make::ext::ident_path(name));
                        let assoc_items = impl_def.get_or_create_assoc_item_list();
                        assoc_items.add_item(f.clone().into());
                        let start_offset = strukt.syntax().text_range().end();
                        let snippet = render_snippet(cap, impl_def.syntax(), cursor);
                        builder.insert_snippet(cap, start_offset, snippet);
                    }
                }
            },
        )?;
    }
    Some(())
}

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

    use super::*;

    #[test]
    fn test_generate_setter_from_field() {
        check_assist(
            generate_delegate,
            r#"
struct Age(u8);
impl Age {
    fn age(&self) -> u8 {
        self.0

    }
}

struct Person {
    ag$0e: Age,
}

impl Person {}
"#,
            r#"
struct Age(u8);
impl Age {
    $0fn age(&self) -> u8 {
        self.0
    }
}

struct Person {
    age: Age,
}

impl Person {
    fn age(&self) -> u8 {
        self.age.age()
    }
}"#,
        );
    }
}
<commit_msg>Get a make version working!<commit_after>use hir::{self, HasCrate, HasSource, HirDisplay};
use syntax::ast::{self, make, AstNode, HasName, HasVisibility};

use crate::{
    utils::{find_struct_impl, render_snippet, Cursor},
    AssistContext, AssistId, AssistKind, Assists, GroupLabel,
};
use syntax::ast::edit::AstNodeEdit;

// Assist: generate_setter
//
// Generate a setter method.
//
// ```
// struct Person {
//     nam$0e: String,
// }
// ```
// ->
// ```
// struct Person {
//     name: String,
// }
//
// impl Person {
//     /// Set the person's name.
//     fn set_name(&mut self, name: String) {
//         self.name = name;
//     }
// }
// ```
pub(crate) fn generate_delegate(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
    let strukt_name = strukt.name()?;

    let field = ctx.find_node_at_offset::<ast::RecordField>()?;
    let field_name = field.name()?;
    let field_ty = field.ty()?;

    let sema_field_ty = ctx.sema.resolve_type(&field_ty)?;
    let krate = sema_field_ty.krate(ctx.db());
    let mut methods = vec![];
    sema_field_ty.iterate_assoc_items(ctx.db(), krate, |item| {
        if let hir::AssocItem::Function(f) = item {
            if f.self_param(ctx.db()).is_some() {
                methods.push(f)
            }
        }
        Some(())
    });

    let target = field_ty.syntax().text_range();
    for method in methods {
        let impl_def = find_struct_impl(
            ctx,
            &ast::Adt::Struct(strukt.clone()),
            &method.name(ctx.db()).to_string(),
        )?;
        acc.add_group(
            &GroupLabel("Generate delegate".to_owned()),
            AssistId("generate_delegate", AssistKind::Generate),
            format!("Generate a delegate method for '{}'", method.name(ctx.db())),
            target,
            |builder| {
                // make function
                let method_source = match method.source(ctx.db()) {
                    Some(source) => source.value,
                    None => return,
                };
                let method_name = method.name(ctx.db());
                let vis = method_source.visibility();
                let name = make::name(&method.name(ctx.db()).to_string());
                let type_params = None;
                let self_ty = method
                    .self_param(ctx.db())
                    .map(|s| s.source(ctx.db()).map(|s| s.value))
                    .flatten();
                let params = make::param_list(self_ty, []);
                let tail_expr = make::expr_method_call(
                    field_from_idents(["self", &field_name.to_string()]).unwrap(),
                    make::name_ref(&method_name.to_string()),
                    make::arg_list([]),
                );
                let body = make::block_expr([], Some(tail_expr));
                let ret_type = &method.ret_type(ctx.db()).display(ctx.db()).to_string();
                let ret_type = Some(make::ret_type(make::ty(ret_type)));
                let is_async = false;
                let f = make::fn_(vis, name, type_params, params, body, ret_type, is_async)
                    .indent(ast::edit::IndentLevel(1))
                    .clone_for_update();

                let cursor = Cursor::Before(f.syntax());
                let cap = ctx.config.snippet_cap.unwrap(); // FIXME.

                // Create or update an impl block, and attach the function to it.
                match impl_def {
                    Some(impl_def) => {
                        // Remember where in our source our `impl` block lives.
                        let impl_def = impl_def.clone_for_update();
                        let old_range = impl_def.syntax().text_range();

                        // Attach the function to the impl block
                        let assoc_items = impl_def.get_or_create_assoc_item_list();
                        assoc_items.add_item(f.clone().into());

                        // Update the impl block.
                        let snippet = render_snippet(cap, impl_def.syntax(), cursor);
                        builder.replace_snippet(cap, old_range, snippet);
                    }
                    None => {
                        // Attach the function to the impl block
                        let name = &strukt_name.to_string();
                        let impl_def = make::impl_(make::ext::ident_path(name)).clone_for_update();
                        let assoc_items = impl_def.get_or_create_assoc_item_list();
                        assoc_items.add_item(f.clone().into());

                        // Insert the impl block.
                        let offset = strukt.syntax().text_range().end();
                        let snippet = render_snippet(cap, impl_def.syntax(), cursor);
                        let snippet = format!("\n\n{}", snippet);
                        builder.insert_snippet(cap, offset, snippet);
                    }
                }
            },
        )?;
    }
    Some(())
}

pub fn field_from_idents<'a>(
    parts: impl std::iter::IntoIterator<Item = &'a str>,
) -> Option<ast::Expr> {
    let mut iter = parts.into_iter();
    let base = make::expr_path(make::ext::ident_path(iter.next()?));
    let expr = iter.fold(base, |base, s| make::expr_field(base, s));
    Some(expr)
}

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

    use super::*;

    #[test]
    fn test_generate_delegate_create_impl_block() {
        check_assist(
            generate_delegate,
            r#"
struct Age(u8);
impl Age {
    fn age(&self) -> u8 {
        self.0
    }
}

struct Person {
    ag$0e: Age,
}"#,
            r#"
struct Age(u8);
impl Age {
    fn age(&self) -> u8 {
        self.0
    }
}

struct Person {
    age: Age,
}

impl Person {
    $0fn age(&self) -> u8 {
        self.age.age()
    }
}"#,
        );
    }

    #[test]
    fn test_generate_delegate_update_impl_block() {
        check_assist(
            generate_delegate,
            r#"
struct Age(u8);
impl Age {
    fn age(&self) -> u8 {
        self.0
    }
}

struct Person {
    ag$0e: Age,
}

impl Person {}"#,
            r#"
struct Age(u8);
impl Age {
    fn age(&self) -> u8 {
        self.0
    }
}

struct Person {
    age: Age,
}

impl Person {
    $0fn age(&self) -> u8 {
        self.age.age()
    }
}"#,
        );
    }
        self.age.age()
    }
}"#,
        );
    }
}
<|endoftext|>


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

use std::io;
use std::os;
use std::mem::replace;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn, test_main};
use extra::json;
use extra::json::{Json, ToJson};
use collections::treemap::TreeMap;

use html5::tokenizer::{Doctype, Attribute, StartTag, EndTag, Tag, Token};
use html5::tokenizer::{DoctypeToken, TagToken, CommentToken};
use html5::tokenizer::{CharacterToken, EOFToken, ParseError};
use html5::tokenizer::{TokenSink, Tokenizer};

struct TokenLogger {
    tokens: ~[Json],
    current_str: ~str,
}

impl TokenLogger {
    fn new() -> TokenLogger {
        TokenLogger {
            tokens: ~[],
            current_str: ~"",
        }
    }

    // Anything but Character
    fn push<T: json::ToJson>(&mut self, val: T) {
        self.finish_str();
        self.tokens.push(val.to_json());
    }

    fn finish_str(&mut self) {
        if self.current_str.len() > 0 {
            let s = replace(&mut self.current_str, ~"");
            self.tokens.push((~[~"Character", s]).to_json());
        }
    }
}

impl TokenSink for TokenLogger {
    fn process_token(&mut self, token: Token) {
        match token {
            CharacterToken(c) => {
                self.current_str.push_char(c);
            }

            TagToken(Tag { kind: StartTag, name, self_closing, attrs }) => {
                let mut attrmap = TreeMap::new();
                for Attribute { name, value } in attrs.move_iter() {
                    attrmap.insert(name, value.to_json());
                }

                let mut out = ~[(~"StartTag").to_json(), name.to_json(), attrmap.to_json()];
                if self_closing {
                    out.push(true.to_json());
                }
                self.push(out);
            }

            TagToken(Tag { kind: EndTag, name, .. }) => {
                self.push(~[~"EndTag", name]);
            }

            DoctypeToken(Doctype { name, public_id, system_id, force_quirks }) => {
                self.push(~[(~"DOCTYPE").to_json(),
                    name.to_json(), public_id.to_json(), system_id.to_json(),
                    (!force_quirks).to_json()]);
            }

            CommentToken(s) => self.push(~[~"Comment", s]),

            ParseError(_) => self.push(~"ParseError"),

            EOFToken => (),
        }
    }
}

fn tokenize_to_json(input: ~str) -> Json {
    let mut sink = TokenLogger::new();
    {
        let mut tok = Tokenizer::new(&mut sink);
        tok.feed(input);
        tok.end();
    }
    sink.finish_str();
    sink.tokens.to_json()
}

trait JsonExt {
    fn get_str(&self) -> ~str;
    fn get_bool(&self) -> bool;
    fn get_obj<'t>(&'t self) -> &'t TreeMap<~str, Self>;
    fn find<'t>(&'t self, key: &str) -> &'t Self;
}

impl JsonExt for Json {
    fn get_str(&self) -> ~str {
        match *self {
            json::String(ref s) => s.clone(),
            _ => fail!("Json::get_str: not a String"),
        }
    }

    fn get_bool(&self) -> bool {
        match *self {
            json::Boolean(b) => b,
            _ => fail!("Json::get_bool: not a Boolean"),
        }
    }

    fn get_obj<'t>(&'t self) -> &'t TreeMap<~str, Json> {
        match *self {
            json::Object(ref m) => &**m,
            _ => fail!("Json::get_obj: not an Object"),
        }
    }

    fn find<'t>(&'t self, key: &str) -> &'t Json {
        self.get_obj().find(&key.to_owned()).unwrap()
    }
}

fn mk_test(path_str: &str, js: &Json) -> Option<TestDescAndFn> {
    let input  = js.find("input").get_str();
    let expect = js.find("output").clone();
    let desc = format!("{:s}: {:s}",
        path_str, js.find("description").get_str());

    // "Double-escaped" tests require additional processing of
    // the input and output.
    let obj = js.get_obj();
    let double_esc = obj.find(&~"doubleEscaped")
        .map_or(false, |j| j.get_bool());
    if double_esc {
        // FIXME: implement this
        return None;
    }

    // Some tests want to start in a state other than Data.
    if obj.find(&~"initialStates").is_some() {
        // FIXME: We can't handle that either
        return None;
    }

    Some(TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(desc),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            // Clone so we still have 'input' for the failure message.
            let output = tokenize_to_json(input.clone());
            if output != expect {
                fail!("\ninput: {:?}\ngot: {:s}\nexpected: {:s}",
                    input, output.to_pretty_str(), expect.to_pretty_str());
            }
        }),
    })
}

static test_blacklist: &'static [&'static str] = &[
    "xmlViolation.test",
];

pub fn run_tests() {
    let mut tests: ~[TestDescAndFn] = ~[];

    let test_dir_path = FromStr::from_str("test-json/tokenizer").unwrap();
    let test_files = io::fs::readdir(&test_dir_path).ok().expect("can't open dir");

    for path in test_files.move_iter() {
        let path_str = path.filename_str().unwrap();

        if !path_str.ends_with(".test") { continue; }
        if test_blacklist.iter().any(|&t| t == path_str) { continue; }

        let warn_skip = || {
            println!("WARNING: can't load {:s}", path_str);
        };

        let mut file = io::File::open(&path).ok().expect("can't open file");
        let js = match json::from_reader(&mut file as &mut Reader) {
            Err(_) => { warn_skip(); continue; }
            Ok(j) => j,
        };

        match *js.find("tests") {
            json::List(ref lst) => {
                for test in lst.iter() {
                    match mk_test(path_str.as_slice(), test) {
                        Some(t) => tests.push(t),
                        None => (),
                    }
                }
            }
            _ => warn_skip(),
        }
    }

    let args = os::args();
    test_main(args.as_slice(), tests);
}
<commit_msg>Handle "doubleEscaped" tokenizer tests<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::{io, os, str, num, char};
use std::mem::replace;
use test::{TestDesc, TestDescAndFn, DynTestName, DynTestFn, test_main};
use extra::json;
use extra::json::{Json, ToJson};
use collections::treemap::TreeMap;

use html5::tokenizer::{Doctype, Attribute, StartTag, EndTag, Tag, Token};
use html5::tokenizer::{DoctypeToken, TagToken, CommentToken};
use html5::tokenizer::{CharacterToken, EOFToken, ParseError};
use html5::tokenizer::{TokenSink, Tokenizer};

struct TokenLogger {
    tokens: ~[Json],
    current_str: ~str,
}

impl TokenLogger {
    fn new() -> TokenLogger {
        TokenLogger {
            tokens: ~[],
            current_str: ~"",
        }
    }

    // Anything but Character
    fn push<T: json::ToJson>(&mut self, val: T) {
        self.finish_str();
        self.tokens.push(val.to_json());
    }

    fn finish_str(&mut self) {
        if self.current_str.len() > 0 {
            let s = replace(&mut self.current_str, ~"");
            self.tokens.push((~[~"Character", s]).to_json());
        }
    }
}

impl TokenSink for TokenLogger {
    fn process_token(&mut self, token: Token) {
        match token {
            CharacterToken(c) => {
                self.current_str.push_char(c);
            }

            TagToken(Tag { kind: StartTag, name, self_closing, attrs }) => {
                let mut attrmap = TreeMap::new();
                for Attribute { name, value } in attrs.move_iter() {
                    attrmap.insert(name, value.to_json());
                }

                let mut out = ~[(~"StartTag").to_json(), name.to_json(), attrmap.to_json()];
                if self_closing {
                    out.push(true.to_json());
                }
                self.push(out);
            }

            TagToken(Tag { kind: EndTag, name, .. }) => {
                self.push(~[~"EndTag", name]);
            }

            DoctypeToken(Doctype { name, public_id, system_id, force_quirks }) => {
                self.push(~[(~"DOCTYPE").to_json(),
                    name.to_json(), public_id.to_json(), system_id.to_json(),
                    (!force_quirks).to_json()]);
            }

            CommentToken(s) => self.push(~[~"Comment", s]),

            ParseError(_) => self.push(~"ParseError"),

            EOFToken => (),
        }
    }
}

fn tokenize_to_json(input: ~str) -> Json {
    let mut sink = TokenLogger::new();
    {
        let mut tok = Tokenizer::new(&mut sink);
        tok.feed(input);
        tok.end();
    }
    sink.finish_str();
    sink.tokens.to_json()
}

trait JsonExt {
    fn get_str(&self) -> ~str;
    fn get_bool(&self) -> bool;
    fn get_obj<'t>(&'t self) -> &'t TreeMap<~str, Self>;
    fn find<'t>(&'t self, key: &str) -> &'t Self;
}

impl JsonExt for Json {
    fn get_str(&self) -> ~str {
        match *self {
            json::String(ref s) => s.clone(),
            _ => fail!("Json::get_str: not a String"),
        }
    }

    fn get_bool(&self) -> bool {
        match *self {
            json::Boolean(b) => b,
            _ => fail!("Json::get_bool: not a Boolean"),
        }
    }

    fn get_obj<'t>(&'t self) -> &'t TreeMap<~str, Json> {
        match *self {
            json::Object(ref m) => &**m,
            _ => fail!("Json::get_obj: not an Object"),
        }
    }

    fn find<'t>(&'t self, key: &str) -> &'t Json {
        self.get_obj().find(&key.to_owned()).unwrap()
    }
}

// Undo the escaping in "doubleEscaped" tests.
fn unescape(s: &str) -> Option<~str> {
    let mut out = str::with_capacity(s.len());
    let mut it = s.chars().peekable();
    loop {
        match it.next() {
            None => return Some(out),
            Some('\\') if it.peek() == Some(&'u') => {
                drop(it.next());
                let hex: ~str = it.by_ref().take(4).collect();
                match num::from_str_radix(hex.as_slice(), 16)
                          .and_then(char::from_u32) {
                    // Some of the tests use lone surrogates, but we have no
                    // way to represent them in the UTF-8 input to our parser.
                    // Since these can only come from script, we will catch
                    // them there.
                    None => return None,
                    Some(c) => out.push_char(c),
                }
            }
            Some('\\') => fail!("can't understand escape"),
            Some(c) => out.push_char(c),
        }
    }
}

fn unescape_json(js: &Json) -> Json {
    match *js {
        // unwrap is OK here because the spec'd *output* of the tokenizer never
        // contains a lone surrogate.
        json::String(ref s) => json::String(unescape(s.as_slice()).unwrap()),
        json::List(ref xs) => json::List(xs.iter().map(unescape_json).collect()),
        json::Object(ref obj) => {
            let mut new_obj = ~TreeMap::new();
            for (k,v) in obj.iter() {
                new_obj.insert(k.clone(), unescape_json(v));
            }
            json::Object(new_obj)
        }
        _ => js.clone(),
    }
}

fn mk_test(path_str: &str, js: &Json) -> Option<TestDescAndFn> {
    let obj = js.get_obj();
    let mut input = js.find("input").get_str();
    let mut expect = js.find("output").clone();
    let desc = format!("{:s}: {:s}",
        path_str, js.find("description").get_str());

    // "Double-escaped" tests require additional processing of
    // the input and output.
    if obj.find(&~"doubleEscaped").map_or(false, |j| j.get_bool()) {
        match unescape(input.as_slice()) {
            None => return None,
            Some(i) => input = i,
        }
        expect = unescape_json(&expect);
    }

    if input.starts_with("\ufeff") {
        // The tests assume the BOM will pass through because they model
        // data sent from JavaScript rather than from a decoded document.
        // https://github.com/html5lib/html5lib-tests/issues/2
        return None;
    }

    // Some tests want to start in a state other than Data.
    if obj.find(&~"initialStates").is_some() {
        // FIXME: We can't handle that either
        return None;
    }

    Some(TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(desc),
            ignore: false,
            should_fail: false,
        },
        testfn: DynTestFn(proc() {
            // Clone so we still have 'input' for the failure message.
            let output = tokenize_to_json(input.clone());
            if output != expect {
                fail!("\ninput: {:?}\ngot: {:s}\nexpected: {:s}",
                    input, output.to_pretty_str(), expect.to_pretty_str());
            }
        }),
    })
}

pub fn run_tests() {
    let mut tests: ~[TestDescAndFn] = ~[];

    let test_dir_path = FromStr::from_str("test-json/tokenizer").unwrap();
    let test_files = io::fs::readdir(&test_dir_path).ok().expect("can't open dir");

    for path in test_files.move_iter() {
        let path_str = path.filename_str().unwrap();
        if !path_str.ends_with(".test") { continue; }

        let mut file = io::File::open(&path).ok().expect("can't open file");
        let js = json::from_reader(&mut file as &mut Reader)
            .ok().expect("json parse error");

        match js.get_obj().find(&~"tests") {
            Some(&json::List(ref lst)) => {
                for test in lst.iter() {
                    match mk_test(path_str.as_slice(), test) {
                        Some(t) => tests.push(t),
                        None => (),
                    }
                }
            }

            // xmlViolation.test doesn't follow this format.
            _ => (),
        }
    }

    let args = os::args();
    test_main(args.as_slice(), tests);
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::hash::Hash;

fn remove_duplicate_elements_hashing<T: Hash + Eq>(elements: &mut Vec<T>) {
    let set: HashSet<_> = elements.drain(..).collect();
    elements.extend(set.into_iter());
}

fn remove_duplicate_elements_sorting<T: Ord>(elements: &mut Vec<T>) {
    elements.sort_unstable();
    elements.dedup();
}

fn main() {
    let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
    println!("Before removal of duplicates : {:?}", sample_elements);
    remove_duplicate_elements_sorting(&mut sample_elements);
    println!("After removal of duplicates : {:?}", sample_elements);
}

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

    #[test]
    fn test_remove_duplicate_elements_hashing() {
        let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
        remove_duplicate_elements_hashing(&mut sample_elements);
        sample_elements.sort_unstable();
        assert_eq!(sample_elements, [0, 1, 2, 3])
    }

    #[test]
    fn test_remove_duplicate_elements_sorting() {
        let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
        remove_duplicate_elements_sorting(&mut sample_elements);
        assert_eq!(sample_elements, [0, 1, 2, 3])
    }
}
<commit_msg>Revert "cleanup & add sorting method"<commit_after>use std::vec::Vec;
use std::collections::HashSet;
use std::hash::Hash;
use std::cmp::Eq;

fn main() {
    let mut sample_elements = vec![0u8, 0, 1, 1, 2, 3, 2];
    println!("Before removal of duplicates : {:?}", sample_elements);
    remove_duplicate_elements(&mut sample_elements);
    println!("After removal of duplicates : {:?}", sample_elements);
}

fn remove_duplicate_elements<T: Hash + Eq>(elements: &mut Vec<T>) {
    let set: HashSet<_> = elements.drain(..).collect();
    elements.extend(set.into_iter());
}

#[test]
fn test_remove_duplicate_elements() {
    let mut sample_elements = vec![0u8, 0, 1, 1, 2, 3, 2];
    remove_duplicate_elements(&mut sample_elements);
    sample_elements.sort();
    assert_eq!(sample_elements, vec![0, 1, 2, 3])
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![crate_name = "cube"]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;

use cgmath::FixedArray;
use cgmath::{Matrix, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::{Device, DeviceHelper};
use glfw::Context;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],

    #[as_float]
    #[name = "a_TexCoord"]
    tex_coord: [u8, ..2],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(MyProgram)]
struct Params {
    #[name = "u_Transform"]
    transform: [[f32, ..4], ..4],

    #[name = "t_Color"]
    color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

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

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));
    let mut renderer = device.create_renderer();

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // top (0, 0, 1)
        Vertex { pos: [-1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // bottom (0, 0, -1)
        Vertex { pos: [ 1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [-1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
        // right (1, 0, 0)
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 1] },
        // left (-1, 0, 0)
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 1] },
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // back (0, -1, 0)
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
    ];

    let mesh = device.create_mesh(vertex_data);

    let index_data: Vec<u8> = vec![
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 16, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = {
        let buf = device.create_buffer_static(&index_data);
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
        .unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::Bilinear,
                                   gfx::tex::Clamp)
    );

    let prog: MyProgram = device
        .link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
        .unwrap();

    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(1.5f32, -5.0, 3.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let data = Params {
        transform: proj.mul_m(&view.mat).into_fixed(),
        color: (texture, Some(sampler)),
    };

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        renderer.reset();
        renderer.clear(clear_data, &frame);
        renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
        device.submit(renderer.as_buffer());

        window.swap_buffers();
    }
}
<commit_msg>use as_slice<commit_after>#![feature(phase)]
#![crate_name = "cube"]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;

use cgmath::FixedArray;
use cgmath::{Matrix, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::{Device, DeviceHelper};
use glfw::Context;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],

    #[as_float]
    #[name = "a_TexCoord"]
    tex_coord: [u8, ..2],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(MyProgram)]
struct Params {
    #[name = "u_Transform"]
    transform: [[f32, ..4], ..4],

    #[name = "t_Color"]
    color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

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

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));
    let mut renderer = device.create_renderer();

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // top (0, 0, 1)
        Vertex { pos: [-1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // bottom (0, 0, -1)
        Vertex { pos: [ 1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [-1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
        // right (1, 0, 0)
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 1] },
        // left (-1, 0, 0)
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 1] },
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // back (0, -1, 0)
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
    ];

    let mesh = device.create_mesh(vertex_data);

    let index_data: Vec<u8> = vec![
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 16, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = {
        let buf = device.create_buffer_static(&index_data.as_slice());
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8].as_slice())
        .unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::Bilinear,
                                   gfx::tex::Clamp)
    );

    let prog: MyProgram = device
        .link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
        .unwrap();

    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(1.5f32, -5.0, 3.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let data = Params {
        transform: proj.mul_m(&view.mat).into_fixed(),
        color: (texture, Some(sampler)),
    };

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        renderer.reset();
        renderer.clear(clear_data, &frame);
        renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
        device.submit(renderer.as_buffer());

        window.swap_buffers();
    }
}
<|endoftext|>


<commit_before>use crate::error::Error;
use crate::instance::{Instance, RunResult, TerminationDetails, State};
use crate::val::Val;
use crate::vmctx::{Vmctx, VmctxInternal};
use futures::future::{FutureExt, LocalBoxFuture};
use std::any::Any;
use std::future::Future;

impl Vmctx {
    /// Run an `async` computation. A `Vmctx` is passed to ordinary
    /// (synchronous) functions called from WebAssembly. We cannot execute
    /// `async` code in that context, so this method trampolines an `async`
    /// computation back to `Instance::run_async`, which can `.await` on it.
    /// Note that this method may only be used if `Instance::run_async` was
    /// used to run the VM, otherwise it will terminate the instance.
    pub fn run_await<'a, R>(&'a self, f: impl Future<Output = R> + 'a) -> R
    where
        R: Any + 'static,
    {
        // Die if we aren't in Instance::run_async
        match self.instance().state {
            State::Running{ async_context } => {
                if !async_context {
                    panic!(TerminationDetails::AwaitNeedsAsync)
                }
            }
            _ => unreachable!("Access to vmctx implies instance is Running"),
        }
        // Wrap the Output of `f` as a boxed ResumeVal. Then, box the entire
        // async computation.
        let f = async move { ResumeVal(Box::new(f.await)) }.boxed_local();
        // Change the lifetime of the async computation from `'a` to `'static.
        // We need to lie about this lifetime so that `YieldedFuture` may impl
        // `Any` and be passed through the yield. `Instance::run_async`
        // rehydrates this lifetime to be at most as long as the Vmctx's `'a`.
        let f = unsafe {
            std::mem::transmute::<LocalBoxFuture<'a, ResumeVal>, LocalBoxFuture<'static, ResumeVal>>(
                f,
            )
        };
        // Wrap the computation in `YieldedFuture` so that
        // `Instance::run_async` can catch and run it.  We will get the
        // `ResumeVal` we applied to `f` above.
        let ResumeVal(v) = self.yield_val_expecting_val(YieldedFuture(f));
        // We may now downcast and unbox the returned Box<dyn Any> into an `R`
        // again.
        *v.downcast().expect("run_async broke invariant")
    }
}

impl Instance {
    /// Run a WebAssembly function with arguments in the guest context at the
    /// given entrypoint. Enable `Vmctx::run_await` to trampoline async
    /// computations back to this context so that we may `.await` on them.
    ///
    /// Aside from asynchrony, this function behaves identically to
    /// `Instance::run`.
    pub async fn run_async<'a>(
        &'a mut self,
        entrypoint: &str,
        args: &[Val],
    ) -> Result<RunResult, Error> {
        if self.is_yielded() {
            return Err(Error::Unsupported(
                "cannot run_async a yielded instance".to_owned(),
            ));
        }

        // Store the ResumeVal here when we get it.
        let mut resume_val: Option<ResumeVal> = None;
        let ret = loop {
            // Run the WebAssembly program
            let run = if self.is_yielded() {
                // A previous iteration of the loop stored the ResumeVal in
                // `resume_val`, send it back to the guest ctx and continue
                // running:
                self._resume_with_val(
                    resume_val
                        .take()
                        .expect("is_yielded implies resume_value is some"),
                    true,
                )
            } else {
                // This is the first iteration, call the entrypoint:
                let func = self.module.get_export_func(entrypoint)?;
                self.run_func(func, args, true)
            };
            match run {
                Ok(run_result) => {
                    // Check if the yield came from Vmctx::run_await:
                    if run_result.has_yielded::<YieldedFuture>() {
                        let YieldedFuture(future) = *run_result
                            .yielded()
                            .unwrap()
                            .downcast::<YieldedFuture>()
                            .unwrap();
                        // Rehydrate the lifetime from `'static` to `'a`, which
                        // is morally the same lifetime as was passed into
                        // `Vmctx::run_await`.
                        let future = future as LocalBoxFuture<'a, ResumeVal>;
                        // await on the computation. Store its result in
                        // `resume_val`.
                        resume_val = Some(future.await);
                        // Now we want to `Instance::resume_with_val` and start
                        // this cycle over.
                        continue;
                    } else {
                        // Any other result of the run is returned to this
                        // function's caller.
                        break Ok(run_result);
                    }
                }
                _ => {
                    // Any other result of the run is returned to this
                    // function's caller.
                    break run;
                }
            }
        };

        // Return the result of the run.
        return ret;
    }
}

/// A unique type that wraps a boxed future with a boxed return value.
/// Type and lifetime guarantees are maintained by `Vmctx::run_await` and
/// `Instance::run_async`. The user never sees this type.
struct YieldedFuture(LocalBoxFuture<'static, ResumeVal>);
/// A unique type for a boxed return value. The user never sees this type.
struct ResumeVal(Box<dyn Any + 'static>);
<commit_msg>rustfmt<commit_after>use crate::error::Error;
use crate::instance::{Instance, RunResult, State, TerminationDetails};
use crate::val::Val;
use crate::vmctx::{Vmctx, VmctxInternal};
use futures::future::{FutureExt, LocalBoxFuture};
use std::any::Any;
use std::future::Future;

impl Vmctx {
    /// Run an `async` computation. A `Vmctx` is passed to ordinary
    /// (synchronous) functions called from WebAssembly. We cannot execute
    /// `async` code in that context, so this method trampolines an `async`
    /// computation back to `Instance::run_async`, which can `.await` on it.
    /// Note that this method may only be used if `Instance::run_async` was
    /// used to run the VM, otherwise it will terminate the instance.
    pub fn run_await<'a, R>(&'a self, f: impl Future<Output = R> + 'a) -> R
    where
        R: Any + 'static,
    {
        // Die if we aren't in Instance::run_async
        match self.instance().state {
            State::Running { async_context } => {
                if !async_context {
                    panic!(TerminationDetails::AwaitNeedsAsync)
                }
            }
            _ => unreachable!("Access to vmctx implies instance is Running"),
        }
        // Wrap the Output of `f` as a boxed ResumeVal. Then, box the entire
        // async computation.
        let f = async move { ResumeVal(Box::new(f.await)) }.boxed_local();
        // Change the lifetime of the async computation from `'a` to `'static.
        // We need to lie about this lifetime so that `YieldedFuture` may impl
        // `Any` and be passed through the yield. `Instance::run_async`
        // rehydrates this lifetime to be at most as long as the Vmctx's `'a`.
        let f = unsafe {
            std::mem::transmute::<LocalBoxFuture<'a, ResumeVal>, LocalBoxFuture<'static, ResumeVal>>(
                f,
            )
        };
        // Wrap the computation in `YieldedFuture` so that
        // `Instance::run_async` can catch and run it.  We will get the
        // `ResumeVal` we applied to `f` above.
        let ResumeVal(v) = self.yield_val_expecting_val(YieldedFuture(f));
        // We may now downcast and unbox the returned Box<dyn Any> into an `R`
        // again.
        *v.downcast().expect("run_async broke invariant")
    }
}

impl Instance {
    /// Run a WebAssembly function with arguments in the guest context at the
    /// given entrypoint. Enable `Vmctx::run_await` to trampoline async
    /// computations back to this context so that we may `.await` on them.
    ///
    /// Aside from asynchrony, this function behaves identically to
    /// `Instance::run`.
    pub async fn run_async<'a>(
        &'a mut self,
        entrypoint: &str,
        args: &[Val],
    ) -> Result<RunResult, Error> {
        if self.is_yielded() {
            return Err(Error::Unsupported(
                "cannot run_async a yielded instance".to_owned(),
            ));
        }

        // Store the ResumeVal here when we get it.
        let mut resume_val: Option<ResumeVal> = None;
        let ret = loop {
            // Run the WebAssembly program
            let run = if self.is_yielded() {
                // A previous iteration of the loop stored the ResumeVal in
                // `resume_val`, send it back to the guest ctx and continue
                // running:
                self._resume_with_val(
                    resume_val
                        .take()
                        .expect("is_yielded implies resume_value is some"),
                    true,
                )
            } else {
                // This is the first iteration, call the entrypoint:
                let func = self.module.get_export_func(entrypoint)?;
                self.run_func(func, args, true)
            };
            match run {
                Ok(run_result) => {
                    // Check if the yield came from Vmctx::run_await:
                    if run_result.has_yielded::<YieldedFuture>() {
                        let YieldedFuture(future) = *run_result
                            .yielded()
                            .unwrap()
                            .downcast::<YieldedFuture>()
                            .unwrap();
                        // Rehydrate the lifetime from `'static` to `'a`, which
                        // is morally the same lifetime as was passed into
                        // `Vmctx::run_await`.
                        let future = future as LocalBoxFuture<'a, ResumeVal>;
                        // await on the computation. Store its result in
                        // `resume_val`.
                        resume_val = Some(future.await);
                        // Now we want to `Instance::resume_with_val` and start
                        // this cycle over.
                        continue;
                    } else {
                        // Any other result of the run is returned to this
                        // function's caller.
                        break Ok(run_result);
                    }
                }
                _ => {
                    // Any other result of the run is returned to this
                    // function's caller.
                    break run;
                }
            }
        };

        // Return the result of the run.
        return ret;
    }
}

/// A unique type that wraps a boxed future with a boxed return value.
/// Type and lifetime guarantees are maintained by `Vmctx::run_await` and
/// `Instance::run_async`. The user never sees this type.
struct YieldedFuture(LocalBoxFuture<'static, ResumeVal>);
/// A unique type for a boxed return value. The user never sees this type.
struct ResumeVal(Box<dyn Any + 'static>);
<|endoftext|>


<commit_before>use super::*;

// test param_list
// fn a() {}
// fn b(x: i32) {}
// fn c(x: i32, ) {}
// fn d(x: i32, y: ()) {}
// fn g1(#[attr1] #[attr2] pat: Type) {}
// fn g2(#[attr1] x: u8) {}
pub(super) fn param_list(p: &mut Parser) {
    list_(p, Flavor::Normal)
}

// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
// fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
pub(super) fn param_list_opt_patterns(p: &mut Parser) {
    list_(p, Flavor::OptionalPattern)
}

pub(super) fn param_list_opt_types(p: &mut Parser) {
    list_(p, Flavor::OptionalType)
}

#[derive(Clone, Copy, Eq, PartialEq)]
enum Flavor {
    OptionalType,
    OptionalPattern,
    Normal,
}

impl Flavor {
    fn type_required(self) -> bool {
        match self {
            Flavor::OptionalType => false,
            _ => true,
        }
    }
}

fn list_(p: &mut Parser, flavor: Flavor) {
    let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
    assert!(p.at(bra));
    let m = p.start();
    p.bump();
    if flavor.type_required() {
        attributes::outer_attributes(p);
        opt_self_param(p);
    }
    while !p.at(EOF) && !p.at(ket) && !(flavor.type_required() && p.at(T![...])) {
        attributes::outer_attributes(p);

        if p.at(T![...]) {
            break;
        }

        if !p.at_ts(VALUE_PARAMETER_FIRST) {
            p.error("expected value parameter");
            break;
        }
        value_parameter(p, flavor);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
    // test param_list_vararg
    // extern "C" { fn printf(format: *const i8, ...) -> i32; }
    // extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
    if flavor.type_required() {
        p.eat(T![...]);
    }
    p.expect(ket);
    m.complete(p, PARAM_LIST);
}

const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);

fn value_parameter(p: &mut Parser, flavor: Flavor) {
    let m = p.start();
    match flavor {
        Flavor::OptionalType | Flavor::Normal => {
            patterns::pattern(p);
            if p.at(T![:]) || flavor.type_required() {
                types::ascription(p)
            }
        }
        // test value_parameters_no_patterns
        // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
        Flavor::OptionalPattern => {
            let la0 = p.current();
            let la1 = p.nth(1);
            let la2 = p.nth(2);
            let la3 = p.nth(3);

            // test trait_fn_placeholder_parameter
            // trait Foo {
            //     fn bar(_: u64, mut x: i32);
            //     fn bar(#[attr] _: u64, #[attr] mut x: i32);
            // }
            if (la0 == IDENT || la0 == T![_]) && la1 == T![:]
                || la0 == T![mut] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:]
            {
                patterns::pattern(p);
                types::ascription(p);
            } else {
                types::type_(p);
            }
        }
    }
    m.complete(p, PARAM);
}

// test self_param
// impl S {
//     fn a(self) {}
//     fn b(&self,) {}
//     fn c(&'a self,) {}
//     fn d(&'a mut self, x: i32) {}
//     fn e(mut self) {}
//     fn f(#[must_use] self) {}
//     fn g1(#[attr] self) {}
//     fn g2(#[attr] &self) {}
//     fn g3<'a>(#[attr] &mut self) {}
//     fn g4<'a>(#[attr] &'a self) {}
//     fn g5<'a>(#[attr] &'a mut self) {}
// }
fn opt_self_param(p: &mut Parser) {
    let m;
    if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
        m = p.start();
        p.eat(T![mut]);
        p.eat(T![self]);
        // test arb_self_types
        // impl S {
        //     fn a(self: &Self) {}
        //     fn b(mut self: Box<Self>) {}
        //     fn c(#[attr] self: Self) {}
        //     fn d(#[attr] self: Rc<Self>) {}
        // }
        if p.at(T![:]) {
            types::ascription(p);
        }
    } else {
        let la1 = p.nth(1);
        let la2 = p.nth(2);
        let la3 = p.nth(3);
        let n_toks = match (p.current(), la1, la2, la3) {
            (T![&], T![self], _, _) => 2,
            (T![&], T![mut], T![self], _) => 3,
            (T![&], LIFETIME, T![self], _) => 3,
            (T![&], LIFETIME, T![mut], T![self]) => 4,
            _ => return,
        };
        m = p.start();
        for _ in 0..n_toks {
            p.bump();
        }
    }
    m.complete(p, SELF_PARAM);
    if !p.at(T![')']) {
        p.expect(T![,]);
    }
}
<commit_msg>Deduplicate while loop break condition<commit_after>use super::*;

// test param_list
// fn a() {}
// fn b(x: i32) {}
// fn c(x: i32, ) {}
// fn d(x: i32, y: ()) {}
// fn g1(#[attr1] #[attr2] pat: Type) {}
// fn g2(#[attr1] x: u8) {}
pub(super) fn param_list(p: &mut Parser) {
    list_(p, Flavor::Normal)
}

// test param_list_opt_patterns
// fn foo<F: FnMut(&mut Foo<'a>)>(){}
// fn foo<F: FnMut(#[attr] &mut Foo<'a>)>(){}
pub(super) fn param_list_opt_patterns(p: &mut Parser) {
    list_(p, Flavor::OptionalPattern)
}

pub(super) fn param_list_opt_types(p: &mut Parser) {
    list_(p, Flavor::OptionalType)
}

#[derive(Clone, Copy, Eq, PartialEq)]
enum Flavor {
    OptionalType,
    OptionalPattern,
    Normal,
}

impl Flavor {
    fn type_required(self) -> bool {
        match self {
            Flavor::OptionalType => false,
            _ => true,
        }
    }
}

fn list_(p: &mut Parser, flavor: Flavor) {
    let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
    assert!(p.at(bra));
    let m = p.start();
    p.bump();
    if flavor.type_required() {
        attributes::outer_attributes(p);
        opt_self_param(p);
    }
    while !p.at(EOF) && !p.at(ket) {
        attributes::outer_attributes(p);

        if flavor.type_required() && p.at(T![...]) {
            break;
        }

        if !p.at_ts(VALUE_PARAMETER_FIRST) {
            p.error("expected value parameter");
            break;
        }
        value_parameter(p, flavor);
        if !p.at(ket) {
            p.expect(T![,]);
        }
    }
    // test param_list_vararg
    // extern "C" { fn printf(format: *const i8, ...) -> i32; }
    // extern "C" { fn printf(format: *const i8, #[attr] ...) -> i32; }
    if flavor.type_required() {
        p.eat(T![...]);
    }
    p.expect(ket);
    m.complete(p, PARAM_LIST);
}

const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);

fn value_parameter(p: &mut Parser, flavor: Flavor) {
    let m = p.start();
    match flavor {
        Flavor::OptionalType | Flavor::Normal => {
            patterns::pattern(p);
            if p.at(T![:]) || flavor.type_required() {
                types::ascription(p)
            }
        }
        // test value_parameters_no_patterns
        // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
        Flavor::OptionalPattern => {
            let la0 = p.current();
            let la1 = p.nth(1);
            let la2 = p.nth(2);
            let la3 = p.nth(3);

            // test trait_fn_placeholder_parameter
            // trait Foo {
            //     fn bar(_: u64, mut x: i32);
            //     fn bar(#[attr] _: u64, #[attr] mut x: i32);
            // }
            if (la0 == IDENT || la0 == T![_]) && la1 == T![:]
                || la0 == T![mut] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == IDENT && la2 == T![:]
                || la0 == T![&] && la1 == T![mut] && la2 == IDENT && la3 == T![:]
            {
                patterns::pattern(p);
                types::ascription(p);
            } else {
                types::type_(p);
            }
        }
    }
    m.complete(p, PARAM);
}

// test self_param
// impl S {
//     fn a(self) {}
//     fn b(&self,) {}
//     fn c(&'a self,) {}
//     fn d(&'a mut self, x: i32) {}
//     fn e(mut self) {}
//     fn f(#[must_use] self) {}
//     fn g1(#[attr] self) {}
//     fn g2(#[attr] &self) {}
//     fn g3<'a>(#[attr] &mut self) {}
//     fn g4<'a>(#[attr] &'a self) {}
//     fn g5<'a>(#[attr] &'a mut self) {}
// }
fn opt_self_param(p: &mut Parser) {
    let m;
    if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
        m = p.start();
        p.eat(T![mut]);
        p.eat(T![self]);
        // test arb_self_types
        // impl S {
        //     fn a(self: &Self) {}
        //     fn b(mut self: Box<Self>) {}
        //     fn c(#[attr] self: Self) {}
        //     fn d(#[attr] self: Rc<Self>) {}
        // }
        if p.at(T![:]) {
            types::ascription(p);
        }
    } else {
        let la1 = p.nth(1);
        let la2 = p.nth(2);
        let la3 = p.nth(3);
        let n_toks = match (p.current(), la1, la2, la3) {
            (T![&], T![self], _, _) => 2,
            (T![&], T![mut], T![self], _) => 3,
            (T![&], LIFETIME, T![self], _) => 3,
            (T![&], LIFETIME, T![mut], T![self]) => 4,
            _ => return,
        };
        m = p.start();
        for _ in 0..n_toks {
            p.bump();
        }
    }
    m.complete(p, SELF_PARAM);
    if !p.at(T![')']) {
        p.expect(T![,]);
    }
}
<|endoftext|>