<commit_before>// Syntax: master_server [ip address (0.0.0.0 by default)]
// This was created for HaloMD.

// If the server does not respond in at least this many seconds, it will be dropped from the list.
const DROP_TIME : i64 = 60;

// Blacklist for blocking IPs. Separate with newlines.
// Blacklisting IPs ignores heartbeat and keepalive packets from an IP address.
// That means that servers that are banned will not be immediately removed, but will time out, instead.
const BLACKLIST_FILE : &'static str = "blacklist.txt";

// Read the blacklist every x amount of seconds.
const BLACKLIST_UPDATE_TIME : u32 = 60;

// Note: The master server must have TCP 29920 open and UDP 27900 open.
const BROADCAST_PORT_UDP : u16 = 27900;
const SERVER_LIST_PORT_TCP : u16 = 29920;

// Broadcast packet types.
const KEEPALIVE : u8 = 8;
const HEARTBEAT : u8 = 3;

// Game state changes
const GAMEEXITED : u16 = 2;

// Opcode info
const OPCODE_INDEX : usize = 0;
const OPCODE_AND_HANDSHAKE_LENGTH : usize = 5;

// Broadcasted game name
const HALO_RETAIL : &'static str = "halor";

use std::net::{UdpSocket,TcpListener,SocketAddr};
use std::net::SocketAddr::{V4,V6};
use std::io::{Write,BufReader,BufRead};
use std::env;
use std::fs::File;
use std::thread;
use std::sync::{Arc, Mutex};

extern crate time;

mod halo_server;
use halo_server::HaloServer;

mod heartbeat_packet;
use heartbeat_packet::HeartbeatPacket;

fn get_ip(addr: SocketAddr) -> String {
    match addr {
        V4(ipv4) => ipv4.ip().to_string(),
        V6(ipv6) => "[".to_string() + &ipv6.ip().to_string() + "]"
    }
}

fn main() {
    let count = env::args().count();
    let ip = if count == 2 {
        let j : Vec<_> = env::args().collect();
        j[1].to_string()
    }
    else if count == 1 {
        "0.0.0.0".to_string()
    }
    else {
        println!("Only one argument is allowed: the IP to bind to.");
        return;
    };

    // We need to bind on two different ports. If it failed to bind (invalid IP, port is taken), then we must make sure this is known.
    let halo_socket = match UdpSocket::bind((&ip as &str,BROADCAST_PORT_UDP)) {
        Err(error) => {
            println!("Error creating a UDP socket at {}:{}. {}.",ip,BROADCAST_PORT_UDP,error);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,SERVER_LIST_PORT_TCP)) {
        Err(error) => {
            println!("Error listening to TCP at {}:{}. {}.",ip,SERVER_LIST_PORT_TCP,error);
            return;
        },
        Ok(client_socket) => client_socket
    };

    // Mutex for thread safety.
    let servers_halo: Vec<HaloServer> = Vec::new();
    let servers_mut_udp = Arc::new(Mutex::new(servers_halo));
    let servers_mut_tcp = servers_mut_udp.clone();
    let servers_mut_destruction = servers_mut_udp.clone();

    // Destruction thread. This will remove servers that have not broadcasted their presence in a while.
    thread::spawn(move || {
        loop {
            thread::sleep_ms(10 * 1000);
            let mut servers = servers_mut_destruction.lock().unwrap();
            let timenow = time::now().to_timespec().sec;
            servers.retain(|x| x.last_alive + DROP_TIME > timenow);
        }
    });

    // Blacklist mutex. Concurrency needs to be safe, my friend.
    let blacklist: Vec<String> = Vec::new();
    let blacklist_update = Arc::new(Mutex::new(blacklist));
    let blacklist_udp = blacklist_update.clone();

    // Blacklist read thread.
    thread::spawn(move || {
        loop {
            // Placed in a block so blacklist is unlocked before sleeping to prevent threads from being locked for too long.
            {
                let mut blacklist_ref = blacklist_update.lock().unwrap();
                match File::open(BLACKLIST_FILE) {
                    Ok(file) => {
                        let reader = BufReader::new(&file);
                        match reader.lines().collect() {
                            Err(_) => {
                                blacklist_ref.clear();
                            },
                            Ok(t) => {
                                *blacklist_ref = t;
                            }
                        }
                    },
                    Err(_) => {}
                };
            }
            thread::sleep_ms(BLACKLIST_UPDATE_TIME * 1000);
        }
    });

    // TCP server thread. This is for the HaloMD application.
    thread::spawn(move || {
        loop {
            for stream in client_socket.incoming() {
                let mut client = match stream {
                    Err(_) => continue,
                    Ok(the_stream) => the_stream
                };
                // Unwrap the IP.
                let ip = match client.peer_addr() {
                    Err(_) => continue,
                    Ok(ip) => get_ip(ip)
                };

                let mut ips = String::new();

                // Make servers_ref go out of scope to unlock it for other threads, since we don't need it.
                {
                    let servers_ref = servers_mut_tcp.lock().unwrap();
                    let servers = (*servers_ref).iter();

                    for j in servers {
                        ips = ips + &(j.to_string()) + "\n";
                    }
                }

                // Some number placed after the requester's IP. If you ask me, the source code was abducted by aliens, and this is a tracking number. Regardless, it's needed.
                ips = ips + &ip + ":49149:3425";

                // We may be here a while. Just in case...
                thread::spawn( move || {
                    let _ = client.write_all(ips.as_bytes());
                });
            }
        }
    });

    // UDP server is run on the main thread. Servers broadcast their presence here.

    // These are the allowed game versions. HaloMD and Halo PC 1.09 uses 01.00.09.0620, while Halo PC servers on 1.10 use 01.00.10.0621 (these are also joinable).
    let game_versions = [ "01.00.09.0620".to_string(), "01.00.10.0621".to_string() ];

    let mut buffer = [0; 2048];
    loop {
        let (length, source) = match halo_socket.recv_from(&mut buffer) {
            Err(_) => continue,
            Ok(x) => x
        };
        if length <= OPCODE_INDEX {
            continue;
        }

        if buffer[OPCODE_INDEX] != KEEPALIVE && buffer[OPCODE_INDEX] != HEARTBEAT {
            continue;
        }

        let client_ip = get_ip(source);

        let blacklist_ref = blacklist_udp.lock().unwrap();
        if blacklist_ref.contains(&client_ip) {
            continue;
        }

        // Heartbeat packet. These contain null-terminated C strings and are ordered in key1[0]value1[0]key2[0]value2[0]key3[0]value3[0] where [0] is a byte equal to 0x00.
        if buffer[OPCODE_INDEX] == HEARTBEAT && length > OPCODE_AND_HANDSHAKE_LENGTH {

            let mut servers = servers_mut_udp.lock().unwrap();

            let packet = HeartbeatPacket::from_buffer(&buffer[OPCODE_AND_HANDSHAKE_LENGTH..length]);

            if packet.localport != 0 {
                let updatetime = time::now().to_timespec().sec;
                match servers.iter_mut().position(|x| x.ip == client_ip && x.port == packet.localport) {
                    None => {
                        if game_versions.contains(&packet.gamever) && &packet.gamename == HALO_RETAIL {
                            let serverness = HaloServer { ip:client_ip, port: packet.localport, last_alive: updatetime };
                            (*servers).push(serverness);
                        }
                    }
                    Some(k) => {
                        servers[k].last_alive = updatetime;
                        if packet.statechanged == GAMEEXITED {
                            servers.remove(k);
                        }
                    }
                };
            }
        }

        // Keepalive packet. We need to rely on the origin's port for this, unfortunately. This may mean that the source port is incorrect if the port was changed with NAT.
        else if buffer[OPCODE_INDEX] == KEEPALIVE {
            let mut servers_ref = servers_mut_udp.lock().unwrap();
            let servers = (*servers_ref).iter_mut();

            for i in servers {
                if i.ip == client_ip && i.port == source.port() {
                    i.last_alive = time::now().to_timespec().sec;
                    break;
                }
            }
        }
    }
}
<commit_msg>Making get_ip into a method for fun<commit_after>// Syntax: master_server [ip address (0.0.0.0 by default)]
// This was created for HaloMD.

// If the server does not respond in at least this many seconds, it will be dropped from the list.
const DROP_TIME : i64 = 60;

// Blacklist for blocking IPs. Separate with newlines.
// Blacklisting IPs ignores heartbeat and keepalive packets from an IP address.
// That means that servers that are banned will not be immediately removed, but will time out, instead.
const BLACKLIST_FILE : &'static str = "blacklist.txt";

// Read the blacklist every x amount of seconds.
const BLACKLIST_UPDATE_TIME : u32 = 60;

// Note: The master server must have TCP 29920 open and UDP 27900 open.
const BROADCAST_PORT_UDP : u16 = 27900;
const SERVER_LIST_PORT_TCP : u16 = 29920;

// Broadcast packet types.
const KEEPALIVE : u8 = 8;
const HEARTBEAT : u8 = 3;

// Game state changes
const GAMEEXITED : u16 = 2;

// Opcode info
const OPCODE_INDEX : usize = 0;
const OPCODE_AND_HANDSHAKE_LENGTH : usize = 5;

// Broadcasted game name
const HALO_RETAIL : &'static str = "halor";

use std::net::{UdpSocket,TcpListener,SocketAddr};
use std::net::SocketAddr::{V4,V6};
use std::io::{Write,BufReader,BufRead};
use std::env;
use std::fs::File;
use std::thread;
use std::sync::{Arc, Mutex};

extern crate time;

mod halo_server;
use halo_server::HaloServer;

mod heartbeat_packet;
use heartbeat_packet::HeartbeatPacket;

trait IPString {
    fn ip_string(&self) -> String;
}

