<commit_before>extern crate git2;

use git2::*;
use std::process::Command;
use std::path::Path;
use std::path::PathBuf;

const TMP_NAME: &'static str = "tmp_fd2db5f8_bac2_4a1e_9487_4ac3414788aa";

pub trait RepoHost
{
    fn remote_url(&self, &str) -> String;
    fn create_project(&self, &str) -> String;
    fn fetch_url(&self, module: &str) -> String
    {
        self.remote_url(module)
    }
}

pub struct Scratch<'a>
{
    repo: Repository,
    host: &'a RepoHost,
}

impl<'a> Scratch<'a>
{
    pub fn new(path: &Path, host: &'a RepoHost) -> Scratch<'a>
    {
        Scratch {
            repo: Repository::init_bare(&path).expect("could not init scratch"),
            host: host,
        }
    }

    fn tracking(&self, module: &str, branch: &str) -> Option<Object>
    {
        self.host.create_project(&module);

        let remote_name = format!("{}", module);
        let fetch_url = self.host.fetch_url(&module);
        let mut remote = if let Ok(remote) = self.repo.find_remote(&remote_name) {
            remote
        }
        else {
            debug!("==== create remote (remote_name:{}, remote_url:{})",
                   &remote_name,
                   &fetch_url);
            self.repo.remote(&remote_name, &fetch_url).expect("can't create remote")
        };

        let rs = remote.get_refspec(0).unwrap().str().unwrap().to_string();
        remote.fetch(&[&rs], None, None).expect("fetch failed");
        return self.repo
            .revparse_single(&format!("remotes/{}/{}", module, branch))
            .ok();
    }

    fn call_git(self: &Scratch<'a>, cmd: &str) -> Result<String, Error>
    {
        let args: Vec<&str> = cmd.split(" ").collect();
        let repo_path = &self.repo.path();
        let mut c = Command::new("git");
        c.env("GIT_DIR", repo_path.as_os_str());
        c.args(&args);

        let output = c.output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
        Ok(String::from_utf8(output.stderr).expect("cannot decode utf8"))
    }

    // force push of the new revision-object to temp repo
    pub fn transfer(&self, rev: &str, source: &Path) -> Object
    {
        // TODO: implement using libgit
        let target = &self.repo.path();
        let shell = Shell { cwd: source.to_path_buf() };
        // create tmp branch
        shell.command(&format!("git branch -f {} {}", TMP_NAME, rev));
        // force push
        shell.command(&format!("git push --force {} {}",
                               &target.to_string_lossy(),
                               TMP_NAME));
        // delete tmp branch
        shell.command(&format!("git branch -D {}", TMP_NAME));

        let obj = self.repo.revparse_single(rev).expect("can't find transfered ref");
        return obj;
    }

    // takes everything from base except it's tree and replaces it with the tree
    // given
    fn rewrite(&self, base: &Commit, parents: &[&Commit], tree: &Tree) -> Result<Oid, Error>
    {
        if parents.len() != 0 {
            try!(self.repo.set_head_detached(parents[0].id()));
        }
        self.repo.commit(Some("HEAD"),
                         &base.author(),
                         &base.committer(),
                         &base.message().unwrap_or("no message"),
                         tree,
                         parents)
    }

    fn push(&self, oid: Oid, module: &str, target: &str)
    {
        let commit = &self.repo.find_commit(oid).expect("can't find commit");
        self.repo.set_head_detached(commit.id()).expect("can't detach HEAD");
        let output = self.call_git(&format!("push {} HEAD:{}",
                               self.host.remote_url(module),
                               target))
            .expect("can't push");
        debug!("{}", output);
    }

    fn subtree(&self, tree: &Tree, path: &Path) -> Option<Tree>
    {
        if let Some(oid) = tree.get_path(path).map(|x| x.id()).ok() {
            return self.repo.find_tree(oid).ok();
        }
        else {
            return None;
        }
    }

    fn module_to_subfolder(&self,
                           module_path: &Path,
                           module_tree: &Tree,
                           master_tree: &Tree)
        -> Result<Oid, Error>
    {
        assert!(module_path.components().count() == 2); // FIXME: drop this requirement
        let parent_path = module_path.parent().expect("module not in subdir");
        let module_name = module_path.file_name().expect("no module name");

        let modules_tree = {
            let mut builder = try!(self.repo
                .treebuilder(Some(&self.subtree(master_tree, parent_path)
                    .unwrap())));
            try!(builder.insert(module_name, module_tree.id(), 0o0040000)); // GIT_FILEMODE_TREE
            try!(builder.write())
        };

        let full_tree = {
            let mut builder = try!(self.repo.treebuilder(Some(master_tree)));
            try!(builder.insert(parent_path, modules_tree, 0o0040000)); // GIT_FILEMODE_TREE
            try!(builder.write())
        };
        Ok(full_tree)
    }

    fn module_paths(&self, object: &Object) -> Vec<String>
    {
        let mut names = Vec::<String>::new();
        let commit = object.as_commit().expect("module_paths: object is not a commit");
        let tree: Tree = commit.tree().expect("module_paths: commit has no tree");

        if let Ok(tree_object) = tree.get_path(&Path::new("modules")) {
            let modules_o = tree_object.to_object(&self.repo).expect("module_paths: to_object");
            if let Some(modules) = modules_o.as_tree() {

                for module in modules.iter() {
                    names.push(format!("modules/{}",
                                       module.name().expect("module_paths: TreeItem has no name"))
                        .to_string());
                }
            }
        }
        return names;
    }

    fn split_subdir(&self, module: &str, newrev: &Oid) -> Object
    {
        // TODO: implement using libgit
        let shell = Shell { cwd: self.repo.path().to_path_buf() };
        shell.command("rm -Rf refs/original");

        self.call_git(&format!("branch -f initial_{} {}", module, newrev))
            .expect("create branch");

        self.call_git(&format!("filter-branch -f --subdirectory-filter {}/ -- initial_{}",
                               module,
                               module))
            .expect("error in filter-branch");

        return self.repo
            .revparse_single(&format!("initial_{}", module))
            .expect("can't find rewritten branch");
    }
}

pub fn module_review_upload(scratch: &Scratch,
                            newrev: Object,
                            module: &str,
                            central: &str)
    -> Result<(), Error>
{
    debug!(".\n\n==== Doing review upload for module {}",
           &module);

    let new = newrev.id();
    let old = scratch.tracking(&module, "master").expect("no tracking branch 1").id();

    if !try!(scratch.repo.graph_descendant_of(new, old)) {
        debug!(".");
        debug!("==============================================================================");
        debug!("================ Commit not based on master, rebase first! ===================");
        debug!("==============================================================================");
        return Ok(());
    }

    let walk = {
        let mut walk = try!(scratch.repo.revwalk());
        walk.set_sorting(SORT_REVERSE | SORT_TIME);
        try!(walk.push_range(&format!("{}..{}", old, new)));
        walk
    };

    debug!("==== Rewriting commits from {} to {}", old, new);

    let mut current_oid = scratch.tracking(central, "master").expect("no central tracking").id();
    for rev in walk {
        let currev = format!("{}", try!(rev));
        let oldrev = format!("{}", old);
        if oldrev == currev {
            continue;
        }
        debug!("==== Rewriting commit {}", currev);

        let module_commit_obj = try!(scratch.repo.revparse_single(&currev));
        let module_commit = try!(module_commit_obj.as_commit()
            .ok_or(Error::from_str("object is not actually a commit")));
        let module_tree = try!(module_commit.tree());

        let parent_commit = try!(scratch.repo.find_commit(current_oid));

        let new_tree = {
            let master_tree: Tree = try!(parent_commit.tree());
            let new_tree_oid =
                try!(scratch.module_to_subfolder(Path::new(module), &module_tree, &master_tree));
            try!(scratch.repo.find_tree(new_tree_oid))
        };

        current_oid = try!(scratch.rewrite(module_commit, &vec![&parent_commit], &new_tree));
    }

    debug!("");
    debug!("");
    debug!("====================== Doing actual upload in central git ========================");

    scratch.push(current_oid, central, "refs/for/master");

    debug!("==== The review upload may have worked, even if it says error below. Look UP! ====");
    Ok(())
}

pub fn central_submit(scratch: &Scratch, newrev: Object) -> Result<(), Error>
{
    debug!(" ---> central_submit (sha1 of commit: {})",
           &newrev.id());

    let central_commit = try!(newrev.as_commit()
        .ok_or(Error::from_str("could not get commit from obj")));
    let central_tree = try!(central_commit.tree());

    for module in scratch.module_paths(&newrev) {
        debug!("");
        debug!("==== fetching tracking branch for module: {}",
               &module);
        let module_master_commit_obj = match scratch.tracking(&module, "master") {
            Some(obj) => obj,
            None => {
                error!("====    no tracking branch for module {} => project does not exist or is \
                        empty",
                       &module);
                error!("====    initializing with subdir history");
                let commit = scratch.split_subdir(&module, &newrev.id());
                scratch.host.create_project(&module);
                scratch.push(commit.id(), &module, "refs/heads/master");
                scratch.tracking(&module, "master").expect("no tracking branch 3")
            }
        };

        let parents = vec![module_master_commit_obj.as_commit()
                               .expect("could not get commit from obj")];

        debug!("==== checking for changes in module: {:?}",
               module);

        // new tree is sub-tree of complete central tree
        let old_tree = try!(parents[0].tree());
        let new_tree = try!(scratch.repo
            .find_tree(try!(central_tree.get_path(&Path::new(&module))).id()));

        // if sha1's are equal the content is equal
        if new_tree.id() != old_tree.id() {
            debug!("====    commit changes module => make commit on module");
            let module_commit = try!(scratch.rewrite(central_commit, &parents, &new_tree));
            scratch.push(module_commit, &module, "master");
        }
        else {
            debug!("====    commit does not change module => skipping");
        }
    }
    Ok(())
}

pub struct Shell
{
    pub cwd: PathBuf,
}

impl Shell
{
    pub fn command(&self, cmd: &str) -> String
    {
        let output = Command::new("sh")
            .current_dir(&self.cwd)
            .arg("-c")
            .arg(&cmd)
            .output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

        return String::from_utf8(output.stdout).expect("failed to decode utf8").trim().to_string();
    }
}
<commit_msg>restore hook output<commit_after>extern crate git2;

use git2::*;
use std::process::Command;
use std::path::Path;
use std::path::PathBuf;

const TMP_NAME: &'static str = "tmp_fd2db5f8_bac2_4a1e_9487_4ac3414788aa";

pub trait RepoHost
{
    fn remote_url(&self, &str) -> String;
    fn create_project(&self, &str) -> String;
    fn fetch_url(&self, module: &str) -> String
    {
        self.remote_url(module)
    }
}

pub struct Scratch<'a>
{
    repo: Repository,
    host: &'a RepoHost,
}

impl<'a> Scratch<'a>
{
    pub fn new(path: &Path, host: &'a RepoHost) -> Scratch<'a>
    {
        Scratch {
            repo: Repository::init_bare(&path).expect("could not init scratch"),
            host: host,
        }
    }

    fn tracking(&self, module: &str, branch: &str) -> Option<Object>
    {
        self.host.create_project(&module);

        let remote_name = format!("{}", module);
        let fetch_url = self.host.fetch_url(&module);
        let mut remote = if let Ok(remote) = self.repo.find_remote(&remote_name) {
            remote
        }
        else {
            debug!("==== create remote (remote_name:{}, remote_url:{})",
                   &remote_name,
                   &fetch_url);
            self.repo.remote(&remote_name, &fetch_url).expect("can't create remote")
        };

        let rs = remote.get_refspec(0).unwrap().str().unwrap().to_string();
        remote.fetch(&[&rs], None, None).expect("fetch failed");
        return self.repo
            .revparse_single(&format!("remotes/{}/{}", module, branch))
            .ok();
    }

    fn call_git(self: &Scratch<'a>, cmd: &str) -> Result<String, Error>
    {
        let args: Vec<&str> = cmd.split(" ").collect();
        let repo_path = &self.repo.path();
        let mut c = Command::new("git");
        c.env("GIT_DIR", repo_path.as_os_str());
        c.args(&args);

        let output = c.output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));
        Ok(String::from_utf8(output.stderr).expect("cannot decode utf8"))
    }

    // force push of the new revision-object to temp repo
    pub fn transfer(&self, rev: &str, source: &Path) -> Object
    {
        // TODO: implement using libgit
        let target = &self.repo.path();
        let shell = Shell { cwd: source.to_path_buf() };
        // create tmp branch
        shell.command(&format!("git branch -f {} {}", TMP_NAME, rev));
        // force push
        shell.command(&format!("git push --force {} {}",
                               &target.to_string_lossy(),
                               TMP_NAME));
        // delete tmp branch
        shell.command(&format!("git branch -D {}", TMP_NAME));

        let obj = self.repo.revparse_single(rev).expect("can't find transfered ref");
        return obj;
    }

    // takes everything from base except it's tree and replaces it with the tree
    // given
    fn rewrite(&self, base: &Commit, parents: &[&Commit], tree: &Tree) -> Result<Oid, Error>
    {
        if parents.len() != 0 {
            try!(self.repo.set_head_detached(parents[0].id()));
        }
        self.repo.commit(Some("HEAD"),
                         &base.author(),
                         &base.committer(),
                         &base.message().unwrap_or("no message"),
                         tree,
                         parents)
    }

    fn push(&self, oid: Oid, module: &str, target: &str) -> String
    {
        let commit = &self.repo.find_commit(oid).expect("can't find commit");
        self.repo.set_head_detached(commit.id()).expect("can't detach HEAD");
        let output = self.call_git(&format!("push {} HEAD:{}",
                               self.host.remote_url(module),
                               target))
            .expect("can't push");
        format!("{}", output)
    }

    fn subtree(&self, tree: &Tree, path: &Path) -> Option<Tree>
    {
        if let Some(oid) = tree.get_path(path).map(|x| x.id()).ok() {
            return self.repo.find_tree(oid).ok();
        }
        else {
            return None;
        }
    }

    fn module_to_subfolder(&self,
                           module_path: &Path,
                           module_tree: &Tree,
                           master_tree: &Tree)
        -> Result<Oid, Error>
    {
        assert!(module_path.components().count() == 2); // FIXME: drop this requirement
        let parent_path = module_path.parent().expect("module not in subdir");
        let module_name = module_path.file_name().expect("no module name");

        let modules_tree = {
            let mut builder = try!(self.repo
                .treebuilder(Some(&self.subtree(master_tree, parent_path)
                    .unwrap())));
            try!(builder.insert(module_name, module_tree.id(), 0o0040000)); // GIT_FILEMODE_TREE
            try!(builder.write())
        };

        let full_tree = {
            let mut builder = try!(self.repo.treebuilder(Some(master_tree)));
            try!(builder.insert(parent_path, modules_tree, 0o0040000)); // GIT_FILEMODE_TREE
            try!(builder.write())
        };
        Ok(full_tree)
    }

    fn module_paths(&self, object: &Object) -> Vec<String>
    {
        let mut names = Vec::<String>::new();
        let commit = object.as_commit().expect("module_paths: object is not a commit");
        let tree: Tree = commit.tree().expect("module_paths: commit has no tree");

        if let Ok(tree_object) = tree.get_path(&Path::new("modules")) {
            let modules_o = tree_object.to_object(&self.repo).expect("module_paths: to_object");
            if let Some(modules) = modules_o.as_tree() {

                for module in modules.iter() {
                    names.push(format!("modules/{}",
                                       module.name().expect("module_paths: TreeItem has no name"))
                        .to_string());
                }
            }
        }
        return names;
    }

    fn split_subdir(&self, module: &str, newrev: &Oid) -> Object
    {
        // TODO: implement using libgit
        let shell = Shell { cwd: self.repo.path().to_path_buf() };
        shell.command("rm -Rf refs/original");

        self.call_git(&format!("branch -f initial_{} {}", module, newrev))
            .expect("create branch");

        self.call_git(&format!("filter-branch -f --subdirectory-filter {}/ -- initial_{}",
                               module,
                               module))
            .expect("error in filter-branch");

        return self.repo
            .revparse_single(&format!("initial_{}", module))
            .expect("can't find rewritten branch");
    }
}

pub fn module_review_upload(scratch: &Scratch,
                            newrev: Object,
                            module: &str,
                            central: &str)
    -> Result<(), Error>
{
    debug!(".\n\n==== Doing review upload for module {}",
           &module);

    let new = newrev.id();
    let old = scratch.tracking(&module, "master").expect("no tracking branch 1").id();

    if !try!(scratch.repo.graph_descendant_of(new, old)) {
        println!(".");
        println!("==============================================================================");
        println!("================ Commit not based on master, rebase first! ===================");
        println!("==============================================================================");
        return Ok(());
    }

    let walk = {
        let mut walk = try!(scratch.repo.revwalk());
        walk.set_sorting(SORT_REVERSE | SORT_TIME);
        try!(walk.push_range(&format!("{}..{}", old, new)));
        walk
    };

    debug!("==== Rewriting commits from {} to {}", old, new);

    let mut current_oid = scratch.tracking(central, "master").expect("no central tracking").id();
    for rev in walk {
        let currev = format!("{}", try!(rev));
        let oldrev = format!("{}", old);
        if oldrev == currev {
            continue;
        }
        debug!("==== Rewriting commit {}", currev);

        let module_commit_obj = try!(scratch.repo.revparse_single(&currev));
        let module_commit = try!(module_commit_obj.as_commit()
            .ok_or(Error::from_str("object is not actually a commit")));
        let module_tree = try!(module_commit.tree());

        let parent_commit = try!(scratch.repo.find_commit(current_oid));

        let new_tree = {
            let master_tree: Tree = try!(parent_commit.tree());
            let new_tree_oid =
                try!(scratch.module_to_subfolder(Path::new(module), &module_tree, &master_tree));
            try!(scratch.repo.find_tree(new_tree_oid))
        };

        current_oid = try!(scratch.rewrite(module_commit, &vec![&parent_commit], &new_tree));
    }

    println!("");
    println!("");
    println!("====================== Doing actual upload in central git ========================");

    println!("{}",
             scratch.push(current_oid, central, "refs/for/master"));

    println!("==== The review upload may have worked, even if it says error below. Look UP! ====");
    Ok(())
}

pub fn central_submit(scratch: &Scratch, newrev: Object) -> Result<(), Error>
{
    debug!(" ---> central_submit (sha1 of commit: {})",
           &newrev.id());

    let central_commit = try!(newrev.as_commit()
        .ok_or(Error::from_str("could not get commit from obj")));
    let central_tree = try!(central_commit.tree());

    for module in scratch.module_paths(&newrev) {
        debug!("");
        debug!("==== fetching tracking branch for module: {}",
               &module);
        let module_master_commit_obj = match scratch.tracking(&module, "master") {
            Some(obj) => obj,
            None => {
                error!("====    no tracking branch for module {} => project does not exist or is \
                        empty",
                       &module);
                error!("====    initializing with subdir history");
                let commit = scratch.split_subdir(&module, &newrev.id());
                scratch.host.create_project(&module);
                scratch.push(commit.id(), &module, "refs/heads/master");
                scratch.tracking(&module, "master").expect("no tracking branch 3")
            }
        };

        let parents = vec![module_master_commit_obj.as_commit()
                               .expect("could not get commit from obj")];

        debug!("==== checking for changes in module: {:?}",
               module);

        // new tree is sub-tree of complete central tree
        let old_tree = try!(parents[0].tree());
        let new_tree = try!(scratch.repo
            .find_tree(try!(central_tree.get_path(&Path::new(&module))).id()));

        // if sha1's are equal the content is equal
        if new_tree.id() != old_tree.id() {
            debug!("====    commit changes module => make commit on module");
            let module_commit = try!(scratch.rewrite(central_commit, &parents, &new_tree));
            println!("{}",
                     scratch.push(module_commit, &module, "master"));
        }
        else {
            debug!("====    commit does not change module => skipping");
        }
    }
    Ok(())
}

pub struct Shell
{
    pub cwd: PathBuf,
}

impl Shell
{
    pub fn command(&self, cmd: &str) -> String
    {
        let output = Command::new("sh")
            .current_dir(&self.cwd)
            .arg("-c")
            .arg(&cmd)
            .output()
            .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

        return String::from_utf8(output.stdout).expect("failed to decode utf8").trim().to_string();
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::io::{Read, Write};
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{TcpListener, TcpStream, Shutdown};
use mio::util::Slab;
use slab::Index;

pub mod client;
pub mod server;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener() -> Self {
        unimplemented!();
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        // This may need to be in an if events.is_readable() block.
        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => unimplemented!(),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<commit_msg>cargo fmt<commit_after>use std::convert::From;
use std::io::{Read, Write};
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{Shutdown, TcpListener, TcpStream};
use mio::util::Slab;
use slab::Index;

pub mod client;
pub mod server;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener() -> Self {
        unimplemented!();
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        // This may need to be in an if events.is_readable() block.
        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => unimplemented!(),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]

use {Action, InputTranslator, RebindBuilder, InputRebind};

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

fn create_prepopulated_builder() -> TestBuilder {
    use input::keyboard::Key;
    use input::Button::Keyboard;

    RebindBuilder::default()
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}
<commit_msg>Add test_translator_get_action_from_buttonpress(), which checks whether the primary purpose of the translator is fulfilled (it is).<commit_after>#![allow(dead_code, unused_variables)]

use {Action, InputTranslator, RebindBuilder, InputRebind, Translated};
use input::Input;
use input::Button::Keyboard;
use input::keyboard::Key;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
enum TestAction {
    Action1, Action2, Action3, Action4, Action5,
    Action6, Action7, Action8, Action9, Action10
}

impl Action for TestAction { }

type TestBuilder = RebindBuilder<TestAction>;
type TestTranslator = InputTranslator<TestAction>;
type TestRebind = InputRebind<TestAction>;

fn create_prepopulated_builder() -> TestBuilder {
    RebindBuilder::default()
        .with_action_mapping(Keyboard(Key::Up),    TestAction::Action1)
        .with_action_mapping(Keyboard(Key::W),     TestAction::Action1)
        .with_action_mapping(Keyboard(Key::Down),  TestAction::Action2)
        .with_action_mapping(Keyboard(Key::S),     TestAction::Action2)
        .with_action_mapping(Keyboard(Key::Left),  TestAction::Action3)
        .with_action_mapping(Keyboard(Key::A),     TestAction::Action3)
        .with_action_mapping(Keyboard(Key::Right), TestAction::Action4)
        .with_action_mapping(Keyboard(Key::D),     TestAction::Action4)
}

#[test]
fn test_translator_get_action_from_buttonpress() {
    let translator = create_prepopulated_builder().build_translator();

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Down))).unwrap(),
               Translated::Press(TestAction::Action2));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::D))).unwrap(),
               Translated::Press(TestAction::Action4));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::Left))).unwrap(),
               Translated::Press(TestAction::Action3));

    assert_eq!(translator.translate(&Input::Press(Keyboard(Key::W))).unwrap(),
               Translated::Press(TestAction::Action1));
}