impl IPString for SocketAddr {
    fn ip_string(&self) -> String {
        // when self.ip() becomes stable, we won't need to match on the IP version
        match *self {
            V4(ipv4) => ipv4.ip().to_string(),
            V6(ipv6) => "[".to_string() + &ipv6.ip().to_string() + "]"
        }
    }
}

fn main() {
    let count = env::args().count();
    let ip = if count == 2 {
        let j : Vec<_> = env::args().collect();
        j[1].to_string()
    }
    else if count == 1 {
        "0.0.0.0".to_string()
    }
    else {
        println!("Only one argument is allowed: the IP to bind to.");
        return;
    };

    // We need to bind on two different ports. If it failed to bind (invalid IP, port is taken), then we must make sure this is known.
    let halo_socket = match UdpSocket::bind((&ip as &str,BROADCAST_PORT_UDP)) {
        Err(error) => {
            println!("Error creating a UDP socket at {}:{}. {}.",ip,BROADCAST_PORT_UDP,error);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,SERVER_LIST_PORT_TCP)) {
        Err(error) => {
            println!("Error listening to TCP at {}:{}. {}.",ip,SERVER_LIST_PORT_TCP,error);
            return;
        },
        Ok(client_socket) => client_socket
    };

    // Mutex for thread safety.
    let servers_halo: Vec<HaloServer> = Vec::new();
    let servers_mut_udp = Arc::new(Mutex::new(servers_halo));
    let servers_mut_tcp = servers_mut_udp.clone();
    let servers_mut_destruction = servers_mut_udp.clone();

    // Destruction thread. This will remove servers that have not broadcasted their presence in a while.
    thread::spawn(move || {
        loop {
            thread::sleep_ms(10 * 1000);
            let mut servers = servers_mut_destruction.lock().unwrap();
            let timenow = time::now().to_timespec().sec;
            servers.retain(|x| x.last_alive + DROP_TIME > timenow);
        }
    });

    // Blacklist mutex. Concurrency needs to be safe, my friend.
    let blacklist: Vec<String> = Vec::new();
    let blacklist_update = Arc::new(Mutex::new(blacklist));
    let blacklist_udp = blacklist_update.clone();

    // Blacklist read thread.
    thread::spawn(move || {
        loop {
            // Placed in a block so blacklist is unlocked before sleeping to prevent threads from being locked for too long.
            {
                let mut blacklist_ref = blacklist_update.lock().unwrap();
                match File::open(BLACKLIST_FILE) {
                    Ok(file) => {
                        let reader = BufReader::new(&file);
                        match reader.lines().collect() {
                            Err(_) => {
                                blacklist_ref.clear();
                            },
                            Ok(t) => {
                                *blacklist_ref = t;
                            }
                        }
                    },
                    Err(_) => {}
                };
            }
            thread::sleep_ms(BLACKLIST_UPDATE_TIME * 1000);
        }
    });

    // TCP server thread. This is for the HaloMD application.
    thread::spawn(move || {
        loop {
            for stream in client_socket.incoming() {
                let mut client = match stream {
                    Err(_) => continue,
                    Ok(the_stream) => the_stream
                };
                // Unwrap the IP.
                let ip = match client.peer_addr() {
                    Err(_) => continue,
                    Ok(ip) => ip.ip_string()
                };

                let mut ips = String::new();

                // Make servers_ref go out of scope to unlock it for other threads, since we don't need it.
                {
                    let servers_ref = servers_mut_tcp.lock().unwrap();
                    let servers = (*servers_ref).iter();

                    for j in servers {
                        ips = ips + &(j.to_string()) + "\n";
                    }
                }

                // Some number placed after the requester's IP. If you ask me, the source code was abducted by aliens, and this is a tracking number. Regardless, it's needed.
                ips = ips + &ip + ":49149:3425";

                // We may be here a while. Just in case...
                thread::spawn( move || {
                    let _ = client.write_all(ips.as_bytes());
                });
            }
        }
    });

    // UDP server is run on the main thread. Servers broadcast their presence here.

    // These are the allowed game versions. HaloMD and Halo PC 1.09 uses 01.00.09.0620, while Halo PC servers on 1.10 use 01.00.10.0621 (these are also joinable).
    let game_versions = [ "01.00.09.0620".to_string(), "01.00.10.0621".to_string() ];

    let mut buffer = [0; 2048];
    loop {
        let (length, source) = match halo_socket.recv_from(&mut buffer) {
            Err(_) => continue,
            Ok(x) => x
        };
        if length <= OPCODE_INDEX {
            continue;
        }

        if buffer[OPCODE_INDEX] != KEEPALIVE && buffer[OPCODE_INDEX] != HEARTBEAT {
            continue;
        }

        let client_ip = source.ip_string();

        let blacklist_ref = blacklist_udp.lock().unwrap();
        if blacklist_ref.contains(&client_ip) {
            continue;
        }

        // Heartbeat packet. These contain null-terminated C strings and are ordered in key1[0]value1[0]key2[0]value2[0]key3[0]value3[0] where [0] is a byte equal to 0x00.
        if buffer[OPCODE_INDEX] == HEARTBEAT && length > OPCODE_AND_HANDSHAKE_LENGTH {

            let mut servers = servers_mut_udp.lock().unwrap();

            let packet = HeartbeatPacket::from_buffer(&buffer[OPCODE_AND_HANDSHAKE_LENGTH..length]);

            if packet.localport != 0 {
                let updatetime = time::now().to_timespec().sec;
                match servers.iter_mut().position(|x| x.ip == client_ip && x.port == packet.localport) {
                    None => {
                        if game_versions.contains(&packet.gamever) && &packet.gamename == HALO_RETAIL {
                            let serverness = HaloServer { ip:client_ip, port: packet.localport, last_alive: updatetime };
                            (*servers).push(serverness);
                        }
                    }
                    Some(k) => {
                        servers[k].last_alive = updatetime;
                        if packet.statechanged == GAMEEXITED {
                            servers.remove(k);
                        }
                    }
                };
            }
        }

        // Keepalive packet. We need to rely on the origin's port for this, unfortunately. This may mean that the source port is incorrect if the port was changed with NAT.
        else if buffer[OPCODE_INDEX] == KEEPALIVE {
            let mut servers_ref = servers_mut_udp.lock().unwrap();
            let servers = (*servers_ref).iter_mut();

            for i in servers {
                if i.ip == client_ip && i.port == source.port() {
                    i.last_alive = time::now().to_timespec().sec;
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//src/annotate.rs

use std::io::{BufRead, BufReader};
use std::fs::File;
use regex::Regex;
use std::collections::HashMap;

pub fn distance_to_gene(sv_pos: usize, gene_pos: usize) ->usize {
    let mut dist: Vec<usize> = Vec::new();
    dist.push(0);
    dist.push(gene_pos - sv_pos);
    dist.push(sv_pos - gene_pos);
    dist.sort_by(|a, b| b.cmp(a));
    dist[1]
}

pub fn annotate(sv_path: String, bed_path: String) {
    let sv_file_header: String = "CHROM\tSTRAND\tPOSITION\tNEARBY_FEATURES\t\tCHROM\tSTRAND\tPOSITION\tNEARBY_FEATURES\t\tNUM_SPANNING_FRAGMENTS\tNUM_SPANNING_MATES\tSPANNING_MATE_SEQUENCES".to_uppercase();
    let mut sv  = BufReader::new(File::open(&sv_path).unwrap());
    let mut bed = BufReader::new(File::open(&bed_path).unwrap());

    let mut features: Vec<String> = Vec::new();

    for b in bed.lines() {
        let line = b.unwrap();
        let cols: Vec<&str> = line.split('\t').collect();
        let mut feat: Vec<&str> = Vec::new();
        feat.push(cols[0]); feat.push(cols[5]);
        feat.push(cols[1]);feat.push(cols[2]); feat.push(cols[3]);
        features.push(feat.join("\t"));
    }

    let re = Regex::new(r" \(ENSG.*?\)").unwrap();
    println!("{}", sv_file_header);
    for l in sv.lines() {
		let line: String = l.unwrap();
		if !line.starts_with("chr") { continue; }

		let mut tokens: Vec<&str> = line.split('\t').collect();
        let chr_1    = tokens[0];
        let strand_1 = tokens[1];
        let pos_1    = tokens[2].parse::<usize>().unwrap();

        let chr_2    = tokens[5];
        let strand_2 = tokens[6];
        let pos_2    = tokens[7].parse::<usize>().unwrap();

        let mut nearby_features_1 = HashMap::new();
        let mut nearby_features_2 = HashMap::new();

        for f in &features {
            let fe: Vec<&str> = f.split('\t').collect();
            if fe[0] == chr_1 {
                nearby_features_1.insert(re.replace(fe[4], "").to_string(), distance_to_gene(pos_1, fe[2].parse::<usize>().unwrap()));
            }
        }

        for f in &features {
            let fe: Vec<&str> = f.split('\t').collect();
            if fe[0] == chr_2 {
                nearby_features_2.insert(re.replace(fe[4], "").to_string(), distance_to_gene(pos_1, fe[2].parse::<usize>().unwrap()));
            }
        }

        nearby_features_1.retain(|ref x, &mut v| v < 100_000);
        nearby_features_2.retain(|ref x, &mut v| v < 100_000);

        let mut sorted_1: Vec<String> = nearby_features_1.keys().cloned().collect();
        		sorted_1.sort();
		let mut sorted_2: Vec<String> = nearby_features_2.keys().cloned().collect();
        		sorted_2.sort();

		let mut nb_feat1 = HashMap::new();
		let mut nb_feat2 = HashMap::new();

		for key in &sorted_1 {
			if nearby_features_1.contains_key(key) {
				nb_feat1.insert(key, nearby_features_1.get(key).unwrap());
			} else { continue; }
		}

		for key in sorted_2.iter() {
			if nearby_features_2.contains_key(key) {
				nb_feat2.insert(key, nearby_features_2.get(key).unwrap());
			} else { continue; }
		}

		let mut nb1 = String::new();
		let mut nb2 = String::new();

	}
}
<commit_msg>src/annotate.rs added<commit_after>//src/annotate.rs

use std::io::{BufRead, BufReader};
use std::fs::File;
use regex::Regex;
use std::collections::HashMap;

pub fn distance_to_gene(sv_pos: usize, gene_pos: usize) ->usize {
    let mut dist: Vec<usize> = Vec::new();
    dist.push(0);
    dist.push(gene_pos - sv_pos);
    dist.push(sv_pos - gene_pos);
    dist.sort_by(|a, b| b.cmp(a));
    dist[1]
}

pub fn annotate(sv_path: String, bed_path: String) {
    let sv_file_header: String = "CHROM\tSTRAND\tPOSITION\tNEARBY_FEATURES\t\tCHROM\tSTRAND\tPOSITION\tNEARBY_FEATURES\t\tNUM_SPANNING_FRAGMENTS\tNUM_SPANNING_MATES\tSPANNING_MATE_SEQUENCES".to_uppercase();
    let mut sv  = BufReader::new(File::open(&sv_path).unwrap());
    let mut bed = BufReader::new(File::open(&bed_path).unwrap());

    let mut features: Vec<String> = Vec::new();

    for b in bed.lines() {
        let line = b.unwrap();
        let cols: Vec<&str> = line.split('\t').collect();
        let mut feat: Vec<&str> = Vec::new();
        feat.push(cols[0]); feat.push(cols[5]);
        feat.push(cols[1]);feat.push(cols[2]); feat.push(cols[3]);
        features.push(feat.join("\t"));
    }

    let re = Regex::new(r" \(ENSG.*?\)").unwrap();
    println!("{}", sv_file_header);
    for l in sv.lines() {
		let line: String = l.unwrap();
		if !line.starts_with("chr") { continue; }

		let mut tokens: Vec<&str> = line.split('\t').collect();
        let chr_1    = tokens[0];
        let strand_1 = tokens[1];
        let pos_1    = tokens[2].parse::<usize>().unwrap();

        let chr_2    = tokens[5];
        let strand_2 = tokens[6];
        let pos_2    = tokens[7].parse::<usize>().unwrap();

        let mut nearby_features_1 = HashMap::new();
        let mut nearby_features_2 = HashMap::new();

        for f in &features {
            let fe: Vec<&str> = f.split('\t').collect();
            if fe[0] == chr_1 {
                nearby_features_1.insert(re.replace(fe[4], "").to_string(), distance_to_gene(pos_1, fe[2].parse::<usize>().unwrap()));
            }
        }

        for f in &features {
            let fe: Vec<&str> = f.split('\t').collect();
            if fe[0] == chr_2 {
                nearby_features_2.insert(re.replace(fe[4], "").to_string(), distance_to_gene(pos_1, fe[2].parse::<usize>().unwrap()));
            }
        }

        nearby_features_1.retain(|ref x, &mut v| v < 100_000);
        nearby_features_2.retain(|ref x, &mut v| v < 100_000);

        let mut sorted_1: Vec<String> = nearby_features_1.keys().cloned().collect();
        		sorted_1.sort();
		let mut sorted_2: Vec<String> = nearby_features_2.keys().cloned().collect();
        		sorted_2.sort();

		let mut nb_feat1 = HashMap::new();
		let mut nb_feat2 = HashMap::new();

		for key in &sorted_1 {
			if nearby_features_1.contains_key(key) {
				nb_feat1.insert(key, nearby_features_1.get(key).unwrap());
			} else { continue; }
		}

		for key in sorted_2.iter() {
			if nearby_features_2.contains_key(key) {
				nb_feat2.insert(key, nearby_features_2.get(key).unwrap());
			} else { continue; }
		}

		let mut nb1: Vec<String> = vec![];
		let mut nb2: Vec<String> = vec![];

		for (g, n) in nb_feat1 { nb1.push(format!("{} ({:?})", g, n)); }
		for (g, n) in nb_feat2 { nb2.push(format!("{} ({:?})", g, n)); }
        //TODO push nb1 and nb2 to tokens[3] and tokens[8]
        //tokens[3] = &nb1[..].to_owned().join(",");
        //FIXME above pushing not compiling "borrow error"
        println!("{}\t{}\t{}\t{}\t{}", tokens[..3].join("\t"), nb1.join(", "), tokens[4..8].join("\t"), nb2.join(", "), tokens[9..].join("\t"));
	}
}
<|endoftext|>


<commit_before>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](::client) and [Servers](::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - The [`Payload`](body::Payload) trait the describes all possible bodies. hyper
//!   allows any body type that implements `Payload`, allowing applications to
//!   have fine-grained control over their streaming.
//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`,
//!  and returned by hyper as a "receive stream" (so, for server requests and
//!  client responses). It is also a decent default implementation if you don't
//!  have very custom needs of your send streams.

#[doc(hidden)]
pub use http_body::Body as HttpBody;

pub use self::body::{Body, Sender};
pub use self::chunk::Chunk;
pub use self::payload::Payload;

mod body;
mod chunk;
mod payload;

/// An optimization to try to take a full body if immediately available.
///
/// This is currently limited to *only* `hyper::Body`s.
pub(crate) fn take_full_data<T: Payload + 'static>(body: &mut T) -> Option<T::Data> {
    use std::any::{Any, TypeId};

    // This static type check can be optimized at compile-time.
    if TypeId::of::<T>() == TypeId::of::<Body>() {
        let mut full = (body as &mut dyn Any)
            .downcast_mut::<Body>()
            .expect("must be Body")
            .take_full_data();
        // This second cast is required to make the type system happy.
        // Without it, the compiler cannot reason that the type is actually
        // `T::Data`. Oh wells.
        //
        // It's still a measurable win!
        (&mut full as &mut dyn Any)
            .downcast_mut::<Option<T::Data>>()
            .expect("must be T::Data")
            .take()
    } else {
        None
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

<commit_msg>feat(body): replace the `Payload` trait with `HttpBody`<commit_after>//! Streaming bodies for Requests and Responses
//!
//! For both [Clients](::client) and [Servers](::server), requests and
//! responses use streaming bodies, instead of complete buffering. This
//! allows applications to not use memory they don't need, and allows exerting
//! back-pressure on connections by only reading when asked.
//!
//! There are two pieces to this in hyper:
//!
//! - The [`HttpBody`](body::HttpBody) trait the describes all possible bodies.
//!   hyper allows any body type that implements `HttpBody`, allowing
//!   applications to have fine-grained control over their streaming.
//! - The [`Body`](Body) concrete type, which is an implementation of
//!   `HttpBody`, and returned by hyper as a "receive stream" (so, for server
//!   requests and client responses). It is also a decent default implementation
//!   if you don't have very custom needs of your send streams.

pub use http_body::Body as HttpBody;

pub use self::body::{Body, Sender};
pub use self::chunk::Chunk;
pub(crate) use self::payload::Payload;

mod body;
mod chunk;
mod payload;

/// An optimization to try to take a full body if immediately available.
///
/// This is currently limited to *only* `hyper::Body`s.
pub(crate) fn take_full_data<T: Payload + 'static>(body: &mut T) -> Option<T::Data> {
    use std::any::{Any, TypeId};

    // This static type check can be optimized at compile-time.
    if TypeId::of::<T>() == TypeId::of::<Body>() {
        let mut full = (body as &mut dyn Any)
            .downcast_mut::<Body>()
            .expect("must be Body")
            .take_full_data();
        // This second cast is required to make the type system happy.
        // Without it, the compiler cannot reason that the type is actually
        // `T::Data`. Oh wells.
        //
        // It's still a measurable win!
        (&mut full as &mut dyn Any)
            .downcast_mut::<Option<T::Data>>()
            .expect("must be T::Data")
            .take()
    } else {
        None
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

<|endoftext|>


<commit_before>pub mod dto;
mod suit;
mod rank;

pub use card::suit::Suit;
pub use card::suit::OptionSuit;
pub use card::rank::Rank;
pub use card::rank::OptionRank;

#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
pub struct Card {
    pub suit: Suit,
    pub rank: Rank
}

impl Card {
    pub fn new(suit: Suit, rank: Rank) -> Card {
        Card { suit: suit, rank: rank }
    }
}

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

    #[test]
    fn reversible_suit() {
        let num: u32 = Suit::Heart.into();
        assert_eq!(Some(Suit::Heart), *OptionSuit::from(num));
    }

    #[test]
    fn reversible_rank() {
        let num: u32 = Rank::Ace.into();
        assert_eq!(Some(Rank::Ace), *OptionRank::from(num));
    }

    #[test]
    fn invalid_rank() {
        assert_eq!(None, *OptionRank::from(1));
    }

}
<commit_msg>cleanup<commit_after>pub mod dto;
mod suit;
mod rank;

pub use card::suit::Suit;
pub use card::suit::OptionSuit;
pub use card::rank::Rank;
pub use card::rank::OptionRank;

#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
pub struct Card {
    pub suit: Suit,
    pub rank: Rank
}

impl Card {
    pub fn new(suit: Suit, rank: Rank) -> Card {
        Card { suit: suit, rank: rank }
    }
}

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

    #[test]
    fn reversible_suit() {
        assert_eq!(Some(Suit::Heart), *OptionSuit::from(u32::from(Suit::Heart)));
    }

    #[test]
    fn reversible_rank() {
        assert_eq!(Some(Rank::Ace), *OptionRank::from(u32::from(Rank::Ace)));
    }

    #[test]
    fn invalid_rank() {
        assert_eq!(None, *OptionRank::from(1));
    }

}
<|endoftext|>


<commit_before>// Implements the `zakopane checksum` subcommand.

use std::io::Read;
use std::io::Write;

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
const READ_SIZE: usize = 2 << 20;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    path: std::path::PathBuf,

    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        path: std::path::PathBuf,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            path,
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(MAX_TASKS)),
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

fn checksum_task_impl(path: std::path::PathBuf) -> ChecksumResult {
    let mut hasher = crypto_hash::Hasher::new(crypto_hash::Algorithm::SHA256);
    let mut buffer: Vec<u8> = vec![0; READ_SIZE];
    let mut file = std::fs::File::open(&path).map_err(ZakopaneError::Io)?;
    loop {
        let read_bytes = file.read(&mut buffer).map_err(ZakopaneError::Io)?;
        if read_bytes == 0 {
            let checksum = hasher
                .finish()
                .into_iter()
                .map(|byte| format!("{:02x}", byte))
                .collect::<Vec<String>>()
                .join("");
            return Ok(ChecksumWithPath::new(checksum, path));
        }
        hasher
            .write_all(&buffer[..read_bytes])
            .map_err(ZakopaneError::Io)?;
    }
}

// Represents a spawned checksum task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    semaphore_clone: std::sync::Arc<tokio::sync::Semaphore>,
) {
    let result = checksum_task_impl(path);
    checksum_task_send_result(result, sender);

    // See comment in `ChecksumTaskManager::spawn_task()`.
    semaphore_clone.add_permits(1);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            return sums;
        }
    }
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    path: std::path::PathBuf,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(MAX_TASKS);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(path, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(&context.path).into_iter();
    // The `filter_entry()` call is crafted s.t.
    // *    we skip and don't descend into hidden directories
    // *    unless the hidden directory is the target directory, because
    //      the target directory is always the first yielded value from
    //      the `WalkDir`.
    for entry in walk_iter.filter_entry(|e| {
        e.path() == &context.path
            || !e
                .file_name()
                .to_str()
                .map(|path| path.starts_with("."))
                .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if let Ok(metadata) = std::fs::symlink_metadata(&path) {
                if !metadata.file_type().is_file() {
                    continue;
                }
            } else {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.acquire().await.unwrap();

            // Icky workaround for not being able to pass `SemaphorePermit`
            // directly into a spawned task. Note that new permits are added
            // later in the checksum task.
            //
            // See also: https://github.com/tokio-rs/tokio/issues/1998
            permit.forget();

            let sender = context.sender.clone();
            let semaphore_clone = context.semaphore.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, semaphore_clone));
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(path: std::path::PathBuf) -> String {
    let (dispatcher_data, join_handle) = spawn_collector(path.clone()).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(path: std::path::PathBuf) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(path))
}
<commit_msg>checksum: Erase semaphore workaround<commit_after>// Implements the `zakopane checksum` subcommand.

use std::io::Read;
use std::io::Write;

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
const READ_SIZE: usize = 2 << 20;

struct ChecksumWithPath {
    checksum: String,
    path: std::path::PathBuf,
}

impl ChecksumWithPath {
    pub fn new(checksum: String, path: std::path::PathBuf) -> Self {
        Self { checksum, path }
    }
}

type ChecksumResult = Result<ChecksumWithPath, ZakopaneError>;
type ChecksumTaskJoinHandle = tokio::task::JoinHandle<Vec<ChecksumWithPath>>;

struct ChecksumTaskDispatcherData {
    path: std::path::PathBuf,

    // Rate-limiter for spawned checksum tasks.
    semaphore: std::sync::Arc<tokio::sync::Semaphore>,

    // Counts total number of spawned checksum tasks.
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,

    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
}

impl ChecksumTaskDispatcherData {
    pub fn new(
        path: std::path::PathBuf,
        spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
        sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    ) -> Self {
        Self {
            path,
            semaphore: std::sync::Arc::new(tokio::sync::Semaphore::new(MAX_TASKS)),
            spawn_counter,
            sender,
        }
    }
}

// Sends a checksum task result downstream to the collector task.
fn checksum_task_send_result(
    result: ChecksumResult,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
) {
    if let Err(e) = sender.blocking_send(result) {
        eprintln!("BUG: Sender::send() failed: {}", e);
    }
}

fn checksum_task_impl(path: std::path::PathBuf) -> ChecksumResult {
    let mut hasher = crypto_hash::Hasher::new(crypto_hash::Algorithm::SHA256);
    let mut buffer: Vec<u8> = vec![0; READ_SIZE];
    let mut file = std::fs::File::open(&path).map_err(ZakopaneError::Io)?;
    loop {
        let read_bytes = file.read(&mut buffer).map_err(ZakopaneError::Io)?;
        if read_bytes == 0 {
            let checksum = hasher
                .finish()
                .into_iter()
                .map(|byte| format!("{:02x}", byte))
                .collect::<Vec<String>>()
                .join("");
            return Ok(ChecksumWithPath::new(checksum, path));
        }
        hasher
            .write_all(&buffer[..read_bytes])
            .map_err(ZakopaneError::Io)?;
    }
}

// Represents a spawned checksum task.
//
// `_permit` is moved into this checksum task simply to hold onto the
// semaphore-dispensed resource for the duration of this task.
fn checksum_task(
    path: std::path::PathBuf,
    sender: tokio::sync::mpsc::Sender<ChecksumResult>,
    _permit: tokio::sync::OwnedSemaphorePermit,
) {
    let result = checksum_task_impl(path);
    checksum_task_send_result(result, sender);
}

// Represents the spawned collection task.
async fn collector_task(
    mut receiver: tokio::sync::mpsc::Receiver<ChecksumResult>,
    spawn_counter: std::sync::Arc<std::sync::atomic::AtomicUsize>,
) -> Vec<ChecksumWithPath> {
    let mut sums: Vec<ChecksumWithPath> = Vec::new();
    let mut errors: usize = 0;
    loop {
        while let Some(result) = receiver.recv().await {
            match result {
                Ok(digest_with_path) => sums.push(digest_with_path),
                Err(_) => errors += 1,
            }
        }
        if sums.len() + errors == spawn_counter.load(std::sync::atomic::Ordering::SeqCst) {
            return sums;
        }
    }
}

// Spawns the collector task that listens for checksum results
// provided by the checksum tasks.
async fn spawn_collector(
    path: std::path::PathBuf,
) -> (ChecksumTaskDispatcherData, ChecksumTaskJoinHandle) {
    let (sender, receiver) = tokio::sync::mpsc::channel(MAX_TASKS);
    let spawn_counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
    let join_handle = tokio::task::spawn(collector_task(receiver, spawn_counter.clone()));
    (
        ChecksumTaskDispatcherData::new(path, spawn_counter, sender),
        join_handle,
    )
}

async fn spawn_checksum_tasks(context: ChecksumTaskDispatcherData) {
    let walk_iter = walkdir::WalkDir::new(&context.path).into_iter();
    // The `filter_entry()` call is crafted s.t.
    // *    we skip and don't descend into hidden directories
    // *    unless the hidden directory is the target directory, because
    //      the target directory is always the first yielded value from
    //      the `WalkDir`.
    for entry in walk_iter.filter_entry(|e| {
        e.path() == &context.path
            || !e
                .file_name()
                .to_str()
                .map(|path| path.starts_with("."))
                .unwrap_or(false)
    }) {
        if let Ok(direntry) = entry {
            let path = direntry.into_path();
            if let Ok(metadata) = std::fs::symlink_metadata(&path) {
                if !metadata.file_type().is_file() {
                    continue;
                }
            } else {
                continue;
            }

            context
                .spawn_counter
                .fetch_add(1, std::sync::atomic::Ordering::SeqCst);
            let permit = context.semaphore.clone().acquire_owned().await.unwrap();
            let sender = context.sender.clone();
            tokio::task::spawn_blocking(move || checksum_task(path, sender, permit));
        }
    }
}

// Pretty-prints the sorted `checksums` in a format much like what the
// `sha256sum` binary outputs.
//
// Note that the standard zakopane snapshot header is not added here.
fn pretty_format_checksums(path: std::path::PathBuf, checksums: Vec<ChecksumWithPath>) -> String {
    let mut buffer: Vec<String> = checksums
        .into_iter()
        .map(|e| {
            format!(
                "{}  ./{}",
                e.checksum,
                e.path.strip_prefix(&path).unwrap().to_str().unwrap()
            )
        })
        .collect();
    buffer.push(String::new());
    buffer.join("\n")
}

async fn checksum_impl(path: std::path::PathBuf) -> String {
    let (dispatcher_data, join_handle) = spawn_collector(path.clone()).await;
    spawn_checksum_tasks(dispatcher_data).await;
    let mut checksums: Vec<ChecksumWithPath> = join_handle.await.unwrap();
    checksums.sort_by(|a, b| a.path.cmp(&b.path));
    pretty_format_checksums(path, checksums)
}

pub fn checksum(path: std::path::PathBuf) -> String {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl(path))
}
<|endoftext|>


<commit_before>use binding::vm;

pub struct VM;

impl VM {
    pub fn init() {
        vm::init();
    }
}
<commit_msg>Create VM parse_arguments()<commit_after>use std::slice;

use binding::vm;
use class::object;
use types;

pub struct VM;

impl VM {
    pub fn init() {
        vm::init();
    }

    pub fn parse_arguments(argc: types::argc, arguments: *const types::rb_value) -> Vec<object::Object> {
        let arguments = unsafe {
            slice::from_raw_parts(arguments, argc as usize).to_vec()
        };

        arguments.iter().map(|value| object::Object::from(*value)).collect()
    }
}
<|endoftext|>


<commit_before>use super::*;
use std::env;
use std::path::Path;
use types::CliArgs;

#[test]
fn run_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn print_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: true,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn list_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: true,
        experimental: false
    });
}

#[test]
fn run_file_and_task() {
    run(CliArgs {
        build_file: "./examples/dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn run_cwd_with_file() {
    let directory = Path::new("./examples");
    assert!(env::set_current_dir(&directory).is_ok());

    run(CliArgs {
        build_file: "./examples/dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: Some("..".to_string()),
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
#[should_panic]
fn run_cwd_task_not_found() {
    let directory = Path::new("./examples");
    assert!(env::set_current_dir(&directory).is_ok());

    run(CliArgs {
        build_file: "./dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: Some("..".to_string()),
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
#[should_panic]
fn run_cli_panic() {
    run_cli();
}

#[test]
#[should_panic]
fn run_for_args_bad_subcommand() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["bad"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_valid() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["cargo", "make", "--makefile", "./examples/dependencies.toml", "-t", "A", "-l", "error"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_log_level_override() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["cargo", "make", "--makefile", "./examples/dependencies.toml", "-t", "A", "-l", "error", "-v"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_set_env() {
    let app = create_cli();

    env::set_var("ENV1_TEST", "EMPTY");
    env::set_var("ENV2_TEST", "EMPTY");
    env::set_var("ENV3_TEST", "EMPTY");

    let matches = app.get_matches_from(vec![
        "cargo",
        "make",
        "--env",
        "ENV1_TEST=TEST1",
        "--env",
        "ENV2_TEST=TEST2",
        "-e",
        "ENV3_TEST=TEST3",
        "--verbose",
        "--disable-check-for-updates",
        "-t",
        "empty",
    ]);

    run_for_args(matches);

    assert_eq!(env::var("ENV1_TEST").unwrap(), "TEST1");
    assert_eq!(env::var("ENV2_TEST").unwrap(), "TEST2");
    assert_eq!(env::var("ENV3_TEST").unwrap(), "TEST3");
}

#[test]
fn run_for_args_print_only() {
    let app = create_cli();

    let matches = app.get_matches_from(vec![
        "cargo",
        "make",
        "--makefile",
        "./examples/dependencies.toml",
        "-t",
        "A",
        "-l",
        "error",
        "--no-workspace",
        "--print-steps",
        "--experimental",
    ]);

    run_for_args(matches);
}
<commit_msg>mac build issues<commit_after>use super::*;
use std::env;
use std::path::Path;
use types::CliArgs;

#[test]
fn run_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn print_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: true,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn list_empty_task() {
    run(CliArgs {
        build_file: "bad.toml".to_string(),
        task: "empty".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: true,
        experimental: false
    });
}

#[test]
fn run_file_and_task() {
    run(CliArgs {
        build_file: "./examples/dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: None,
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
fn run_cwd_with_file() {
    let directory = Path::new("./examples");
    assert!(env::set_current_dir(&directory).is_ok());

    run(CliArgs {
        build_file: "./examples/dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: Some("..".to_string()),
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
#[should_panic]
fn run_cwd_task_not_found() {
    let directory = Path::new("./examples");
    assert!(env::set_current_dir(&directory).is_ok());

    run(CliArgs {
        build_file: "./dependencies.toml".to_string(),
        task: "A".to_string(),
        log_level: "error".to_string(),
        cwd: Some("..".to_string()),
        env: None,
        disable_workspace: false,
        disable_check_for_updates: true,
        print_only: false,
        list_all_steps: false,
        experimental: false
    });
}

#[test]
#[should_panic]
#[cfg(not(target_os = "macos"))]
fn run_cli_panic() {
    run_cli();
}

#[test]
#[should_panic]
fn run_for_args_bad_subcommand() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["bad"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_valid() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["cargo", "make", "--makefile", "./examples/dependencies.toml", "-t", "A", "-l", "error"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_log_level_override() {
    let app = create_cli();

    let matches = app.get_matches_from(vec!["cargo", "make", "--makefile", "./examples/dependencies.toml", "-t", "A", "-l", "error", "-v"]);

    run_for_args(matches);
}

#[test]
fn run_for_args_set_env() {
    let app = create_cli();

    env::set_var("ENV1_TEST", "EMPTY");
    env::set_var("ENV2_TEST", "EMPTY");
    env::set_var("ENV3_TEST", "EMPTY");

    let matches = app.get_matches_from(vec![
        "cargo",
        "make",
        "--env",
        "ENV1_TEST=TEST1",
        "--env",
        "ENV2_TEST=TEST2",
        "-e",
        "ENV3_TEST=TEST3",
        "--verbose",
        "--disable-check-for-updates",
        "-t",
        "empty",
    ]);

    run_for_args(matches);

    assert_eq!(env::var("ENV1_TEST").unwrap(), "TEST1");
    assert_eq!(env::var("ENV2_TEST").unwrap(), "TEST2");
    assert_eq!(env::var("ENV3_TEST").unwrap(), "TEST3");
}

#[test]
fn run_for_args_print_only() {
    let app = create_cli();

    let matches = app.get_matches_from(vec![
        "cargo",
        "make",
        "--makefile",
        "./examples/dependencies.toml",
        "-t",
        "A",
        "-l",
        "error",
        "--no-workspace",
        "--print-steps",
        "--experimental",
    ]);

    run_for_args(matches);
}
<|endoftext|>


<commit_before>//! Semantic Tokens helpers

use std::ops;

use lsp_types::{
    Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens,
    SemanticTokensEdit,
};

macro_rules! define_semantic_token_types {
    ($(($ident:ident, $string:literal)),*$(,)?) => {
        $(pub(crate) const $ident: SemanticTokenType = SemanticTokenType::new($string);)*

        pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
            SemanticTokenType::COMMENT,
            SemanticTokenType::KEYWORD,
            SemanticTokenType::STRING,
            SemanticTokenType::NUMBER,
            SemanticTokenType::REGEXP,
            SemanticTokenType::OPERATOR,
            SemanticTokenType::NAMESPACE,
            SemanticTokenType::TYPE,
            SemanticTokenType::STRUCT,
            SemanticTokenType::CLASS,
            SemanticTokenType::INTERFACE,
            SemanticTokenType::ENUM,
            SemanticTokenType::ENUM_MEMBER,
            SemanticTokenType::TYPE_PARAMETER,
            SemanticTokenType::FUNCTION,
            SemanticTokenType::METHOD,
            SemanticTokenType::PROPERTY,
            SemanticTokenType::MACRO,
            SemanticTokenType::VARIABLE,
            SemanticTokenType::PARAMETER,
            $($ident),*
        ];
    };
}

define_semantic_token_types![
    (ANGLE, "angle"),
    (ARITHMETIC, "arithmetic"),
    (ATTRIBUTE_BRACKET, "attributeBracket"),
    (BITWISE, "bitwise"),
    (BOOLEAN, "boolean"),
    (BRACE, "brace"),
    (BRACKET, "bracket"),
    (BUILTIN_ATTRIBUTE, "builtinAttribute"),
    (BUILTIN_TYPE, "builtinType"),
    (CHAR, "character"),
    (COLON, "colon"),
    (COMMA, "comma"),
    (COMPARISON, "comparison"),
    (CONST_PARAMETER, "constParameter"),
    // FIXME: to be replaced once lsp-types has the upstream version
    (DECORATOR, "decorator"),
    (DERIVE, "derive"),
    (DERIVE_HELPER, "deriveHelper"),
    (DOT, "dot"),
    (ESCAPE_SEQUENCE, "escapeSequence"),
    (FORMAT_SPECIFIER, "formatSpecifier"),
    (GENERIC, "generic"),
    (LABEL, "label"),
    (LIFETIME, "lifetime"),
    (LOGICAL, "logical"),
    (MACRO_BANG, "macroBang"),
    (PARENTHESIS, "parenthesis"),
    (PUNCTUATION, "punctuation"),
    (SELF_KEYWORD, "selfKeyword"),
    (SELF_TYPE_KEYWORD, "selfTypeKeyword"),
    (SEMICOLON, "semicolon"),
    (TYPE_ALIAS, "typeAlias"),
    (TOOL_MODULE, "toolModule"),
    (UNION, "union"),
    (UNRESOLVED_REFERENCE, "unresolvedReference"),
];

macro_rules! define_semantic_token_modifiers {
    ($(($ident:ident, $string:literal)),*$(,)?) => {
        $(pub(crate) const $ident: SemanticTokenModifier = SemanticTokenModifier::new($string);)*

        pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
            SemanticTokenModifier::DOCUMENTATION,
            SemanticTokenModifier::DECLARATION,
            SemanticTokenModifier::DEFINITION,
            SemanticTokenModifier::STATIC,
            SemanticTokenModifier::ABSTRACT,
            SemanticTokenModifier::DEPRECATED,
            SemanticTokenModifier::READONLY,
            SemanticTokenModifier::DEFAULT_LIBRARY,
            $($ident),*
        ];
    };
}

define_semantic_token_modifiers![
    (ASYNC, "async"),
    (ATTRIBUTE_MODIFIER, "attribute"),
    (CALLABLE, "callable"),
    (CONSTANT, "constant"),
    (CONSUMING, "consuming"),
    (CONTROL_FLOW, "controlFlow"),
    (CRATE_ROOT, "crateRoot"),
    (INJECTED, "injected"),
    (INTRA_DOC_LINK, "intraDocLink"),
    (LIBRARY, "library"),
    (MUTABLE, "mutable"),
    (PUBLIC, "public"),
    (REFERENCE, "reference"),
    (TRAIT_MODIFIER, "trait"),
    (UNSAFE, "unsafe"),
];

#[derive(Default)]
pub(crate) struct ModifierSet(pub(crate) u32);

impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet {
    fn bitor_assign(&mut self, rhs: SemanticTokenModifier) {
        let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap();
        self.0 |= 1 << idx;
    }
}

/// Tokens are encoded relative to each other.
///
/// This is a direct port of <https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45>
pub(crate) struct SemanticTokensBuilder {
    id: String,
    prev_line: u32,
    prev_char: u32,
    data: Vec<SemanticToken>,
}

impl SemanticTokensBuilder {
    pub(crate) fn new(id: String) -> Self {
        SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() }
    }

    /// Push a new token onto the builder
    pub(crate) fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
        let mut push_line = range.start.line as u32;
        let mut push_char = range.start.character as u32;

        if !self.data.is_empty() {
            push_line -= self.prev_line;
            if push_line == 0 {
                push_char -= self.prev_char;
            }
        }

        // A token cannot be multiline
        let token_len = range.end.character - range.start.character;

        let token = SemanticToken {
            delta_line: push_line,
            delta_start: push_char,
            length: token_len as u32,
            token_type: token_index,
            token_modifiers_bitset: modifier_bitset,
        };

        self.data.push(token);

        self.prev_line = range.start.line as u32;
        self.prev_char = range.start.character as u32;
    }

    pub(crate) fn build(self) -> SemanticTokens {
        SemanticTokens { result_id: Some(self.id), data: self.data }
    }
}

pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> {
    let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count();

    let (_, old) = old.split_at(offset);
    let (_, new) = new.split_at(offset);

    let offset_from_end =
        new.iter().rev().zip(old.iter().rev()).take_while(|&(n, p)| n == p).count();

    let (old, _) = old.split_at(old.len() - offset_from_end);
    let (new, _) = new.split_at(new.len() - offset_from_end);

    if old.is_empty() && new.is_empty() {
        vec![]
    } else {
        // The lsp data field is actually a byte-diff but we
        // travel in tokens so `start` and `delete_count` are in multiples of the
        // serialized size of `SemanticToken`.
        vec![SemanticTokensEdit {
            start: 5 * offset as u32,
            delete_count: 5 * old.len() as u32,
            data: Some(new.into()),
        }]
    }
}

pub(crate) fn type_index(ty: SemanticTokenType) -> u32 {
    SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
}

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

    fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken {
        SemanticToken {
            delta_line: t.0,
            delta_start: t.1,
            length: t.2,
            token_type: t.3,
            token_modifiers_bitset: t.4,
        }
    }

    #[test]
    fn test_diff_insert_at_end() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 10,
                delete_count: 0,
                data: Some(vec![from((11, 12, 13, 14, 15))])
            }
        );
    }

    #[test]
    fn test_diff_insert_at_beginning() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 0,
                delete_count: 0,
                data: Some(vec![from((11, 12, 13, 14, 15))])
            }
        );
    }

    #[test]
    fn test_diff_insert_in_middle() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [
            from((1, 2, 3, 4, 5)),
            from((10, 20, 30, 40, 50)),
            from((60, 70, 80, 90, 100)),
            from((6, 7, 8, 9, 10)),
        ];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 5,
                delete_count: 0,
                data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))])
            }
        );
    }

    #[test]
    fn test_diff_remove_from_end() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 10, delete_count: 5, data: Some(vec![]) });
    }

    #[test]
    fn test_diff_remove_from_beginning() {
        let before = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 0, delete_count: 5, data: Some(vec![]) });
    }

    #[test]
    fn test_diff_remove_from_middle() {
        let before = [
            from((1, 2, 3, 4, 5)),
            from((10, 20, 30, 40, 50)),
            from((60, 70, 80, 90, 100)),
            from((6, 7, 8, 9, 10)),
        ];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 5, delete_count: 10, data: Some(vec![]) });
    }
}
<commit_msg>Remove unused default semantic modifiers<commit_after>//! Semantic Tokens helpers