#[test]
fn test_conversion_from_rebind_to_translator() {
    let translator = create_prepopulated_builder().build_translator();

    let translator_clone = translator.clone();
    let converted_translator = Into::<TestTranslator>::into(
            Into::<TestRebind>::into(translator));

    assert_eq!(translator_clone, converted_translator);
}
<|endoftext|>


<commit_before>use std::default:: { Default };
use std::collections:: { HashMap };
use std::ops::AddAssign;
use branch:: { BranchUnit };
use lcov_parser:: { LineData, FunctionData, BranchData };

type LineNumber = u32;
type ExecutionCount = u32;
type FunctionName = String;

pub type TestSum = Test;

#[derive(Debug,Clone)]
pub struct Test {
    line: HashMap<LineNumber, ExecutionCount>,
    func: HashMap<FunctionName, ExecutionCount>,
    branch: HashMap<LineNumber, HashMap<BranchUnit, ExecutionCount>>
}

impl Default for Test {
    fn default() -> Self {
        Test {
            line: HashMap::new(),
            func: HashMap::new(),
            branch: HashMap::new()
        }
    }
}

impl Test {
    pub fn new() -> Self {
        Test {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }

    /// Add the number of times of execution of the line
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge::TestSum;
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_line_count(&1, &1);
    /// sum.add_line_count(&1, &2);
    ///
    /// assert_eq!(sum.get_line_count(&1), Some(&3));
    /// ```
    pub fn add_line_count(&mut self, line_number: &u32, exec_count: &u32) {
        let mut line_count = self.line.entry(line_number.clone())
            .or_insert(0);
        *line_count += *exec_count;
    }

    pub fn get_line_count(&self, line_number: &u32) -> Option<&u32> {
        self.line.get(line_number)
    }

    pub fn add_func_count(&mut self, func_name: &String, exec_count: &u32) {
        let mut func_count = self.func.entry(func_name.clone())
            .or_insert(0);
        *func_count += *exec_count;
    }

    pub fn get_func_count(&self, func_name: &String) -> Option<&u32> {
        self.func.get(func_name)
    }

    /// Add the number of times of execution of the branch
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge:: { TestSum, BranchUnit };
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &1);
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &2);
    ///
    /// let branch = sum.get_branch_count(&1);
    /// let branch_count = branch.unwrap().get(&BranchUnit::new(1, 1));
    ///
    /// assert_eq!(branch_count, Some(&3));
    /// ```
    pub fn add_branch_count(&mut self, line_number: &u32, unit: &BranchUnit, exec_count: &u32) {
        let mut branch = self.branch.entry(line_number.clone())
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit.clone())
            .or_insert(0);

        *branch_count += *exec_count;
    }

    pub fn get_branch_count(&self, line_number: &u32) -> Option<&HashMap<BranchUnit, u32>> {
        self.branch.get(line_number)
    }
}

impl<'a> AddAssign<&'a LineData> for Test {
    fn add_assign(&mut self, data: &'a LineData) {
        let mut line_count = self.line.entry(data.line)
            .or_insert(0);
        *line_count += data.count;
    }
}

impl<'a> AddAssign<&'a FunctionData> for Test {
    fn add_assign(&mut self, data: &'a FunctionData) {
        let mut func_count = self.func.entry(data.name.clone())
            .or_insert(0);
        *func_count += data.count;
    }
}

impl<'a> AddAssign<&'a BranchData> for Test {
    fn add_assign(&mut self, data: &'a BranchData) {
        let unit = BranchUnit::new(data.block, data.branch);

        let mut branch = self.branch.entry(data.line)
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit)
            .or_insert(0);

        *branch_count += data.taken;
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use test:: { Test };
    use branch:: { BranchUnit };
    use lcov_parser:: { LineData, FunctionData, BranchData };

    #[test]
    fn add_line_data() {
        let mut test = Test::new();

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&1u32) );

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&2u32) );
    }

    #[test]
    fn add_func_data() {
        let mut test = Test::new();

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&1u32) );

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&2u32) );
    }

    #[test]
    fn add_branch_data() {
        let mut test = Test::new();

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut first_branch_count = HashMap::new();
        first_branch_count.insert(BranchUnit::new(1, 1), 1);

        assert_eq!( test.get_branch_count(&1), Some(&first_branch_count) );

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut second_branch_count = HashMap::new();
        second_branch_count.insert(BranchUnit::new(1, 1), 2);

        assert_eq!( test.get_branch_count(&1), Some(&second_branch_count) );
    }
}
<commit_msg>add AddAssign impl<commit_after>use std::default:: { Default };
use std::collections:: { HashMap };
use std::ops::AddAssign;
use branch:: { BranchUnit };
use lcov_parser:: { LineData, FunctionData, BranchData };