use std::ops;

use lsp_types::{
    Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens,
    SemanticTokensEdit,
};

macro_rules! define_semantic_token_types {
    ($(($ident:ident, $string:literal)),*$(,)?) => {
        $(pub(crate) const $ident: SemanticTokenType = SemanticTokenType::new($string);)*

        pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
            SemanticTokenType::COMMENT,
            SemanticTokenType::KEYWORD,
            SemanticTokenType::STRING,
            SemanticTokenType::NUMBER,
            SemanticTokenType::REGEXP,
            SemanticTokenType::OPERATOR,
            SemanticTokenType::NAMESPACE,
            SemanticTokenType::TYPE,
            SemanticTokenType::STRUCT,
            SemanticTokenType::CLASS,
            SemanticTokenType::INTERFACE,
            SemanticTokenType::ENUM,
            SemanticTokenType::ENUM_MEMBER,
            SemanticTokenType::TYPE_PARAMETER,
            SemanticTokenType::FUNCTION,
            SemanticTokenType::METHOD,
            SemanticTokenType::PROPERTY,
            SemanticTokenType::MACRO,
            SemanticTokenType::VARIABLE,
            SemanticTokenType::PARAMETER,
            $($ident),*
        ];
    };
}

define_semantic_token_types![
    (ANGLE, "angle"),
    (ARITHMETIC, "arithmetic"),
    (ATTRIBUTE_BRACKET, "attributeBracket"),
    (BITWISE, "bitwise"),
    (BOOLEAN, "boolean"),
    (BRACE, "brace"),
    (BRACKET, "bracket"),
    (BUILTIN_ATTRIBUTE, "builtinAttribute"),
    (BUILTIN_TYPE, "builtinType"),
    (CHAR, "character"),
    (COLON, "colon"),
    (COMMA, "comma"),
    (COMPARISON, "comparison"),
    (CONST_PARAMETER, "constParameter"),
    // FIXME: to be replaced once lsp-types has the upstream version
    (DECORATOR, "decorator"),
    (DERIVE, "derive"),
    (DERIVE_HELPER, "deriveHelper"),
    (DOT, "dot"),
    (ESCAPE_SEQUENCE, "escapeSequence"),
    (FORMAT_SPECIFIER, "formatSpecifier"),
    (GENERIC, "generic"),
    (LABEL, "label"),
    (LIFETIME, "lifetime"),
    (LOGICAL, "logical"),
    (MACRO_BANG, "macroBang"),
    (PARENTHESIS, "parenthesis"),
    (PUNCTUATION, "punctuation"),
    (SELF_KEYWORD, "selfKeyword"),
    (SELF_TYPE_KEYWORD, "selfTypeKeyword"),
    (SEMICOLON, "semicolon"),
    (TYPE_ALIAS, "typeAlias"),
    (TOOL_MODULE, "toolModule"),
    (UNION, "union"),
    (UNRESOLVED_REFERENCE, "unresolvedReference"),
];