type LineNumber = u32;
type ExecutionCount = u32;
type FunctionName = String;

pub type TestSum = Test;

#[derive(Debug,Clone)]
pub struct Test {
    line: HashMap<LineNumber, ExecutionCount>,
    func: HashMap<FunctionName, ExecutionCount>,
    branch: HashMap<LineNumber, HashMap<BranchUnit, ExecutionCount>>
}

impl Default for Test {
    fn default() -> Self {
        Test {
            line: HashMap::new(),
            func: HashMap::new(),
            branch: HashMap::new()
        }
    }
}

impl Test {
    pub fn new() -> Self {
        Test {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }
    pub fn lines(&self) -> &HashMap<LineNumber, ExecutionCount> {
        &self.line
    }
    pub fn functions(&self) -> &HashMap<FunctionName, ExecutionCount> {
        &self.func
    }
    pub fn branches(&self) -> &HashMap<LineNumber, HashMap<BranchUnit, ExecutionCount>> {
        &self.branch
    }

    /// Add the number of times of execution of the line
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge::TestSum;
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_line_count(&1, &1);
    /// sum.add_line_count(&1, &2);
    ///
    /// assert_eq!(sum.get_line_count(&1), Some(&3));
    /// ```
    pub fn add_line_count(&mut self, line_number: &u32, exec_count: &u32) {
        let mut line_count = self.line.entry(line_number.clone())
            .or_insert(0);
        *line_count += *exec_count;
    }

    pub fn get_line_count(&self, line_number: &u32) -> Option<&u32> {
        self.line.get(line_number)
    }

    pub fn add_func_count(&mut self, func_name: &String, exec_count: &u32) {
        let mut func_count = self.func.entry(func_name.clone())
            .or_insert(0);
        *func_count += *exec_count;
    }

    pub fn get_func_count(&self, func_name: &String) -> Option<&u32> {
        self.func.get(func_name)
    }

    /// Add the number of times of execution of the branch
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge:: { TestSum, BranchUnit };
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &1);
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &2);
    ///
    /// let branch = sum.get_branch_count(&1);
    /// let branch_count = branch.unwrap().get(&BranchUnit::new(1, 1));
    ///
    /// assert_eq!(branch_count, Some(&3));
    /// ```
    pub fn add_branch_count(&mut self, line_number: &u32, unit: &BranchUnit, exec_count: &u32) {
        let mut branch = self.branch.entry(line_number.clone())
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit.clone())
            .or_insert(0);

        *branch_count += *exec_count;
    }

    pub fn get_branch_count(&self, line_number: &u32) -> Option<&HashMap<BranchUnit, u32>> {
        self.branch.get(line_number)
    }
}

impl<'a> AddAssign<&'a LineData> for Test {
    fn add_assign(&mut self, data: &'a LineData) {
        let mut line_count = self.line.entry(data.line)
            .or_insert(0);
        *line_count += data.count;
    }
}

impl<'a> AddAssign<&'a FunctionData> for Test {
    fn add_assign(&mut self, data: &'a FunctionData) {
        let mut func_count = self.func.entry(data.name.clone())
            .or_insert(0);
        *func_count += data.count;
    }
}

impl<'a> AddAssign<&'a BranchData> for Test {
    fn add_assign(&mut self, data: &'a BranchData) {
        let unit = BranchUnit::new(data.block, data.branch);

        let mut branch = self.branch.entry(data.line)
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit)
            .or_insert(0);

        *branch_count += data.taken;
    }
}

impl<'a> AddAssign<&'a Test> for Test {
    fn add_assign(&mut self, other: &'a Test) {
        let lines = other.lines();

        for (line, count) in lines.iter() {
            if self.line.contains_key(line) {
                let current_count = self.line.get_mut(line).unwrap();
                *current_count += *count;
            } else {
                self.line.insert(*line, *count);
            }
        }

        let functions = other.functions();

        for (name, count) in functions.iter() {
            if self.func.contains_key(name) {
                let current_count = self.func.get_mut(name).unwrap();
                *current_count += *count;
            } else {
                self.func.insert(name.clone(), *count);
            }
        }

        let branches = other.branches();

        for (line, branch) in branches.iter() {
            if self.branch.contains_key(line) {
                let current_branch_count = self.branch.get_mut(line).unwrap();

                for (unit, count) in branch.iter() {
                    if current_branch_count.contains_key(unit) {
                        let current_count = current_branch_count.get_mut(unit).unwrap();
                        *current_count += *count;
                    } else {
                        current_branch_count.insert(unit.clone(), *count);
                    }
                }
            } else {
                self.branch.insert(*line, branch.clone());
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use test:: { Test };
    use branch:: { BranchUnit };
    use lcov_parser:: { LineData, FunctionData, BranchData };

    #[test]
    fn add_line_data() {
        let mut test = Test::new();

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&1u32) );

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&2u32) );
    }

    #[test]
    fn add_func_data() {
        let mut test = Test::new();

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&1u32) );

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&2u32) );
    }

    #[test]
    fn add_branch_data() {
        let mut test = Test::new();

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut first_branch_count = HashMap::new();
        first_branch_count.insert(BranchUnit::new(1, 1), 1);

        assert_eq!( test.get_branch_count(&1), Some(&first_branch_count) );

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut second_branch_count = HashMap::new();
        second_branch_count.insert(BranchUnit::new(1, 1), 2);

        assert_eq!( test.get_branch_count(&1), Some(&second_branch_count) );
    }

    #[test]
    fn add_test_data() {
        let mut test1 = Test::new();
        test1 += &LineData { line: 1, count: 1, checksum: None };
        test1 += &FunctionData { name: "main".to_string(), count: 1 };
        test1 += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let test2 = {
            let mut test2 = Test::new();
            test2 += &LineData { line: 1, count: 1, checksum: None };
            test2 += &FunctionData { name: "main".to_string(), count: 1 };
            test2 += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };
            test2
        };
        test1 += &test2;

        assert_eq!( test1.get_line_count(&1), Some(&2u32) );
        assert_eq!( test1.get_func_count(&"main".to_string()), Some(&2u32) );

        let mut second_branch_count = HashMap::new();
        second_branch_count.insert(BranchUnit::new(1, 1), 2);

        assert_eq!( test1.get_branch_count(&1), Some(&second_branch_count) );
    }
}
<|endoftext|>


<commit_before>//! Functions to read time stamp counters on x86.

use core::mem;
use arch::{_rdtsc, __rdtscp};

/// Read the time stamp counter.
///
/// The RDTSC instruction is not a serializing instruction.
/// It does not necessarily wait until all previous instructions
/// have been executed before reading the counter. Similarly,
/// subsequent instructions may begin execution before the
/// read operation is performed. If software requires RDTSC to be
/// executed only after all previous instructions have completed locally,
/// it can either use RDTSCP or execute the sequence LFENCE;RDTSC.
///
/// # Safety
/// * Causes a GP fault if the TSD flag in register CR4 is set and the CPL
///   is greater than 0.
pub unsafe fn rdtsc() -> u64 {
    mem::transmute(_rdtsc())
}

/// Read the time stamp counter.
///
/// The RDTSCP instruction waits until all previous instructions
/// have been executed before reading the counter.
/// However, subsequent instructions may begin execution
/// before the read operation is performed.
///
/// Volatile is used here because the function may be used to act as
/// an instruction barrier.
///
/// # Safety
/// * Causes a GP fault if the TSD flag in register CR4 is set and the
///   CPL is greater than 0.
pub unsafe fn rdtscp() -> u64 {
    let mut _aux = 0;
    __rdtscp(&mut _aux)
}
<commit_msg>Case using as rather than transmute.<commit_after>//! Functions to read time stamp counters on x86.

use arch::{_rdtsc, __rdtscp};

/// Read the time stamp counter.
///
/// The RDTSC instruction is not a serializing instruction.
/// It does not necessarily wait until all previous instructions
/// have been executed before reading the counter. Similarly,
/// subsequent instructions may begin execution before the
/// read operation is performed. If software requires RDTSC to be
/// executed only after all previous instructions have completed locally,
/// it can either use RDTSCP or execute the sequence LFENCE;RDTSC.
///
/// # Safety
/// * Causes a GP fault if the TSD flag in register CR4 is set and the CPL
///   is greater than 0.
pub unsafe fn rdtsc() -> u64 {
    _rdtsc() as u64
}

/// Read the time stamp counter.
///
/// The RDTSCP instruction waits until all previous instructions
/// have been executed before reading the counter.
/// However, subsequent instructions may begin execution
/// before the read operation is performed.
///
/// Volatile is used here because the function may be used to act as
/// an instruction barrier.
///
/// # Safety
/// * Causes a GP fault if the TSD flag in register CR4 is set and the
///   CPL is greater than 0.
pub unsafe fn rdtscp() -> u64 {
    let mut _aux = 0;
    __rdtscp(&mut _aux)
}
<|endoftext|>


<commit_before>
use std::time::{Instant, Duration};
use std::ops::{Add, Sub, AddAssign, SubAssign};

/// Utility to track time in a program
#[derive(Clone)]
pub struct Timer {
    start: Instant,
    last: Instant,
}

impl Timer {
    pub fn new() -> Timer {
        let now = Instant::now();

        Timer {
            start: now,
            last: now,
        }
    }

    /// Returns `(time_since_start, time_since_last_tick)`
    pub fn tick(&mut self) -> (Time, Time) {
        let now = Instant::now();

        let age = (now - self.start).into();
        let delta = (now - self.last).into();

        self.last = now;

        (age, delta)
    }
}

/// Time, stored as nanoseconds
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(pub u64);

impl Time {
    pub const ZERO: Time = Time(0);
    pub const NANOSECONDS_PER_SECOND: u64 = 1_000_000_000;
    pub const NANOSECONDS_PER_MILISECOND: u64 = 1_000_000;

    pub fn from_ms(ms: u64) -> Time {
        Time(ms * Time::NANOSECONDS_PER_MILISECOND)
    }

    pub fn from_secs(s: u64) -> Time {
        Time(s * Time::NANOSECONDS_PER_SECOND)
    }

    pub fn from_secs_f32(s: f32) -> Time {
        Time((s * Time::NANOSECONDS_PER_SECOND as f32) as u64)
    }

    /// Converts this timing to milliseconds, truncating any overflow. 1.999 ms will be converted to 1 ms.
    pub fn to_ms(self) -> u64 {
        self.0 / Time::NANOSECONDS_PER_MILISECOND
    }

    pub fn to_ms_f32(self) -> f32 {
        self.0 as f32 / Time::NANOSECONDS_PER_MILISECOND as f32
    }

    /// Converts this timing to seconds, truncating any overflow. 1.999 seconds will be converted to 1.
    pub fn to_secs(self) -> u64 {
        self.0 / Time::NANOSECONDS_PER_SECOND
    }

    pub fn to_secs_f32(self) -> f32 {
        self.0 as f32 / Time::NANOSECONDS_PER_SECOND as f32
    }

    pub fn max(self, other: Time) -> Time {
        ::std::cmp::max(self, other)
    }

    pub fn min(self, other: Time) -> Time {
        ::std::cmp::min(self, other)
    }
}

impl Add for Time {
    type Output = Time;
    fn add(self, rhs: Time) -> Time {
        Time(self.0 + rhs.0)
    }
}

impl Sub for Time {
    type Output = Time;
    fn sub(self, rhs: Time) -> Time {
        Time(self.0 - rhs.0)
    }
}

impl AddAssign for Time {
    fn add_assign(&mut self, rhs: Time) {
        self.0 += rhs.0;
    }
}

impl SubAssign for Time {
    fn sub_assign(&mut self, rhs: Time) {
        self.0 -= rhs.0;
    }
}

impl From<Duration> for Time {
    fn from(d: Duration) -> Time {
        Time(d.as_secs()*Time::NANOSECONDS_PER_SECOND + (d.subsec_nanos() as u64))
    }
}

impl From<Time> for Duration {
    fn from(t: Time) -> Duration {
        let nanos = t.0 % Time::NANOSECONDS_PER_SECOND;
        let secs = t.0 / Time::NANOSECONDS_PER_SECOND;
        Duration::new(secs, nanos as u32)
    }
}
<commit_msg>`lerp` for `Time`<commit_after>
use std::time::{Instant, Duration};
use std::ops::{Add, Sub, AddAssign, SubAssign};

/// Utility to track time in a program
#[derive(Clone)]
pub struct Timer {
    start: Instant,
    last: Instant,
}

impl Timer {
    pub fn new() -> Timer {
        let now = Instant::now();

        Timer {
            start: now,
            last: now,
        }
    }

    /// Returns `(time_since_start, time_since_last_tick)`
    pub fn tick(&mut self) -> (Time, Time) {
        let now = Instant::now();

        let age = (now - self.start).into();
        let delta = (now - self.last).into();

        self.last = now;

        (age, delta)
    }
}

/// Time, stored as nanoseconds
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(pub u64);

impl Time {
    pub const ZERO: Time = Time(0);
    pub const NANOSECONDS_PER_SECOND: u64 = 1_000_000_000;
    pub const NANOSECONDS_PER_MILISECOND: u64 = 1_000_000;

    pub fn from_ms(ms: u64) -> Time {
        Time(ms * Time::NANOSECONDS_PER_MILISECOND)
    }

    pub fn from_secs(s: u64) -> Time {
        Time(s * Time::NANOSECONDS_PER_SECOND)
    }

    pub fn from_secs_f32(s: f32) -> Time {
        Time((s * Time::NANOSECONDS_PER_SECOND as f32) as u64)
    }

    /// Converts this timing to milliseconds, truncating any overflow. 1.999 ms will be converted to 1 ms.
    pub fn to_ms(self) -> u64 {
        self.0 / Time::NANOSECONDS_PER_MILISECOND
    }

    pub fn to_ms_f32(self) -> f32 {
        self.0 as f32 / Time::NANOSECONDS_PER_MILISECOND as f32
    }