macro_rules! define_semantic_token_modifiers {
    ($(($ident:ident, $string:literal)),*$(,)?) => {
        $(pub(crate) const $ident: SemanticTokenModifier = SemanticTokenModifier::new($string);)*

        pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
            SemanticTokenModifier::DOCUMENTATION,
            SemanticTokenModifier::DECLARATION,
            SemanticTokenModifier::STATIC,
            SemanticTokenModifier::DEFAULT_LIBRARY,
            $($ident),*
        ];
    };
}

define_semantic_token_modifiers![
    (ASYNC, "async"),
    (ATTRIBUTE_MODIFIER, "attribute"),
    (CALLABLE, "callable"),
    (CONSTANT, "constant"),
    (CONSUMING, "consuming"),
    (CONTROL_FLOW, "controlFlow"),
    (CRATE_ROOT, "crateRoot"),
    (INJECTED, "injected"),
    (INTRA_DOC_LINK, "intraDocLink"),
    (LIBRARY, "library"),
    (MUTABLE, "mutable"),
    (PUBLIC, "public"),
    (REFERENCE, "reference"),
    (TRAIT_MODIFIER, "trait"),
    (UNSAFE, "unsafe"),
];

#[derive(Default)]
pub(crate) struct ModifierSet(pub(crate) u32);