    /// Converts this timing to seconds, truncating any overflow. 1.999 seconds will be converted to 1.
    pub fn to_secs(self) -> u64 {
        self.0 / Time::NANOSECONDS_PER_SECOND
    }

    pub fn to_secs_f32(self) -> f32 {
        self.0 as f32 / Time::NANOSECONDS_PER_SECOND as f32
    }

    pub fn max(self, other: Time) -> Time {
        ::std::cmp::max(self, other)
    }

    pub fn min(self, other: Time) -> Time {
        ::std::cmp::min(self, other)
    }

    /// Interpolates between the two given times. `t = 0` is `self`, and `t = 1` is `other`. Note
    /// that unlike other lerp functions I commonly use, this one clamps `t` to avoid overflows
    /// with unsigned integers.
    pub fn lerp(self, other: Time, t: f32) -> Time {
        if t <= 0.0 {
            return self;
        } else if t >= 1.0 {
            return other;
        }

        if self.0 > other.0 {
            let d = self.0 - other.0;
            Time(other.0 + (d as f32 * (1.0 - t)) as u64)
        } else {
            let d = other.0 - self.0;
            Time(self.0 + (d as f32 * t) as u64)
        }
    }
}

impl Add for Time {
    type Output = Time;
    fn add(self, rhs: Time) -> Time {
        Time(self.0 + rhs.0)
    }
}

impl Sub for Time {
    type Output = Time;
    fn sub(self, rhs: Time) -> Time {
        Time(self.0 - rhs.0)
    }
}

impl AddAssign for Time {
    fn add_assign(&mut self, rhs: Time) {
        self.0 += rhs.0;
    }
}

impl SubAssign for Time {
    fn sub_assign(&mut self, rhs: Time) {
        self.0 -= rhs.0;
    }
}

impl From<Duration> for Time {
    fn from(d: Duration) -> Time {
        Time(d.as_secs()*Time::NANOSECONDS_PER_SECOND + (d.subsec_nanos() as u64))
    }
}

impl From<Time> for Duration {
    fn from(t: Time) -> Duration {
        let nanos = t.0 % Time::NANOSECONDS_PER_SECOND;
        let secs = t.0 / Time::NANOSECONDS_PER_SECOND;
        Duration::new(secs, nanos as u32)
    }
}
<|endoftext|>


<commit_before><commit_msg>Userland/wtk - Further work on layout::Box's mouse support<commit_after><|endoftext|>