impl ops::BitOrAssign<SemanticTokenModifier> for ModifierSet {
    fn bitor_assign(&mut self, rhs: SemanticTokenModifier) {
        let idx = SUPPORTED_MODIFIERS.iter().position(|it| it == &rhs).unwrap();
        self.0 |= 1 << idx;
    }
}

/// Tokens are encoded relative to each other.
///
/// This is a direct port of <https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45>
pub(crate) struct SemanticTokensBuilder {
    id: String,
    prev_line: u32,
    prev_char: u32,
    data: Vec<SemanticToken>,
}

impl SemanticTokensBuilder {
    pub(crate) fn new(id: String) -> Self {
        SemanticTokensBuilder { id, prev_line: 0, prev_char: 0, data: Default::default() }
    }

    /// Push a new token onto the builder
    pub(crate) fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
        let mut push_line = range.start.line as u32;
        let mut push_char = range.start.character as u32;

        if !self.data.is_empty() {
            push_line -= self.prev_line;
            if push_line == 0 {
                push_char -= self.prev_char;
            }
        }

        // A token cannot be multiline
        let token_len = range.end.character - range.start.character;

        let token = SemanticToken {
            delta_line: push_line,
            delta_start: push_char,
            length: token_len as u32,
            token_type: token_index,
            token_modifiers_bitset: modifier_bitset,
        };

        self.data.push(token);

        self.prev_line = range.start.line as u32;
        self.prev_char = range.start.character as u32;
    }

    pub(crate) fn build(self) -> SemanticTokens {
        SemanticTokens { result_id: Some(self.id), data: self.data }
    }
}

pub(crate) fn diff_tokens(old: &[SemanticToken], new: &[SemanticToken]) -> Vec<SemanticTokensEdit> {
    let offset = new.iter().zip(old.iter()).take_while(|&(n, p)| n == p).count();

    let (_, old) = old.split_at(offset);
    let (_, new) = new.split_at(offset);

    let offset_from_end =
        new.iter().rev().zip(old.iter().rev()).take_while(|&(n, p)| n == p).count();

    let (old, _) = old.split_at(old.len() - offset_from_end);
    let (new, _) = new.split_at(new.len() - offset_from_end);

    if old.is_empty() && new.is_empty() {
        vec![]
    } else {
        // The lsp data field is actually a byte-diff but we
        // travel in tokens so `start` and `delete_count` are in multiples of the
        // serialized size of `SemanticToken`.
        vec![SemanticTokensEdit {
            start: 5 * offset as u32,
            delete_count: 5 * old.len() as u32,
            data: Some(new.into()),
        }]
    }
}

pub(crate) fn type_index(ty: SemanticTokenType) -> u32 {
    SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
}

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

    fn from(t: (u32, u32, u32, u32, u32)) -> SemanticToken {
        SemanticToken {
            delta_line: t.0,
            delta_start: t.1,
            length: t.2,
            token_type: t.3,
            token_modifiers_bitset: t.4,
        }
    }

    #[test]
    fn test_diff_insert_at_end() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 10,
                delete_count: 0,
                data: Some(vec![from((11, 12, 13, 14, 15))])
            }
        );
    }

    #[test]
    fn test_diff_insert_at_beginning() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 0,
                delete_count: 0,
                data: Some(vec![from((11, 12, 13, 14, 15))])
            }
        );
    }

    #[test]
    fn test_diff_insert_in_middle() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [
            from((1, 2, 3, 4, 5)),
            from((10, 20, 30, 40, 50)),
            from((60, 70, 80, 90, 100)),
            from((6, 7, 8, 9, 10)),
        ];

        let edits = diff_tokens(&before, &after);
        assert_eq!(
            edits[0],
            SemanticTokensEdit {
                start: 5,
                delete_count: 0,
                data: Some(vec![from((10, 20, 30, 40, 50)), from((60, 70, 80, 90, 100))])
            }
        );
    }

    #[test]
    fn test_diff_remove_from_end() {
        let before = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10)), from((11, 12, 13, 14, 15))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 10, delete_count: 5, data: Some(vec![]) });
    }

    #[test]
    fn test_diff_remove_from_beginning() {
        let before = [from((11, 12, 13, 14, 15)), from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 0, delete_count: 5, data: Some(vec![]) });
    }

    #[test]
    fn test_diff_remove_from_middle() {
        let before = [
            from((1, 2, 3, 4, 5)),
            from((10, 20, 30, 40, 50)),
            from((60, 70, 80, 90, 100)),
            from((6, 7, 8, 9, 10)),
        ];
        let after = [from((1, 2, 3, 4, 5)), from((6, 7, 8, 9, 10))];

        let edits = diff_tokens(&before, &after);
        assert_eq!(edits[0], SemanticTokensEdit { start: 5, delete_count: 10, data: Some(vec![]) });
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering::Equal;
use std::collections::HashMap;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input: &str) -> String {
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in input.to_string().lines() {
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
            },
            _ => () // Ignore bad lines
        }
    }
    write_tally(&results)
}

fn write_tally(results: &HashMap<String, TeamResult>) -> String {
    let mut v: Vec<_> = results.iter().map(|(team, r)| {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        (team, games, r, points)
    }).collect();
    // Sort by points, then games played, in reverse order.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.1.cmp(&(b.1)).reverse(),
                  other => other
              });
    let mut lines = vec![format!("{:30} | MP |  W |  D |  L |  P", "Team")];
    lines.extend(v.iter().map(|&(ref team, games, r, points)| {
        format!("{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                team, games, r.wins, r.draws, r.losses, points)
    }));
    lines.join("\n")
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    results.entry(team).or_insert(TeamResult::new()).add_game_result(result);
}
<commit_msg>tournament: Sort by name A-Z, not games played<commit_after>use std::cmp::Ordering::Equal;
use std::collections::HashMap;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input: &str) -> String {
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in input.to_string().lines() {
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
            },
            _ => () // Ignore bad lines
        }
    }
    write_tally(&results)
}

fn write_tally(results: &HashMap<String, TeamResult>) -> String {
    let mut v: Vec<_> = results.iter().map(|(team, r)| {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        (team, games, r, points)
    }).collect();
    // Sort by points descending, then name A-Z.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.0.cmp(&(b.0)),
                  other => other
              });
    let mut lines = vec![format!("{:30} | MP |  W |  D |  L |  P", "Team")];
    lines.extend(v.iter().map(|&(ref team, games, r, points)| {
        format!("{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                team, games, r.wins, r.draws, r.losses, points)
    }));
    lines.join("\n")
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    results.entry(team).or_insert(TeamResult::new()).add_game_result(result);
}
<|endoftext|>


<commit_before>extern crate serialize;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::vec::Vec;
use swarm::SwarmMsg;
use agent::SwarmAgent;
use std::io::net::ip::{SocketAddr, ToSocketAddr};
use std::io::net::udp::UdpSocket;
use std::io::MemWriter;
use std::io::{IoResult, IoError, BufReader};
use bincode::{decode_from, encode};
use bincode::DecoderReader;
use bincode::EncoderWriter;

#[deriving(Clone, Eq, PartialEq, Show, Decodable, Encodable)]
enum IronSwarmRPC<Loc> {
    HRTBT(SwarmAgent<Loc>),
    HRTBTACK(Vec<SwarmAgent<Loc>>),
    JOIN(SwarmAgent<Loc>),
    INFO(Loc, SwarmMsg<Loc>),
    BROADCAST(SwarmMsg<Loc>),
}

pub struct SwarmNetwork<Loc> {
    recv_buf: [u8, ..1024],
    socket: UdpSocket,
    local_agent: SwarmAgent<Loc>,
    neighbors: Vec<SwarmAgent<Loc>>
}

// Public interface of the Swarm Network.
impl<Loc> SwarmNetwork<Loc> {
    pub fn new<A: ToSocketAddr>(loc: Loc, address: A) -> SwarmNetwork<Loc> {
        let mut socket = match UdpSocket::bind(address) {
            Ok(s) => s,
            Err(e) => panic!("Could not bind socket: {}", e)
        };
        let addr = match socket.socket_name() {
            Ok(a) => a,
            Err(e) => panic!("Could not get socket name: {}", e)
        };
        let agent = SwarmAgent::new(loc, addr);

        SwarmNetwork {
            recv_buf: [0u8, ..1024],
            socket: socket,
            local_agent: agent,
            neighbors: Vec::new()
        }
    }

    pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
        self.socket.socket_name()
    }

    pub fn update_location(&mut self, location: Loc) {
        self.local_agent.update_location(location);
    }
}

// Implement receiving of IronSwarmRPC through the UDP socket.
impl<'a,Loc:Decodable<DecoderReader<'a,BufReader<'a>>, IoError>> SwarmNetwork<Loc> {
    pub fn recv_msg(&'a mut self) -> IoResult<IronSwarmRPC<Loc>> {
        match self.socket.recv_from(&mut self.recv_buf) {
            Ok((amt, _)) => {
                let rpc = try!(decode_from(&mut BufReader::new(self.recv_buf.slice_to(amt))));
                Ok(rpc)
            }
            Err(e) => panic!("Could not recv a packet: {}", e)
        }
    }
}

// Implement sending of IronSwarmRPC through the UDP socket.
impl<'a,Loc:Encodable<EncoderWriter<'a,MemWriter>, IoError>+Clone> SwarmNetwork<Loc> {
    fn send_heartbeat(&'a mut self, to_agn: SwarmAgent<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::HRTBT(self.local_agent.clone());
        let encoded = try!(encode(&rpc));
        try!(self.socket.send_to(encoded.as_slice(), to_agn.address()));
        Ok(())
    }
}

#[cfg(test)]
mod test {
    extern crate bincode;

    use agent::{SwarmAgent};
    use artifact::SwarmArtifact;
    use swarm::SwarmMsg;
    use Location;
    use std::io::net::ip::{SocketAddr, Ipv4Addr};
    use std::io::net::udp::UdpSocket;
    use std::io::test::next_test_port;
    use std::io::IoResult;
    use swarm::network::IronSwarmRPC;
    use std::path::BytesContainer;
    use std::vec::Vec;
    use super::SwarmNetwork;

    fn bincode_rpc_tester(rpc: IronSwarmRPC<int>) {
        let orig_rpc = rpc.clone();
        let encoded = bincode::encode(&rpc).ok().unwrap();
        let dec_rpc: IronSwarmRPC<int> =
            bincode::decode(encoded).ok().unwrap();
        assert_eq!(orig_rpc, dec_rpc);
    }

    fn recv_msg_rpc_tester(network: &mut SwarmNetwork<int>,
                           rpc: IronSwarmRPC<int>) -> IoResult<()> {
        let mut socket = try!(UdpSocket::bind(local_socket()));
        let orig_rpc = rpc.clone();
        let encoded = bincode::encode(&rpc).ok().unwrap();
        let net_sock = try!(network.socket_name());
        try!(socket.send_to(encoded.container_as_bytes(), net_sock));

        let dec_rpc = try!(network.recv_msg());
        assert_eq!(orig_rpc, dec_rpc);
        Ok(())
    }

    fn send_hrtbt_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let exp_rpc = IronSwarmRPC::HRTBT(from_network.local_agent.clone());

        try!(from_network.send_heartbeat(to_network.local_agent.clone()));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn construct_artifact() -> SwarmArtifact<int> {
        let loc = 9i;

        SwarmArtifact::new(loc)
    }

    fn construct_agent() -> SwarmAgent<int> {
        SwarmAgent::new(9, local_socket())
    }

    fn construct_swarm_msg() -> SwarmMsg<int> {
        SwarmMsg::new_artifact_msg(construct_agent(), construct_artifact())
    }