<commit_before>/*
gl/src/gl_wrapper/mod.rs, 2017-07-17

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

pub mod gl_raw {
    #[cfg(feature = "gles")]
    pub use gl_es_generated::*;

    #[cfg(not(feature = "gles"))]
    pub use gl_generated::*;
}

pub mod shader;
pub mod uniform;
pub mod buffer;
pub mod texture;<commit_msg>GLError and get_version_string function<commit_after>/*
gl/src/gl_wrapper/mod.rs, 2017-07-18

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

pub mod gl_raw {
    #[cfg(feature = "gles")]
    pub use gl_es_generated::*;

    #[cfg(not(feature = "gles"))]
    pub use gl_generated::*;
}

pub mod shader;
pub mod uniform;
pub mod buffer;
pub mod texture;

use gl_raw::types::*;

use std::ffi::CStr;

#[derive(Debug)]
enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    UnknownError(GLenum),
}

impl GLError {
    fn get_error(error: GLenum) -> Result<(),GLError> {
        let error;

        unsafe {
            error = gl_raw::GetError();
        }

        if error == gl_raw::NO_ERROR {
            return Ok(());
        }

        let error = match error {
            gl_raw::INVALID_ENUM => GLError::InvalidEnum,
            gl_raw::INVALID_VALUE => GLError::InvalidValue,
            gl_raw::INVALID_OPERATION => GLError::InvalidOperation,
            gl_raw::OUT_OF_MEMORY => GLError::OutOfMemory,
            gl_raw::INVALID_FRAMEBUFFER_OPERATION => GLError::InvalidFramebufferOperation,
            unknown_error => GLError::UnknownError(unknown_error),
        };

        Err(error)
    }
}

fn get_version_string<'a>() -> &'a CStr {
    unsafe {
        let ptr_to_str = gl_raw::GetString(gl_raw::VERSION) as *const i8;
        CStr::from_ptr(ptr_to_str)
    }
}<|endoftext|>


<commit_before>use syntax::{
    ast::Expr,
    ast::{LetStmt, Type::InferType},
    AstNode, TextRange,
};

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

// Assist: replace_turbofish_with_explicit_type
//
// Converts `::<_>` to an explicit type assignment.
//
// ```
// fn make<T>() -> T { ) }
// fn main() {
//     let a = make$0::<i32>();
// }
// ```
// ->
// ```
// fn make<T>() -> T { ) }
// fn main() {
//     let a: i32 = make();
// }
// ```
pub(crate) fn replace_turbofish_with_explicit_type(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;

    let initializer = let_stmt.initializer()?;

    let (turbofish_start, turbofish_type, turbofish_end) = if let Expr::CallExpr(ce) = initializer {
        if let Expr::PathExpr(pe) = ce.expr()? {
            let path = pe.path()?;

            let generic_args = path.segment()?.generic_arg_list()?;

            let colon2 = generic_args.coloncolon_token()?;
            let r_angle = generic_args.r_angle_token()?;

            let turbofish_args_as_string = generic_args
                .generic_args()
                .into_iter()
                .map(|a| -> String { a.to_string() })
                .collect::<Vec<String>>()
                .join(", ");

            (colon2.text_range().start(), turbofish_args_as_string, r_angle.text_range().end())
        } else {
            cov_mark::hit!(not_applicable_if_non_path_function_call);
            return None;
        }
    } else {
        cov_mark::hit!(not_applicable_if_non_function_call_initializer);
        return None;
    };

    let turbofish_range = TextRange::new(turbofish_start, turbofish_end);

    if let None = let_stmt.colon_token() {
        // If there's no colon in a let statement, then there is no explicit type.
        // let x = fn::<...>();
        let ident_range = let_stmt.pat()?.syntax().text_range();

        return acc.add(
            AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite),
            format!("Replace turbofish with explicit type `: <{}>`", turbofish_type),
            turbofish_range,
            |builder| {
                builder.insert(ident_range.end(), format!(": {}", turbofish_type));
                builder.delete(turbofish_range);
            },
        );
    } else if let Some(InferType(t)) = let_stmt.ty() {
        // If there's a type inferrence underscore, we can offer to replace it with the type in
        // the turbofish.
        // let x: _ = fn::<...>();
        let underscore_range = t.syntax().text_range();

        return acc.add(
            AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite),
            format!("Replace `_` with turbofish type `{}`", turbofish_type),
            turbofish_range,
            |builder| {
                builder.replace(underscore_range, turbofish_type);
                builder.delete(turbofish_range);
            },
        );
    }

    None
}

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

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

    #[test]
    fn replaces_turbofish_for_vec_string() {
        check_assist(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = make$0::<Vec<String>>();
}
"#,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: Vec<String> = make();
}
"#,
        );
    }

    #[test]
    fn replace_turbofish_target() {
        check_assist_target(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = $0make::<Vec<String>>();
}
"#,
            r#"::<Vec<String>>"#,
        );
    }

    #[test]
    fn replace_inferred_type_placeholder() {
        check_assist(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: _ = make$0::<Vec<String>>();
}
"#,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: Vec<String> = make();
}
"#,
        );
    }

    #[test]
    fn not_applicable_constant_initializer() {
        cov_mark::check!(not_applicable_if_non_function_call_initializer);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = "foo"$0;
}
"#,
        );
    }

    #[test]
    fn not_applicable_non_path_function_call() {
        cov_mark::check!(not_applicable_if_non_path_function_call);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    $0let a = (|| {})();
}
"#,
        );
    }
}
<commit_msg>fixup! narrow range; method calls; check for only one type<commit_after>use syntax::{
    ast::{Expr, GenericArg, GenericArgList},
    ast::{LetStmt, Type::InferType},
    AstNode, TextRange,
};

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

// Assist: replace_turbofish_with_explicit_type
//
// Converts `::<_>` to an explicit type assignment.
//
// ```
// fn make<T>() -> T { ) }
// fn main() {
//     let a = make$0::<i32>();
// }
// ```
// ->
// ```
// fn make<T>() -> T { ) }
// fn main() {
//     let a: i32 = make();
// }
// ```
pub(crate) fn replace_turbofish_with_explicit_type(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;

    let initializer = let_stmt.initializer()?;

    let (turbofish_range, turbofish_type) = match &initializer {
        Expr::MethodCallExpr(ce) => {
            let generic_args = ce.generic_arg_list()?;
            (turbofish_range(&generic_args)?, turbofish_type(&generic_args)?)
        }
        Expr::CallExpr(ce) => {
            if let Expr::PathExpr(pe) = ce.expr()? {
                let generic_args = pe.path()?.segment()?.generic_arg_list()?;
                (turbofish_range(&generic_args)?, turbofish_type(&generic_args)?)
            } else {
                cov_mark::hit!(not_applicable_if_non_path_function_call);
                return None;
            }
        }
        _ => {
            cov_mark::hit!(not_applicable_if_non_function_call_initializer);
            return None;
        }
    };

    let initializer_start = initializer.syntax().text_range().start();
    if ctx.offset() > turbofish_range.end() || ctx.offset() < initializer_start {
        cov_mark::hit!(not_applicable_outside_turbofish);
        return None;
    }

    if let None = let_stmt.colon_token() {
        // If there's no colon in a let statement, then there is no explicit type.
        // let x = fn::<...>();
        let ident_range = let_stmt.pat()?.syntax().text_range();

        return acc.add(
            AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite),
            format!("Replace turbofish with explicit type `: <{}>`", turbofish_type),
            TextRange::new(initializer_start, turbofish_range.end()),
            |builder| {
                builder.insert(ident_range.end(), format!(": {}", turbofish_type));
                builder.delete(turbofish_range);
            },
        );
    } else if let Some(InferType(t)) = let_stmt.ty() {
        // If there's a type inferrence underscore, we can offer to replace it with the type in
        // the turbofish.
        // let x: _ = fn::<...>();
        let underscore_range = t.syntax().text_range();

        return acc.add(
            AssistId("replace_turbofish_with_explicit_type", AssistKind::RefactorRewrite),
            format!("Replace `_` with turbofish type `{}`", turbofish_type),
            turbofish_range,
            |builder| {
                builder.replace(underscore_range, turbofish_type);
                builder.delete(turbofish_range);
            },
        );
    }

    None
}

/// Returns the type of the turbofish as a String.
/// Returns None if there are 0 or >1 arguments.
fn turbofish_type(generic_args: &GenericArgList) -> Option<String> {
    let turbofish_args: Vec<GenericArg> = generic_args.generic_args().into_iter().collect();

    if turbofish_args.len() != 1 {
        cov_mark::hit!(not_applicable_if_not_single_arg);
        return None;
    }

    // An improvement would be to check that this is correctly part of the return value of the
    // function call, or sub in the actual return type.
    let turbofish_type = turbofish_args[0].to_string();

    Some(turbofish_type)
}

/// Returns the TextRange of the whole turbofish expression, and the generic argument as a String.
fn turbofish_range(generic_args: &GenericArgList) -> Option<TextRange> {
    let colon2 = generic_args.coloncolon_token()?;
    let r_angle = generic_args.r_angle_token()?;

    Some(TextRange::new(colon2.text_range().start(), r_angle.text_range().end()))
}

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

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

    #[test]
    fn replaces_turbofish_for_vec_string() {
        check_assist(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = make$0::<Vec<String>>();
}
"#,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: Vec<String> = make();
}
"#,
        );
    }

    #[test]
    fn replaces_method_calls() {
        // foo.make() is a method call which uses a different expr in the let initializer
        check_assist(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = foo.make$0::<Vec<String>>();
}
"#,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: Vec<String> = foo.make();
}
"#,
        );
    }

    #[test]
    fn replace_turbofish_target() {
        check_assist_target(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = $0make::<Vec<String>>();
}
"#,
            r#"make::<Vec<String>>"#,
        );
    }

    #[test]
    fn not_applicable_outside_turbofish() {
        cov_mark::check!(not_applicable_outside_turbofish);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let $0a = make::<Vec<String>>();
}
"#,
        );
    }

    #[test]
    fn replace_inferred_type_placeholder() {
        check_assist(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: _ = make$0::<Vec<String>>();
}
"#,
            r#"
fn make<T>() -> T {}
fn main() {
    let a: Vec<String> = make();
}
"#,
        );
    }

    #[test]
    fn not_applicable_constant_initializer() {
        cov_mark::check!(not_applicable_if_non_function_call_initializer);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = "foo"$0;
}
"#,
        );
    }

    #[test]
    fn not_applicable_non_path_function_call() {
        cov_mark::check!(not_applicable_if_non_path_function_call);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    $0let a = (|| {})();
}
"#,
        );
    }

    #[test]
    fn non_applicable_multiple_generic_args() {
        cov_mark::check!(not_applicable_if_not_single_arg);
        check_assist_not_applicable(
            replace_turbofish_with_explicit_type,
            r#"
fn make<T>() -> T {}
fn main() {
    let a = make$0::<Vec<String>, i32>();
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>use eyre::{bail, Result};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::sync::{Mutex, MutexGuard};

pub type Subscriber = fn(topic: String, event: serde_json::Value) -> ();

struct Subscription {
    topic: String,
    subscriber: Subscriber,
}

static SUBSCRIPTIONS: Lazy<Mutex<Vec<Subscription>>> = Lazy::new(|| Mutex::new(Vec::new()));

/// Obtain the subscriptions store
fn obtain() -> Result<MutexGuard<'static, Vec<Subscription>>> {
    // Use `lock`, not `try_lock`, which means this thread may block waiting
    // a little for the subscriptions to become available.
    match SUBSCRIPTIONS.lock() {
        Ok(guard) => Ok(guard),
        Err(error) => bail!("While attempting to obtain subscriptions: {}", error),
    }
}

/// Subscribe to a topic
pub fn subscribe(topic: &str, subscriber: Subscriber) -> Result<()> {
    match obtain() {
        Ok(mut subscriptions) => {
            subscriptions.push(Subscription {
                topic: topic.to_string(),
                subscriber,
            });
            Ok(())
        }
        Err(error) => {
            bail!("Unable to subscribe: {}", error.to_string())
        }
    }
}

/// Publish an event for a topic
///
/// Publishing an event should be treated as 'fire-and-forget'.
/// This function does not return an `Err` if it fails but will
/// log an error (if not already attempting to publish to logging channel).
pub fn publish<Event>(topic: &str, event: &Event)
where
    Event: Serialize,
{
    match obtain() {
        Ok(subscriptions) => {
            for subscription in &*subscriptions {
                if subscription.topic == "*"
                    || subscription.topic == topic
                    || topic.starts_with(&subscription.topic)
                {
                    let value = serde_json::to_value(event).unwrap_or(serde_json::Value::Null);
                    (subscription.subscriber)(topic.into(), value)
                }
            }
        }
        Err(error) => {
            // Do not log error if the topic is logging since that could lead to recursion
            if topic != "logging" {
                tracing::error!("Unable to publish event: {}", error.to_string())
            }
        }
    }
}

/// A progress event
///
/// This is the expected structure of events published on the
/// "progress" topic channel. Although all events are simply `serde_json::Value`,
/// this `struct` provides expectations around the shape of those values
/// both for publishers and subscribers.
#[derive(Default, Debug, Deserialize, Serialize)]
pub struct ProgressEvent {
    /// The id of the task that this progress event relates to
    pub id: Option<String>,

    /// The id of the parent task (if any)
    pub parent: Option<String>,

    /// The event message
    pub message: Option<String>,

    /// The current value
    pub current: Option<i64>,

    /// The expected value when complete
    pub expected: Option<i64>,

    // Whether or not the task is complete
    pub complete: bool,
}

/// Publish an event on the "progress" topic channel
pub fn publish_progress(event: ProgressEvent) {
    publish("progress", &event)
}
<commit_msg>chore(Pubsub): Add debug tracing<commit_after>use eyre::{bail, Result};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::sync::{Mutex, MutexGuard};

pub type Subscriber = fn(topic: String, event: serde_json::Value) -> ();

struct Subscription {
    topic: String,
    subscriber: Subscriber,
}

static SUBSCRIPTIONS: Lazy<Mutex<Vec<Subscription>>> = Lazy::new(|| Mutex::new(Vec::new()));

/// Obtain the subscriptions store
fn obtain() -> Result<MutexGuard<'static, Vec<Subscription>>> {
    // Use `lock`, not `try_lock`, which means this thread may block waiting
    // a little for the subscriptions to become available.
    match SUBSCRIPTIONS.lock() {
        Ok(guard) => Ok(guard),
        Err(error) => bail!("While attempting to obtain subscriptions: {}", error),
    }
}

/// Subscribe to a topic
pub fn subscribe(topic: &str, subscriber: Subscriber) -> Result<()> {
    tracing::debug!("Subscribing to topic: {}", topic);

    match obtain() {
        Ok(mut subscriptions) => {
            subscriptions.push(Subscription {
                topic: topic.to_string(),
                subscriber,
            });
            Ok(())
        }
        Err(error) => {
            bail!("Unable to subscribe: {}", error.to_string())
        }
    }
}

/// Publish an event for a topic
///
/// Publishing an event should be treated as 'fire-and-forget'.
/// This function does not return an `Err` if it fails but will
/// log an error (if not already attempting to publish to logging channel).
pub fn publish<Event>(topic: &str, event: &Event)
where
    Event: Serialize,
{
    tracing::debug!("Publishing event for topic: {}", topic);

    match obtain() {
        Ok(subscriptions) => {
            for subscription in &*subscriptions {
                if subscription.topic == "*"
                    || subscription.topic == topic
                    || topic.starts_with(&subscription.topic)
                {
                    let value = serde_json::to_value(event).unwrap_or(serde_json::Value::Null);
                    (subscription.subscriber)(topic.into(), value)
                }
            }
        }
        Err(error) => {
            // Do not log error if the topic is logging since that could lead to recursion
            if topic != "logging" {
                tracing::error!("Unable to publish event: {}", error.to_string())
            }
        }
    }
}

/// A progress event
///
/// This is the expected structure of events published on the
/// "progress" topic channel. Although all events are simply `serde_json::Value`,
/// this `struct` provides expectations around the shape of those values
/// both for publishers and subscribers.
#[derive(Default, Debug, Deserialize, Serialize)]
pub struct ProgressEvent {
    /// The id of the task that this progress event relates to
    pub id: Option<String>,

    /// The id of the parent task (if any)
    pub parent: Option<String>,

    /// The event message
    pub message: Option<String>,

    /// The current value
    pub current: Option<i64>,

    /// The expected value when complete
    pub expected: Option<i64>,

    // Whether or not the task is complete
    pub complete: bool,
}

/// Publish an event on the "progress" topic channel
pub fn publish_progress(event: ProgressEvent) {
    publish("progress", &event)
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    chain_state::ChainState, loaded_data::loaded_module::LoadedModule, runtime::VMRuntime,
};
use bytecode_verifier::VerifiedModule;
use libra_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag},
};
use move_vm_definition::MoveVMImpl;
use vm::{errors::VMResult, gas_schedule::CostTable, transaction_metadata::TransactionMetadata};
use vm_cache_map::Arena;
use vm_runtime_types::{loaded_data::struct_def::StructDef, values::Value};

rental! {
    mod move_vm_definition {
        use super::*;

        #[rental]
        pub struct MoveVMImpl {
            alloc: Box<Arena<LoadedModule>>,
            runtime: VMRuntime<'alloc>,
        }
    }
}

pub struct MoveVM(MoveVMImpl);

impl MoveVM {
    pub fn new() -> Self {
        MoveVM(MoveVMImpl::new(Box::new(Arena::new()), |arena| {
            VMRuntime::new(&*arena)
        }))
    }

    // API for temporal backward compatibility.
    // TODO: Get rid of it later with the following three api after LibraVM refactor.
    pub fn execute_runtime<F, T>(&self, f: F) -> T
    where
        F: FnOnce(&VMRuntime) -> T,
    {
        self.0.rent(|runtime| f(runtime))
    }

    pub fn execute_function<S: ChainState>(
        &self,
        module: &ModuleId,
        function_name: &IdentStr,
        gas_schedule: &CostTable,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
        args: Vec<Value>,
    ) -> VMResult<()> {
        self.0.rent(|runtime| {
            runtime.execute_function(
                chain_state,
                txn_data,
                gas_schedule,
                module,
                function_name,
                args,
            )
        })
    }

    #[allow(unused)]
    pub fn execute_script<S: ChainState>(
        &self,
        script: Vec<u8>,
        gas_schedule: &CostTable,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
        args: Vec<Value>,
    ) -> VMResult<()> {
        self.0.rent(|runtime| {
            runtime.execute_script(chain_state, txn_data, gas_schedule, script, args)
        })
    }

    pub fn publish_module<S: ChainState>(
        &self,
        module: Vec<u8>,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
    ) -> VMResult<()> {
        self.0
            .rent(|runtime| runtime.publish_module(module, chain_state, txn_data))
    }

    pub fn cache_module(&self, module: VerifiedModule) {
        self.0.rent(|runtime| runtime.cache_module(module))
    }

    pub fn resolve_struct_tag_by_name<S: ChainState>(
        &self,
        module_id: &ModuleId,
        name: &Identifier,
        chain_state: &mut S,
    ) -> VMResult<StructTag> {
        self.0
            .rent(|runtime| runtime.resolve_struct_tag_by_name(module_id, name, chain_state))
    }

    pub fn resolve_struct_def_by_name<S: ChainState>(
        &self,
        module_id: &ModuleId,
        name: &Identifier,
        chain_state: &mut S,
    ) -> VMResult<StructDef> {
        self.0
            .rent(|runtime| runtime.resolve_struct_def_by_name(module_id, name, chain_state))
    }
}

impl Default for MoveVM {
    fn default() -> Self {
        Self::new()
    }
}
<commit_msg>[language/vm-runtime] remove unused MoveVM::execute_runtime<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    chain_state::ChainState, loaded_data::loaded_module::LoadedModule, runtime::VMRuntime,
};
use bytecode_verifier::VerifiedModule;
use libra_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag},
};
use move_vm_definition::MoveVMImpl;
use vm::{errors::VMResult, gas_schedule::CostTable, transaction_metadata::TransactionMetadata};
use vm_cache_map::Arena;
use vm_runtime_types::{loaded_data::struct_def::StructDef, values::Value};

rental! {
    mod move_vm_definition {
        use super::*;

        #[rental]
        pub struct MoveVMImpl {
            alloc: Box<Arena<LoadedModule>>,
            runtime: VMRuntime<'alloc>,
        }
    }
}

pub struct MoveVM(MoveVMImpl);

impl MoveVM {
    pub fn new() -> Self {
        MoveVM(MoveVMImpl::new(Box::new(Arena::new()), |arena| {
            VMRuntime::new(&*arena)
        }))
    }

    pub fn execute_function<S: ChainState>(
        &self,
        module: &ModuleId,
        function_name: &IdentStr,
        gas_schedule: &CostTable,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
        args: Vec<Value>,
    ) -> VMResult<()> {
        self.0.rent(|runtime| {
            runtime.execute_function(
                chain_state,
                txn_data,
                gas_schedule,
                module,
                function_name,
                args,
            )
        })
    }

    #[allow(unused)]
    pub fn execute_script<S: ChainState>(
        &self,
        script: Vec<u8>,
        gas_schedule: &CostTable,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
        args: Vec<Value>,
    ) -> VMResult<()> {
        self.0.rent(|runtime| {
            runtime.execute_script(chain_state, txn_data, gas_schedule, script, args)
        })
    }

    pub fn publish_module<S: ChainState>(
        &self,
        module: Vec<u8>,
        chain_state: &mut S,
        txn_data: &TransactionMetadata,
    ) -> VMResult<()> {
        self.0
            .rent(|runtime| runtime.publish_module(module, chain_state, txn_data))
    }

    pub fn cache_module(&self, module: VerifiedModule) {
        self.0.rent(|runtime| runtime.cache_module(module))
    }

    pub fn resolve_struct_tag_by_name<S: ChainState>(
        &self,
        module_id: &ModuleId,
        name: &Identifier,
        chain_state: &mut S,
    ) -> VMResult<StructTag> {
        self.0
            .rent(|runtime| runtime.resolve_struct_tag_by_name(module_id, name, chain_state))
    }

    pub fn resolve_struct_def_by_name<S: ChainState>(
        &self,
        module_id: &ModuleId,
        name: &Identifier,
        chain_state: &mut S,
    ) -> VMResult<StructDef> {
        self.0
            .rent(|runtime| runtime.resolve_struct_def_by_name(module_id, name, chain_state))
    }
}

impl Default for MoveVM {
    fn default() -> Self {
        Self::new()
    }
}
<|endoftext|>