    fn local_socket() -> SocketAddr {
        SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: next_test_port() }
    }

    fn construct_swarm_network_with_local_socket() -> SwarmNetwork<int> {
        SwarmNetwork::new(27, local_socket())
    }

    #[test]
    fn bincode_test() {
        let mut ack_vec = Vec::new();
        ack_vec.push(construct_agent());

        bincode_rpc_tester(IronSwarmRPC::HRTBT(construct_agent()));
        bincode_rpc_tester(IronSwarmRPC::HRTBTACK(ack_vec));
        bincode_rpc_tester(IronSwarmRPC::JOIN(construct_agent()));
        bincode_rpc_tester(IronSwarmRPC::INFO(10, construct_swarm_msg()));
        bincode_rpc_tester(IronSwarmRPC::BROADCAST(construct_swarm_msg()));
    }

    #[test]
    fn recv_msg_test() {
        let mut ack_vec = Vec::new();
        ack_vec.push(construct_agent());
        let mut network = construct_swarm_network_with_local_socket();

        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::HRTBT(construct_agent()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::HRTBTACK(ack_vec));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::JOIN(construct_agent()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::INFO(10, construct_swarm_msg()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::BROADCAST(construct_swarm_msg()));
        assert!(res.is_ok());
    }

    #[test]
    fn send_hrtbt_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_hrtbt_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }
}
<commit_msg>Enable sending of all IronSwarmRPC's.<commit_after>extern crate serialize;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::vec::Vec;
use swarm::SwarmMsg;
use agent::SwarmAgent;
use std::io::net::ip::{SocketAddr, ToSocketAddr};
use std::io::net::udp::UdpSocket;
use std::io::MemWriter;
use std::io::{IoResult, IoError, BufReader};
use bincode::{decode_from, encode};
use bincode::DecoderReader;
use bincode::EncoderWriter;

#[deriving(Clone, Eq, PartialEq, Show, Decodable, Encodable)]
enum IronSwarmRPC<Loc> {
    HRTBT(SwarmAgent<Loc>),
    HRTBTACK(Vec<SwarmAgent<Loc>>),
    JOIN(SwarmAgent<Loc>),
    INFO(Loc, SwarmMsg<Loc>),
    BROADCAST(SwarmMsg<Loc>),
}

pub struct SwarmNetwork<Loc> {
    recv_buf: [u8, ..1024],
    socket: UdpSocket,
    local_agent: SwarmAgent<Loc>,
    neighbors: Vec<SwarmAgent<Loc>>
}

// Public interface of the Swarm Network.
impl<Loc> SwarmNetwork<Loc> {
    pub fn new<A: ToSocketAddr>(loc: Loc, address: A) -> SwarmNetwork<Loc> {
        let mut socket = match UdpSocket::bind(address) {
            Ok(s) => s,
            Err(e) => panic!("Could not bind socket: {}", e)
        };
        let addr = match socket.socket_name() {
            Ok(a) => a,
            Err(e) => panic!("Could not get socket name: {}", e)
        };
        let agent = SwarmAgent::new(loc, addr);

        SwarmNetwork {
            recv_buf: [0u8, ..1024],
            socket: socket,
            local_agent: agent,
            neighbors: Vec::new()
        }
    }

    pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
        self.socket.socket_name()
    }

    pub fn update_location(&mut self, location: Loc) {
        self.local_agent.update_location(location);
    }
}

// Implement receiving of IronSwarmRPC through the UDP socket.
impl<'a,Loc:Decodable<DecoderReader<'a,BufReader<'a>>, IoError>> SwarmNetwork<Loc> {
    pub fn recv_msg(&'a mut self) -> IoResult<IronSwarmRPC<Loc>> {
        match self.socket.recv_from(&mut self.recv_buf) {
            Ok((amt, _)) => {
                let rpc = try!(decode_from(&mut BufReader::new(self.recv_buf.slice_to(amt))));
                Ok(rpc)
            }
            Err(e) => panic!("Could not recv a packet: {}", e)
        }
    }
}

// Implement sending of IronSwarmRPC through the UDP socket.
impl<'a,Loc:Encodable<EncoderWriter<'a,MemWriter>, IoError>+Clone> SwarmNetwork<Loc> {
    fn send_rpc(&'a mut self, rpc: IronSwarmRPC<Loc>, to_agn: SwarmAgent<Loc>) -> IoResult<()> {
        let encoded = try!(encode(&rpc));
        try!(self.socket.send_to(encoded.as_slice(), to_agn.address()));
        Ok(())
    }

    fn send_heartbeat(&'a mut self, to_agn: SwarmAgent<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::HRTBT(self.local_agent.clone());
        self.send_rpc(rpc, to_agn)
    }

    fn send_heartbeat_ack(&'a mut self, to_agn: SwarmAgent<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::HRTBTACK(self.neighbors.clone());
        self.send_rpc(rpc, to_agn)
    }

    fn send_join(&'a mut self, to_agn: SwarmAgent<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::JOIN(self.local_agent.clone());
        self.send_rpc(rpc, to_agn)
    }

    fn send_info(&'a mut self, to_agn: SwarmAgent<Loc>, loc: Loc, msg: SwarmMsg<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::INFO(loc, msg);
        self.send_rpc(rpc, to_agn)
    }

    fn send_broadcast(&'a mut self, to_agn: SwarmAgent<Loc>, msg: SwarmMsg<Loc>) -> IoResult<()> {
        let rpc = IronSwarmRPC::BROADCAST(msg);
        self.send_rpc(rpc, to_agn)
    }
}

#[cfg(test)]
mod test {
    extern crate bincode;

    use agent::{SwarmAgent};
    use artifact::SwarmArtifact;
    use swarm::SwarmMsg;
    use Location;
    use std::io::net::ip::{SocketAddr, Ipv4Addr};
    use std::io::net::udp::UdpSocket;
    use std::io::test::next_test_port;
    use std::io::IoResult;
    use swarm::network::IronSwarmRPC;
    use std::path::BytesContainer;
    use std::vec::Vec;
    use super::SwarmNetwork;

    fn bincode_rpc_tester(rpc: IronSwarmRPC<int>) {
        let orig_rpc = rpc.clone();
        let encoded = bincode::encode(&rpc).ok().unwrap();
        let dec_rpc: IronSwarmRPC<int> =
            bincode::decode(encoded).ok().unwrap();
        assert_eq!(orig_rpc, dec_rpc);
    }

    fn recv_msg_rpc_tester(network: &mut SwarmNetwork<int>,
                           rpc: IronSwarmRPC<int>) -> IoResult<()> {
        let mut socket = try!(UdpSocket::bind(local_socket()));
        let orig_rpc = rpc.clone();
        let encoded = bincode::encode(&rpc).ok().unwrap();
        let net_sock = try!(network.socket_name());
        try!(socket.send_to(encoded.container_as_bytes(), net_sock));

        let dec_rpc = try!(network.recv_msg());
        assert_eq!(orig_rpc, dec_rpc);
        Ok(())
    }

    fn send_hrtbt_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let exp_rpc = IronSwarmRPC::HRTBT(from_network.local_agent.clone());

        try!(from_network.send_heartbeat(to_network.local_agent.clone()));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn send_hrtbtack_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let exp_rpc = IronSwarmRPC::HRTBTACK(from_network.neighbors.clone());

        try!(from_network.send_heartbeat_ack(to_network.local_agent.clone()));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn send_join_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let exp_rpc = IronSwarmRPC::JOIN(from_network.local_agent.clone());

        try!(from_network.send_join(to_network.local_agent.clone()));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn send_info_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let msg = construct_swarm_msg();
        let exp_rpc = IronSwarmRPC::INFO(27, msg.clone());

        try!(from_network.send_info(to_network.local_agent.clone(), 27, msg));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn send_broadcast_tester(from_network: &mut SwarmNetwork<int>,
                           to_network: &mut SwarmNetwork<int>) -> IoResult<()> {
        let msg = construct_swarm_msg();
        let exp_rpc = IronSwarmRPC::BROADCAST(msg.clone());

        try!(from_network.send_broadcast(to_network.local_agent.clone(), msg));
        let recv_rpc = try!(to_network.recv_msg());

        assert_eq!(exp_rpc, recv_rpc);
        Ok(())
    }

    fn construct_artifact() -> SwarmArtifact<int> {
        let loc = 9i;

        SwarmArtifact::new(loc)
    }

    fn construct_agent() -> SwarmAgent<int> {
        SwarmAgent::new(9, local_socket())
    }

    fn construct_swarm_msg() -> SwarmMsg<int> {
        SwarmMsg::new_artifact_msg(construct_agent(), construct_artifact())
    }

    fn local_socket() -> SocketAddr {
        SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: next_test_port() }
    }

    fn construct_swarm_network_with_local_socket() -> SwarmNetwork<int> {
        SwarmNetwork::new(27, local_socket())
    }

    #[test]
    fn bincode_test() {
        let mut ack_vec = Vec::new();
        ack_vec.push(construct_agent());

        bincode_rpc_tester(IronSwarmRPC::HRTBT(construct_agent()));
        bincode_rpc_tester(IronSwarmRPC::HRTBTACK(ack_vec));
        bincode_rpc_tester(IronSwarmRPC::JOIN(construct_agent()));
        bincode_rpc_tester(IronSwarmRPC::INFO(10, construct_swarm_msg()));
        bincode_rpc_tester(IronSwarmRPC::BROADCAST(construct_swarm_msg()));
    }

    #[test]
    fn recv_msg_test() {
        let mut ack_vec = Vec::new();
        ack_vec.push(construct_agent());
        let mut network = construct_swarm_network_with_local_socket();

        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::HRTBT(construct_agent()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::HRTBTACK(ack_vec));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::JOIN(construct_agent()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::INFO(10, construct_swarm_msg()));
        assert!(res.is_ok());
        let res = recv_msg_rpc_tester(&mut network, IronSwarmRPC::BROADCAST(construct_swarm_msg()));
        assert!(res.is_ok());
    }

    #[test]
    fn send_hrtbt_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_hrtbt_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }

    #[test]
    fn send_hrtbtack_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_hrtbtack_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }

    #[test]
    fn send_join_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_join_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }

    #[test]
    fn send_info_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_info_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }

    #[test]
    fn send_broadcast_test() {
        let mut from_network = construct_swarm_network_with_local_socket();
        let mut to_network = construct_swarm_network_with_local_socket();

        let res = send_broadcast_tester(&mut from_network, &mut to_network);
        assert!(res.is_ok());
    }
}
<|endoftext|>