<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.

use std::net::{UdpSocket,TcpListener};
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 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,27900)) {
        Err(_) => {
            println!("Error creating a UDP socket at {}:27900.",ip);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,29920)) {
        Err(_) => {
            println!("Error listening to TCP at {}:29920.",ip);
            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_new : Vec<String> = Vec::new();
                match File::open(BLACKLIST_FILE) {
                    Ok(file) => {
                        let reader = BufReader::new(&file);
                        for line_possibly in reader.lines() {
                            match line_possibly {
                                Err(_) => break,
                                Ok(line) => {
                                    blacklist_new.push(line);
                                }
                            }
                        }
                    },
                    Err(_) => {}
                };

                let mut blacklist_ref = blacklist_update.lock().unwrap();
                blacklist_ref.clear();

                for b in blacklist_new {
                    blacklist_ref.push(b.clone());
                }
            }
            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.to_string().split(":").next().unwrap().to_string()
                };

                let mut ips = String::new();

                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";
                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((length, source)) => (length,source)
        };
        let client_ip = source.to_string().split(":").next().unwrap().to_string();

        if buffer[0] == 3 || buffer[0] == 8 {
            let blacklist_ref = blacklist_udp.lock().unwrap();
            if blacklist_ref.contains(&client_ip) {
                continue;
            }

            // Heartbeat packet.
            if buffer[0] == 3 {

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

                let packet = HeartbeatPacket::from_buffer(&buffer, length);

                if packet.localport != 0  {
                    let mut found = false;
                    let updatetime = time::now().to_timespec().sec;
                    for i in (0.. servers.len()) {
                        if servers[i].ip == client_ip && servers[i].port == packet.localport {
                            servers[i].last_alive = updatetime;
                            found = true;
                            if packet.statechanged == 2 {
                                // println!("Dropped {}.", servers[i].to_string());
                                servers.remove(i);
                            }
                            break;
                        }
                    }

                    if !found && &packet.gamename == "halor" && game_versions.contains(&packet.gamever) {
                        let serverness = HaloServer { ip:client_ip, port: packet.localport, last_alive: updatetime };
                        // println!("Added {}.", serverness.to_string());
                        (*servers).push(serverness);
                    }
                }
            }

            // Keepalive packet. We need to rely on the origin's port for this, unfortunately.
            else if buffer[0] == 8 {
                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>Use iterator for adding/renewer servers<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.

use std::net::{UdpSocket,TcpListener};
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 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,27900)) {
        Err(_) => {
            println!("Error creating a UDP socket at {}:27900.",ip);
            return;
        },
        Ok(halo_socket) => halo_socket
    };

    let client_socket = match TcpListener::bind((&ip as &str,29920)) {
        Err(_) => {
            println!("Error listening to TCP at {}:29920.",ip);
            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_new : Vec<String> = Vec::new();
                match File::open(BLACKLIST_FILE) {
                    Ok(file) => {
                        let reader = BufReader::new(&file);
                        for line_possibly in reader.lines() {
                            match line_possibly {
                                Err(_) => break,
                                Ok(line) => {
                                    blacklist_new.push(line);
                                }
                            }
                        }
                    },
                    Err(_) => {}
                };

                let mut blacklist_ref = blacklist_update.lock().unwrap();
                blacklist_ref.clear();

                for b in blacklist_new {
                    blacklist_ref.push(b.clone());
                }
            }
            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.to_string().split(":").next().unwrap().to_string()
                };

                let mut ips = String::new();

                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";
                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((length, source)) => (length,source)
        };
        if length == 0 {
            continue;
        }
        let client_ip = source.to_string().split(":").next().unwrap().to_string();

        if buffer[0] == 3 || buffer[0] == 8 {
            let blacklist_ref = blacklist_udp.lock().unwrap();
            if blacklist_ref.contains(&client_ip) {
                continue;
            }

            // Heartbeat packet.
            if buffer[0] == 3 {

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

                let packet = HeartbeatPacket::from_buffer(&buffer, length);

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

            // Keepalive packet. We need to rely on the origin's port for this, unfortunately.
            else if buffer[0] == 8 {
                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>use cocoa::base::{id, nil};
use cocoa::foundation::{NSInteger, NSUInteger};
use core_foundation::base::CFRange;
use objc::runtime::YES;
use std::mem;
use std::ops::{Deref, Range};
use sys::{MTLTexture, MTLTextureType, MTLTextureUsage};
use {FromRaw, FromRawError, PixelFormat, Region, Resource, Size};
#[cfg(target_os = "ios")]
use Buffer;

pub struct Texture(id);

impl Texture {
    pub fn with_pixel_format(format: PixelFormat) -> Result<Self, FromRawError> {
        let raw_tex = unsafe { MTLTexture::newTextureViewWithPixelFormat(nil, format.into()) };
        Self::from_raw(raw_tex)
    }

    pub fn new(format: PixelFormat, tex_type: TextureType, levels: Range<isize>, slices: usize)
               -> Result<Self, FromRawError> {
        let cf_levels = CFRange::init(levels.start as NSInteger,
                                      (levels.end - levels.start) as NSInteger);
        let raw_tex = unsafe {
            MTLTexture::newTextureViewWithPixelFormat_textureType_levels_slices(
                nil, format.into(), tex_type.into(), cf_levels,
                slices as NSUInteger)
        };
        Self::from_raw(raw_tex)
    }

    pub fn replace_region_at_slice(&mut self, region: Region, slice: usize, mipmap_level: usize,
                                   bytes: &AsRef<[u8]>, bytes_per_row: usize,
                                   bytes_per_image: usize) {
        unsafe {
            self.0.replaceRegion_mipmapLevel_slice_withBytes_bytesPerRow_bytesPerImage(
                region.into(), mipmap_level as NSUInteger, slice as NSUInteger,
                bytes.as_ref().as_ptr() as *const _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger);
        }
    }

    pub fn replace_region(&mut self, mipmap_level: usize, region: Region, bytes: &AsRef<[u8]>,
                          bytes_per_row: usize) {
        let bytes = bytes.as_ref();
        if bytes.len() % bytes_per_row != 0 {
            return;
        }
        unsafe {
            self.0.replaceRegion_mipmapLevel_withBytes_bytesPerRow(region.into(),
                                                                   mipmap_level as NSUInteger,
                                                                   bytes.as_ptr() as *const _,
                                                                   bytes_per_row as NSUInteger);
        }
    }

    // TODO(George): Investigate non-allocating APIs, and add predicates in rust code so that
    // panics can be generated
    pub fn get_bytes_at_slice(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize,
                              bytes_per_image: usize, region: Region, mipmap_level: usize,
                              slice: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0.getBytes_bytesPerRow_bytesPerImage_fromRegion_mipmapLevel_slice(
                bytes_storage.as_mut_ptr() as *mut _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger, region.into(), mipmap_level as NSUInteger,
                slice as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn get_bytes(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize, region: Region,
                     mipmap_level: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0
                .getBytes_bytesPerRow_fromRegion_mipmapLevel(bytes_storage.as_mut_ptr() as *mut _,
                                                             bytes_per_row as NSUInteger,
                                                             region.into(),
                                                             mipmap_level as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn texture_type(&self) -> TextureType {
        unsafe { self.0.textureType().into() }
    }

    pub fn pixel_format(&self) -> PixelFormat {
        unsafe { self.0.pixelFormat().into() }
    }

    pub fn width(&self) -> usize {
        unsafe { self.0.width() as usize }
    }

    pub fn height(&self) -> usize {
        unsafe { self.0.height() as usize }
    }

    pub fn depth(&self) -> usize {
        unsafe { self.0.depth() as usize }
    }

    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height(), self.depth())
    }

    pub fn mipmap_level_count(&self) -> usize {
        unsafe { self.0.mipmapLevelCount() as usize }
    }

    pub fn array_length(&self) -> usize {
        unsafe { self.0.arrayLength() as usize }
    }

    pub fn sample_count(&self) -> usize {
        unsafe { self.0.sampleCount() as usize }
    }

    pub fn is_frame_buffer_only(&self) -> bool {
        unsafe { self.0.frameBufferOnly() == YES }
    }

    pub fn root_resource(&self) -> Option<Resource> {
        unsafe { FromRaw::from_raw(self.0.rootResource()).ok() }
    }

    pub fn usage(&self) -> TextureUsage {
        unsafe { self.0.usage().into() }
    }

    pub fn parent_texture(&self) -> Option<Self> {
        unsafe { Self::from_raw(self.0.parentTexture()).ok() }
    }

    pub fn parent_relative_level(&self) -> usize {
        unsafe { self.0.parentRelativeLevel() as usize }
    }

    pub fn parent_relative_slice(&self) -> usize {
        unsafe { self.0.parentRelativeSlice() as usize }
    }
}

#[cfg(target_os = "macos")]
impl Texture {}

#[cfg(target_os = "ios")]
impl Texture {
    pub fn buffer(&self) -> Option<Buffer> {
        unsafe { FromRaw::from_raw(MTLTexture::buffer(self.0)).ok() }
    }

    pub fn buffer_offset(&self) -> usize {
        unsafe { self.0.bufferOffset() as usize }
    }

    pub fn buffer_bytes_per_row(&self) -> usize {
        unsafe { self.0.bufferBytesPerRow() as usize }
    }
}

impl Deref for Texture {
    type Target = Resource;
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(self) }
    }
}

impl_from_into_raw!(Texture, of protocol "MTLTexture");

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureType: MTLTextureType {
        Type1D => MTLTextureType1D,
        Type1DArray => MTLTextureType1DArray,
        Type2D => MTLTextureType2D,
        Type2DArray => MTLTextureType2DArray,
        Type2DMultisample => MTLTextureType2DMultisample,
        TypeCube => MTLTextureTypeCube,
        Type3D => MTLTextureType3D
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureUsage: MTLTextureUsage {
        Unknown => MTLTextureUsageUnknown,
        ShaderRead => MTLTextureUsageShaderRead,
        ShaderWrite => MTLTextureUsageShaderWrite,
        RenderTarget => MTLTextureUsageRenderTarget,
        PixelFormatView => MTLTextureUsagePixelFormatView
    }
}
<commit_msg>Add stub for TextureDescriptor object<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::{NSInteger, NSUInteger};
use core_foundation::base::CFRange;
use objc::runtime::YES;
use std::mem;
use std::ops::{Deref, Range};
use sys::{MTLTexture, MTLTextureType, MTLTextureUsage};
use {FromRaw, FromRawError, PixelFormat, Region, Resource, Size};
#[cfg(target_os = "ios")]
use Buffer;

pub struct Texture(id);

impl Texture {
    pub fn with_pixel_format(format: PixelFormat) -> Result<Self, FromRawError> {
        let raw_tex = unsafe { MTLTexture::newTextureViewWithPixelFormat(nil, format.into()) };
        Self::from_raw(raw_tex)
    }

    pub fn new(format: PixelFormat, tex_type: TextureType, levels: Range<isize>, slices: usize)
               -> Result<Self, FromRawError> {
        let cf_levels = CFRange::init(levels.start as NSInteger,
                                      (levels.end - levels.start) as NSInteger);
        let raw_tex = unsafe {
            MTLTexture::newTextureViewWithPixelFormat_textureType_levels_slices(
                nil, format.into(), tex_type.into(), cf_levels,
                slices as NSUInteger)
        };
        Self::from_raw(raw_tex)
    }

    pub fn replace_region_at_slice(&mut self, region: Region, slice: usize, mipmap_level: usize,
                                   bytes: &AsRef<[u8]>, bytes_per_row: usize,
                                   bytes_per_image: usize) {
        unsafe {
            self.0.replaceRegion_mipmapLevel_slice_withBytes_bytesPerRow_bytesPerImage(
                region.into(), mipmap_level as NSUInteger, slice as NSUInteger,
                bytes.as_ref().as_ptr() as *const _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger);
        }
    }

    pub fn replace_region(&mut self, mipmap_level: usize, region: Region, bytes: &AsRef<[u8]>,
                          bytes_per_row: usize) {
        let bytes = bytes.as_ref();
        if bytes.len() % bytes_per_row != 0 {
            return;
        }
        unsafe {
            self.0.replaceRegion_mipmapLevel_withBytes_bytesPerRow(region.into(),
                                                                   mipmap_level as NSUInteger,
                                                                   bytes.as_ptr() as *const _,
                                                                   bytes_per_row as NSUInteger);
        }
    }

    // TODO(George): Investigate non-allocating APIs, and add predicates in rust code so that
    // panics can be generated
    pub fn get_bytes_at_slice(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize,
                              bytes_per_image: usize, region: Region, mipmap_level: usize,
                              slice: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0.getBytes_bytesPerRow_bytesPerImage_fromRegion_mipmapLevel_slice(
                bytes_storage.as_mut_ptr() as *mut _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger, region.into(), mipmap_level as NSUInteger,
                slice as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn get_bytes(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize, region: Region,
                     mipmap_level: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0
                .getBytes_bytesPerRow_fromRegion_mipmapLevel(bytes_storage.as_mut_ptr() as *mut _,
                                                             bytes_per_row as NSUInteger,
                                                             region.into(),
                                                             mipmap_level as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn texture_type(&self) -> TextureType {
        unsafe { self.0.textureType().into() }
    }

    pub fn pixel_format(&self) -> PixelFormat {
        unsafe { self.0.pixelFormat().into() }
    }

    pub fn width(&self) -> usize {
        unsafe { self.0.width() as usize }
    }

    pub fn height(&self) -> usize {
        unsafe { self.0.height() as usize }
    }

    pub fn depth(&self) -> usize {
        unsafe { self.0.depth() as usize }
    }

    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height(), self.depth())
    }

    pub fn mipmap_level_count(&self) -> usize {
        unsafe { self.0.mipmapLevelCount() as usize }
    }

    pub fn array_length(&self) -> usize {
        unsafe { self.0.arrayLength() as usize }
    }

    pub fn sample_count(&self) -> usize {
        unsafe { self.0.sampleCount() as usize }
    }

    pub fn is_frame_buffer_only(&self) -> bool {
        unsafe { self.0.frameBufferOnly() == YES }
    }

    pub fn root_resource(&self) -> Option<Resource> {
        unsafe { FromRaw::from_raw(self.0.rootResource()).ok() }
    }

    pub fn usage(&self) -> TextureUsage {
        unsafe { self.0.usage().into() }
    }

    pub fn parent_texture(&self) -> Option<Self> {
        unsafe { Self::from_raw(self.0.parentTexture()).ok() }
    }

    pub fn parent_relative_level(&self) -> usize {
        unsafe { self.0.parentRelativeLevel() as usize }
    }

    pub fn parent_relative_slice(&self) -> usize {
        unsafe { self.0.parentRelativeSlice() as usize }
    }
}

#[cfg(target_os = "macos")]
impl Texture {}

#[cfg(target_os = "ios")]
impl Texture {
    pub fn buffer(&self) -> Option<Buffer> {
        unsafe { FromRaw::from_raw(MTLTexture::buffer(self.0)).ok() }
    }

    pub fn buffer_offset(&self) -> usize {
        unsafe { self.0.bufferOffset() as usize }
    }

    pub fn buffer_bytes_per_row(&self) -> usize {
        unsafe { self.0.bufferBytesPerRow() as usize }
    }
}

impl Deref for Texture {
    type Target = Resource;
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(self) }
    }
}

impl_from_into_raw!(Texture, of protocol "MTLTexture");

pub struct TextureDescriptor(id);

impl_from_into_raw!(TextureDescriptor, of class "MTLTextureDescriptor");

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureType: MTLTextureType {
        Type1D => MTLTextureType1D,
        Type1DArray => MTLTextureType1DArray,
        Type2D => MTLTextureType2D,
        Type2DArray => MTLTextureType2DArray,
        Type2DMultisample => MTLTextureType2DMultisample,
        TypeCube => MTLTextureTypeCube,
        Type3D => MTLTextureType3D
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureUsage: MTLTextureUsage {
        Unknown => MTLTextureUsageUnknown,
        ShaderRead => MTLTextureUsageShaderRead,
        ShaderWrite => MTLTextureUsageShaderWrite,
        RenderTarget => MTLTextureUsageRenderTarget,
        PixelFormatView => MTLTextureUsagePixelFormatView
    }
}
<|endoftext|>


<commit_before>use std::cell::Cell;

use sdl2::video::Window;
use sdl2::render::Renderer;
use sdl2::pixels::Color::RGB;
use sdl2::rect::{Point, Rect};

use sdl2::event::Event;
use sdl2::keycode::KeyCode;

use super::{ButtonState};
use gpu::Color;

pub struct Display {
    renderer: Renderer,
    /// Upscaling factor, log2.
    upscale:  uint,
}

impl Display {
    pub fn new(upscale: uint) -> Display {
        ::sdl2::init(::sdl2::INIT_VIDEO);

        let up = 1 << upscale;

        let xres = 160 * up;
        let yres = 144 * up;

        let window = match Window::new("gb-rs",
                                       ::sdl2::video::WindowPos::PosCentered,
                                       ::sdl2::video::WindowPos::PosCentered,
                                       xres, yres, ::sdl2::video::OPENGL) {
            Ok(window) => window,
            Err(err)   => panic!("failed to create SDL2 window: {}", err)
        };

        let renderer =
            match Renderer::from_window(window,
                                        ::sdl2::render::RenderDriverIndex::Auto,
                                        ::sdl2::render::SOFTWARE) {
            Ok(renderer) => renderer,
            Err(err) => panic!("failed to create SDL2 renderer: {}", err)
        };

        Display { renderer: renderer, upscale: upscale }
    }
}

impl super::Display for Display {
    fn clear(&mut self) {
        let _ = self.renderer.set_draw_color(RGB(0xff, 0x00, 0x00));
        let _ = self.renderer.clear();
    }

    fn set_pixel(&mut self, x: u32, y: u32, color: Color) {
        let color = match color {
            Color::Black     => RGB(0x00, 0x00, 0x00),
            Color::DarkGrey  => RGB(0x55, 0x55, 0x55),
            Color::LightGrey => RGB(0xab, 0xab, 0xab),
            Color::White     => RGB(0xff, 0xff, 0xff),
        };

        let _ = self.renderer.set_draw_color(color);

        if self.upscale == 0 {
            let _ = self.renderer.draw_point(Point::new(x as i32, y as i32));
        } else {
            let up = 1 << self.upscale;

            // Translate coordinates
            let x = x as i32 * up;
            let y = y as i32 * up;

            let _ = self.renderer.fill_rect(&Rect::new(x, y, up, up));
        }
    }

    fn flip(&mut self) {
        self.renderer.present();
        self.clear();
    }
}

pub struct Controller {
    buttons: Cell<super::Buttons>,
}

impl Controller {
    pub fn new() -> Controller {
        Controller {
            buttons: Cell::new(super::Buttons::new(ButtonState::Up)),
        }
    }

    /// Update key state. For now keybindings are hardcoded.
    fn update_key(&self, key: KeyCode, state: ButtonState) {
        let mut b = self.buttons.get();

        match key {
            KeyCode::Up        => b.up     = state,
            KeyCode::Down      => b.down   = state,
            KeyCode::Left      => b.left   = state,
            KeyCode::Right     => b.right  = state,
            KeyCode::LAlt      => b.a      = state,
            KeyCode::LCtrl     => b.b      = state,
            KeyCode::Return    => b.start  = state,
            KeyCode::RShift    => b.select = state,
            _                  => (),
        }

        self.buttons.set(b);
    }
}

impl super::Controller for Controller {
    fn update(&self) -> super::Event {
        let mut event = super::Event::None;

        loop {
            match ::sdl2::event::poll_event() {
                Event::None =>
                    break,
                Event::KeyDown(_, _, KeyCode::Escape, _, _, _) =>
                    event = super::Event::PowerOff,
                Event::KeyDown(_, _, key, _, _, _) =>
                    self.update_key(key, ButtonState::Down),
                Event::KeyUp(_, _, key, _, _, _) =>
                    self.update_key(key, ButtonState::Up),
                _ => ()
            }
        }

        event
    }

    fn buttons(&self) -> &Cell<super::Buttons> {
        &self.buttons
    }
}
<commit_msg>Quit emulator on sdl2 Quit Event<commit_after>use std::cell::Cell;

use sdl2::video::Window;
use sdl2::render::Renderer;
use sdl2::pixels::Color::RGB;
use sdl2::rect::{Point, Rect};

use sdl2::event::Event;
use sdl2::keycode::KeyCode;

use super::{ButtonState};
use gpu::Color;

pub struct Display {
    renderer: Renderer,
    /// Upscaling factor, log2.
    upscale:  uint,
}

impl Display {
    pub fn new(upscale: uint) -> Display {
        ::sdl2::init(::sdl2::INIT_VIDEO);

        let up = 1 << upscale;

        let xres = 160 * up;
        let yres = 144 * up;

        let window = match Window::new("gb-rs",
                                       ::sdl2::video::WindowPos::PosCentered,
                                       ::sdl2::video::WindowPos::PosCentered,
                                       xres, yres, ::sdl2::video::OPENGL) {
            Ok(window) => window,
            Err(err)   => panic!("failed to create SDL2 window: {}", err)
        };

        let renderer =
            match Renderer::from_window(window,
                                        ::sdl2::render::RenderDriverIndex::Auto,
                                        ::sdl2::render::SOFTWARE) {
            Ok(renderer) => renderer,
            Err(err) => panic!("failed to create SDL2 renderer: {}", err)
        };

        Display { renderer: renderer, upscale: upscale }
    }
}

impl super::Display for Display {
    fn clear(&mut self) {
        let _ = self.renderer.set_draw_color(RGB(0xff, 0x00, 0x00));
        let _ = self.renderer.clear();
    }

    fn set_pixel(&mut self, x: u32, y: u32, color: Color) {
        let color = match color {
            Color::Black     => RGB(0x00, 0x00, 0x00),
            Color::DarkGrey  => RGB(0x55, 0x55, 0x55),
            Color::LightGrey => RGB(0xab, 0xab, 0xab),
            Color::White     => RGB(0xff, 0xff, 0xff),
        };

        let _ = self.renderer.set_draw_color(color);

        if self.upscale == 0 {
            let _ = self.renderer.draw_point(Point::new(x as i32, y as i32));
        } else {
            let up = 1 << self.upscale;

            // Translate coordinates
            let x = x as i32 * up;
            let y = y as i32 * up;

            let _ = self.renderer.fill_rect(&Rect::new(x, y, up, up));
        }
    }

    fn flip(&mut self) {
        self.renderer.present();
        self.clear();
    }
}

pub struct Controller {
    buttons: Cell<super::Buttons>,
}

impl Controller {
    pub fn new() -> Controller {
        Controller {
            buttons: Cell::new(super::Buttons::new(ButtonState::Up)),
        }
    }

    /// Update key state. For now keybindings are hardcoded.
    fn update_key(&self, key: KeyCode, state: ButtonState) {
        let mut b = self.buttons.get();

        match key {
            KeyCode::Up        => b.up     = state,
            KeyCode::Down      => b.down   = state,
            KeyCode::Left      => b.left   = state,
            KeyCode::Right     => b.right  = state,
            KeyCode::LAlt      => b.a      = state,
            KeyCode::LCtrl     => b.b      = state,
            KeyCode::Return    => b.start  = state,
            KeyCode::RShift    => b.select = state,
            _                  => (),
        }

        self.buttons.set(b);
    }
}

impl super::Controller for Controller {
    fn update(&self) -> super::Event {
        let mut event = super::Event::None;

        loop {
            match ::sdl2::event::poll_event() {
                Event::None =>
                    break,
                Event::KeyDown(_, _, KeyCode::Escape, _, _, _) =>
                    event = super::Event::PowerOff,
                Event::KeyDown(_, _, key, _, _, _) =>
                    self.update_key(key, ButtonState::Down),
                Event::KeyUp(_, _, key, _, _, _) =>
                    self.update_key(key, ButtonState::Up),
                Event::Quit(_) =>
                    event = super::Event::PowerOff,
                _ => ()
            }
        }

        event
    }

    fn buttons(&self) -> &Cell<super::Buttons> {
        &self.buttons
    }
}
<|endoftext|>


<commit_before>use std::ops;

///A 3D Vector with x, y, z coordinates: Vector3
#[derive(Clone, PartialEq, Debug)]
pub struct Vector3 {
    x: f32,
    y: f32,
    z: f32,
}

///A 3D Point with x, y and z coordinates: Point3
#[derive(PartialEq, Debug)]
pub struct Point3 {
    x: f32,
    y: f32,
    z: f32,
}

impl Vector3 {
    ///Instantiates a new vector with to be defined values of x, y, z;
    pub fn new(x: f32, y: f32, z: f32) -> Vector3 {
        Vector3 {x: x, y: y, z: z}
    }

    ///Instantiates a new Vector3 from 2 Point3 (initial position, final position).
    ///The new vector is created as final - initial (Points)
    pub fn diff(origin: Point3, destination: Point3) -> Vector3 {
        Vector3 {x: destination.x - origin.x, y: destination.y - origin.y, z: destination.z - origin.z}
    }

    ///Defines a Vector with UP direction (y=1, x=0, z=0)
    pub fn UP() -> Vector3 {
        Vector3 {x: 0f32, y: 1f32, z: 0f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0, z=0)
    pub fn DOWN() -> Vector3 {
        Vector3 {x: 0f32, y: -1f32, z: 0f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1, z=0)
    pub fn RIGHT() -> Vector3 {
        Vector3 {x: 1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1, z=0)
    pub fn LEFT() -> Vector3 {
        Vector3 {x: -1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with FOWARD direction (y=0, x=0, z=1)
    pub fn FOWARD() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 1f32}
    }

    ///Defines a Vector with BACK direction (y=0, x=0, z=-1)
    pub fn BACK() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: -1f32}
    }

    ///Defines a 3D Vector with x=1, y=1, z=1
    pub fn ONE() -> Vector3 {
        Vector3 {x: 1f32, y: 1f32, z: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0, z=0)
    pub fn ZERO() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 0f32}
    }

    ///Vector magnitude: the square root of the sum of each vector part to the power of 2
    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2) + self.z.powi(2))
    }

    ///Crooss product between two vectors 3.
    pub fn x(self, vec: Vector3) -> Vector3 {
        Vector3 {x: self.y * vec.z - self.z * vec.y,
                y: self.z * vec.x - self.x * vec.z,
                z: self.x * vec.y - self.y * vec.x}
    }
}

impl ops::Add for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '+' trait
    fn add(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

impl ops::Mul<f32> for Vector3 {
    type Output = Vector3;

    ///Implements the scalar multiplication of a Vector3 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector3 {
        Vector3 {x: self.x * value, y: self.y * value, z: self.z * value}
    }
}

impl ops::Mul<Vector3> for Vector3 {
    type Output = f32;

    ///Implements the dot product of 2 Vector3 as '*'.
    fn mul(self, new_vec: Vector3) -> f32 {
        self.x * new_vec.x + self.y * new_vec.y + self.z * new_vec.z
    }
}

impl ops::Sub for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '-' trait
    fn sub(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x - new_vec.x, y: self.y - new_vec.y, z: self.z - new_vec.z}
    }
}

impl Point3 {
    ///Instantiates a new Point3 with x, y and z.
    pub fn new(x: f32, y: f32, z: f32) -> Point3 {
        Point3 {x: x, y: y, z: z}
    }

    ///Creates a new Vector3 relative to position (0, 0, 0)
    pub fn to_vec(self) -> Vector3 {
        Vector3::diff(Point3::origin(), self)
    }

    ///Instantiates a Point3 with (0, 0, 0)
    fn origin() -> Point3 {
        Point3::new(0f32, 0f32, 0f32)
    }
}

impl ops::Add<Vector3> for Point3 {
    type Output = Point3;

    ///Overloads + for Points and Vectors: P + PQ = Q
    fn add(self, new_vec: Vector3) -> Point3 {
        Point3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

fn lin_ind(vec1: Vector3, vec2: Vector3, vec3: Vector3) -> bool {
    let aux_vec1 = vec1.clone();
    let aux_vec2 = vec2.clone();
    let aux_vec3 = vec3.clone();
    vec1 * vec2 == 0f32 && aux_vec1 * vec3 == 0f32 && aux_vec3 * aux_vec2 == 0f32
}

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

    #[test]
    fn creates_vector3_with_parameters() {
        let actual = Vector3::new(1f32, 1f32, 1f32);
        let expected = Vector3 {x: 1f32, y: 1f32, z: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn creates_vector3_up() {
        let actual = Vector3::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32 &&
            actual.z == 0f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector3::RIGHT() + Vector3::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector3::RIGHT() + Vector3::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 0f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector3::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
        assert_eq!(actual.z, 3f32);
    }

    #[test]
    fn sub_right_from_one() {
        let actual = Vector3::ONE() - Vector3::RIGHT();
        assert_eq!(actual.x, 0f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        assert_eq!(vec.magnitude(), 3.7416575f32);
    }

    #[test]
    fn magnitude_of_vector_is_positive() {
        let vec = Vector3 {x: -3f32, y: 4f32, z: 5f32};
        assert!(vec.magnitude() >= 0f32);
    }

    #[test]
    fn dot_product() {
        let vec1 = Vector3 {x: 2f32, y: 1f32, z: 2f32};
        let vec2 = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        let actual = vec1 * vec2;
        let expected = 10f32;
        assert_eq!(actual, expected);
    }

    #[test]
    fn constructs_vector3_from_points3() {
        let vec = Vector3::diff(Point3::new(1f32, -1f32, 2f32),
            Point3::new(2f32, 3f32, 2f32));
        assert_eq!(vec.x, 1f32);
        assert_eq!(vec.y, 4f32);
        assert_eq!(vec.z, 0f32);
    }

    #[test]
    fn creates_vector_from_point3() {
        let point = Point3::new(1f32, 1f32, 1f32);
        let actual = point.to_vec();
        let expected = Vector3::ONE();
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn point_add_vector_result_new_point() {
        let point = Point3::origin();
        let vec = Vector3::ONE();
        let actual = point + vec;
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn cross_product_between_2_vectors() {
        let vec1 = Vector3::new(1f32, 2f32, 3f32);
        let actual = vec1.x(Vector3::new(2f32, 3f32, 4f32));
        let expected = Vector3::new(-1f32, 2f32, -1f32);
        assert_eq!(actual.x, expected.x);
        assert_eq!(actual.y, expected.y);
        assert_eq!(actual.z, expected.z);
    }

    #[test]
    fn veirfies_vectors_linearly_independent() {
        let actual = lin_ind(Vector3::UP(), Vector3::RIGHT(), Vector3::FOWARD());
        assert_eq!(actual, true);
    }

    #[test]
    fn veirfies_vectors_linearly_dependent() {
        let actual = lin_ind(Vector3::UP(), Vector3::ONE(), Vector3::FOWARD());
        assert_eq!(actual, false);
    }
}
<commit_msg>refactored lin ind<commit_after>use std::ops;

///A 3D Vector with x, y, z coordinates: Vector3
#[derive(Clone, PartialEq, Debug)]
pub struct Vector3 {
    x: f32,
    y: f32,
    z: f32,
}

///A 3D Point with x, y and z coordinates: Point3
#[derive(PartialEq, Debug)]
pub struct Point3 {
    x: f32,
    y: f32,
    z: f32,
}

impl Vector3 {
    ///Instantiates a new vector with to be defined values of x, y, z;
    pub fn new(x: f32, y: f32, z: f32) -> Vector3 {
        Vector3 {x: x, y: y, z: z}
    }

    ///Instantiates a new Vector3 from 2 Point3 (initial position, final position).
    ///The new vector is created as final - initial (Points)
    pub fn diff(origin: Point3, destination: Point3) -> Vector3 {
        Vector3 {x: destination.x - origin.x, y: destination.y - origin.y, z: destination.z - origin.z}
    }

    ///Defines a Vector with UP direction (y=1, x=0, z=0)
    pub fn UP() -> Vector3 {
        Vector3 {x: 0f32, y: 1f32, z: 0f32}
    }

    ///Defines a Vector with DOWN direction (y=-1, x=0, z=0)
    pub fn DOWN() -> Vector3 {
        Vector3 {x: 0f32, y: -1f32, z: 0f32}
    }

    ///Defines a Vector with RIGHT direction (y=0, x=1, z=0)
    pub fn RIGHT() -> Vector3 {
        Vector3 {x: 1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with LEFT direction (y=0, x=-1, z=0)
    pub fn LEFT() -> Vector3 {
        Vector3 {x: -1f32, y: 0f32, z: 0f32}
    }

    ///Defines a Vector with FOWARD direction (y=0, x=0, z=1)
    pub fn FOWARD() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 1f32}
    }

    ///Defines a Vector with BACK direction (y=0, x=0, z=-1)
    pub fn BACK() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: -1f32}
    }

    ///Defines a 3D Vector with x=1, y=1, z=1
    pub fn ONE() -> Vector3 {
        Vector3 {x: 1f32, y: 1f32, z: 1f32}
    }

    ///Defines a Modulus ZERO Vector (x=0, y=0, z=0)
    pub fn ZERO() -> Vector3 {
        Vector3 {x: 0f32, y: 0f32, z: 0f32}
    }

    ///Vector magnitude: the square root of the sum of each vector part to the power of 2
    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2) + self.z.powi(2))
    }

    ///Crooss product between two vectors 3.
    pub fn x(self, vec: Vector3) -> Vector3 {
        Vector3 {x: self.y * vec.z - self.z * vec.y,
                y: self.z * vec.x - self.x * vec.z,
                z: self.x * vec.y - self.y * vec.x}
    }
}

impl ops::Add for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '+' trait
    fn add(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

impl ops::Mul<f32> for Vector3 {
    type Output = Vector3;

    ///Implements the scalar multiplication of a Vector3 with a f32. Other numbers should
    ///be passed with 'i as f32'
    fn mul(self, value: f32) -> Vector3 {
        Vector3 {x: self.x * value, y: self.y * value, z: self.z * value}
    }
}

impl ops::Mul<Vector3> for Vector3 {
    type Output = f32;

    ///Implements the dot product of 2 Vector3 as '*'.
    fn mul(self, new_vec: Vector3) -> f32 {
        self.x * new_vec.x + self.y * new_vec.y + self.z * new_vec.z
    }
}

impl ops::Sub for Vector3 {
    type Output = Vector3;

    ///Implements the Vector3 '-' trait
    fn sub(self, new_vec: Vector3) -> Vector3 {
        Vector3 {x: self.x - new_vec.x, y: self.y - new_vec.y, z: self.z - new_vec.z}
    }
}

impl Point3 {
    ///Instantiates a new Point3 with x, y and z.
    pub fn new(x: f32, y: f32, z: f32) -> Point3 {
        Point3 {x: x, y: y, z: z}
    }

    ///Creates a new Vector3 relative to position (0, 0, 0)
    pub fn to_vec(self) -> Vector3 {
        Vector3::diff(Point3::origin(), self)
    }

    ///Instantiates a Point3 with (0, 0, 0)
    fn origin() -> Point3 {
        Point3::new(0f32, 0f32, 0f32)
    }
}

impl ops::Add<Vector3> for Point3 {
    type Output = Point3;

    ///Overloads + for Points and Vectors: P + PQ = Q
    fn add(self, new_vec: Vector3) -> Point3 {
        Point3 {x: self.x + new_vec.x, y: self.y + new_vec.y, z: self.z + new_vec.z}
    }
}

fn lin_ind(vec1: Vector3, vec2: Vector3, vec3: Vector3) -> bool {
    let dot1 = vec1.clone() * vec2.clone();
    let dot2 = vec1 * vec3.clone();
    let dot3 = vec3 * vec2;
    dot1 == 0f32 && dot2 == 0f32 && dot3 == 0f32
}

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

    #[test]
    fn creates_vector3_with_parameters() {
        let actual = Vector3::new(1f32, 1f32, 1f32);
        let expected = Vector3 {x: 1f32, y: 1f32, z: 1f32};
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn creates_vector3_up() {
        let actual = Vector3::UP();
        assert!(actual.x == 0f32 &&
            actual.y == 1f32 &&
            actual.z == 0f32);
    }

    #[test]
    fn adds_right_and_left_vectors() {
         let actual = Vector3::RIGHT() + Vector3::LEFT();
         assert_eq!(actual.x, 0f32);
    }

    #[test]
    fn adds_right_and_up() {
        let actual = Vector3::RIGHT() + Vector3::UP();
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 0f32);
    }

    #[test]
    fn mult_one_by_3() {
        let actual = Vector3::ONE() * 3f32;
        assert_eq!(actual.x, 3f32);
        assert_eq!(actual.y, 3f32);
        assert_eq!(actual.z, 3f32);
    }

    #[test]
    fn sub_right_from_one() {
        let actual = Vector3::ONE() - Vector3::RIGHT();
        assert_eq!(actual.x, 0f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        assert_eq!(vec.magnitude(), 3.7416575f32);
    }

    #[test]
    fn magnitude_of_vector_is_positive() {
        let vec = Vector3 {x: -3f32, y: 4f32, z: 5f32};
        assert!(vec.magnitude() >= 0f32);
    }

    #[test]
    fn dot_product() {
        let vec1 = Vector3 {x: 2f32, y: 1f32, z: 2f32};
        let vec2 = Vector3 {x: 1f32, y: 2f32, z: 3f32};
        let actual = vec1 * vec2;
        let expected = 10f32;
        assert_eq!(actual, expected);
    }

    #[test]
    fn constructs_vector3_from_points3() {
        let vec = Vector3::diff(Point3::new(1f32, -1f32, 2f32),
            Point3::new(2f32, 3f32, 2f32));
        assert_eq!(vec.x, 1f32);
        assert_eq!(vec.y, 4f32);
        assert_eq!(vec.z, 0f32);
    }

    #[test]
    fn creates_vector_from_point3() {
        let point = Point3::new(1f32, 1f32, 1f32);
        let actual = point.to_vec();
        let expected = Vector3::ONE();
        assert!(expected.x == actual.x &&
            expected.y == actual.y &&
            expected.z == actual.z);
    }

    #[test]
    fn point_add_vector_result_new_point() {
        let point = Point3::origin();
        let vec = Vector3::ONE();
        let actual = point + vec;
        assert_eq!(actual.x, 1f32);
        assert_eq!(actual.y, 1f32);
        assert_eq!(actual.z, 1f32);
    }

    #[test]
    fn cross_product_between_2_vectors() {
        let vec1 = Vector3::new(1f32, 2f32, 3f32);
        let actual = vec1.x(Vector3::new(2f32, 3f32, 4f32));
        let expected = Vector3::new(-1f32, 2f32, -1f32);
        assert_eq!(actual.x, expected.x);
        assert_eq!(actual.y, expected.y);
        assert_eq!(actual.z, expected.z);
    }

    #[test]
    fn veirfies_vectors_linearly_independent() {
        let actual = lin_ind(Vector3::UP(), Vector3::RIGHT(), Vector3::FOWARD());
        assert_eq!(actual, true);
    }

    #[test]
    fn veirfies_vectors_linearly_dependent() {
        let actual = lin_ind(Vector3::UP(), Vector3::ONE(), Vector3::FOWARD());
        assert_eq!(actual, false);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "yes"]
#![allow(unstable)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: yes (GNU coreutils) 8.13 */

extern crate getopts;
extern crate libc;

use std::io::print;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "yes";

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "invalid options\n{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("yes 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [STRING]... [OPTION]...", program);
        println!("");
        print(getopts::usage("Repeatedly output a line with all specified STRING(s), or 'y'.", &opts).as_slice());
        return 0;
    }
    if matches.opt_present("version") {
        println!("yes 1.0.0");
        return 0;
    }
    let mut string = "y".to_string();
    if !matches.free.is_empty() {
        string = matches.free.connect(" ");
    }

    exec(string.as_slice());

    0
}

pub fn exec(string: &str) {
    loop {
        if !pipe_println!("{}", string) {
            break;
        }
    }
}
<commit_msg>Cleanup `yes`<commit_after>#![crate_name = "yes"]
#![allow(unstable)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: yes (GNU coreutils) 8.13 */

extern crate getopts;
extern crate libc;

use std::io::print;
use std::borrow::IntoCow;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "yes";

pub fn uumain(args: Vec<String>) -> isize {
    let program = &args[0];
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "invalid options\n{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("yes 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [STRING]... [OPTION]...", program);
        println!("");
        print(&getopts::usage("Repeatedly output a line with all specified STRING(s), or 'y'.", &opts)[]);
        return 0;
    }
    if matches.opt_present("version") {
        println!("yes 1.0.0");
        return 0;
    }
    let string = if matches.free.is_empty() {
        "y".into_cow()
    } else {
        matches.free.connect(" ").into_cow()
    };

    exec(&string[]);

    0
}

pub fn exec(string: &str) {
    while pipe_println!("{}", string) { }
}
<|endoftext|>


<commit_before>#![crate_name = "nucleotide-count_test"]

use std::collections::HashMap;

mod dna;

fn check_dna(s: &str, pairs: &[(char, uint)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<char, uint> = dna::nucleotide_counts(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.pop(&k).unwrap()), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&char,&uint)>>(), vec!());
}

#[test]
#[ignore]
fn test_count_empty() {
    assert_eq!(dna::count('A', ""), 0);
}

#[test]
#[ignore]
fn test_count_repetitive_cytidine() {
    assert_eq!(dna::count('C', "CCCCC"), 5);
}

#[test]
#[ignore]
fn test_count_only_thymidine() {
    assert_eq!(dna::count('T', "GGGGGTAACCCGG"), 1);
}

#[test]
#[ignore]
fn test_nucleotide_count_empty() {
    check_dna(
        "",
        [('A', 0), ('T', 0), ('C', 0), ('G', 0)]);
}

#[test]
#[ignore]
fn test_nucleotide_count_only_guanosine() {
    check_dna(
        "GGGGGGGG",
        [('A', 0), ('T', 0), ('C', 0), ('G', 8)]);
}

#[test]
#[ignore]
fn test_nucleotide_count_counts_all() {
    check_dna(
        "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAA\
         GAGTGTCTGATAGCAGC",
        [('A', 20), ('T', 21), ('C', 12), ('G', 17)]);
}
<commit_msg>Adapt to recent nightly rust<commit_after>#![crate_name = "nucleotide-count_test"]
#![crate_type = "lib"]

use std::collections::HashMap;

mod dna;

fn check_dna(s: &str, pairs: &[(char, uint)]) {
    // The reason for the awkward code in here is to ensure that the failure
    // message for assert_eq! is as informative as possible. A simpler
    // solution would simply check the length of the map, and then
    // check for the presence and value of each key in the given pairs vector.
    let mut m: HashMap<char, uint> = dna::nucleotide_counts(s);
    for &(k, v) in pairs.iter() {
        assert_eq!((k, m.pop(&k).unwrap()), (k, v));
    }
    // may fail with a message that clearly shows all extra pairs in the map
    assert_eq!(m.iter().collect::<Vec<(&char,&uint)>>(), vec!());
}

#[test]
#[ignore]
fn test_count_empty() {
    assert_eq!(dna::count('A', ""), 0);
}

#[test]
#[ignore]
fn test_count_repetitive_cytidine() {
    assert_eq!(dna::count('C', "CCCCC"), 5);
}

#[test]
#[ignore]
fn test_count_only_thymidine() {
    assert_eq!(dna::count('T', "GGGGGTAACCCGG"), 1);
}

#[test]
#[ignore]
fn test_nucleotide_count_empty() {
    check_dna(
        "",
        [('A', 0), ('T', 0), ('C', 0), ('G', 0)]);
}

#[test]
#[ignore]
fn test_nucleotide_count_only_guanosine() {
    check_dna(
        "GGGGGGGG",
        [('A', 0), ('T', 0), ('C', 0), ('G', 8)]);
}

#[test]
#[ignore]
fn test_nucleotide_count_counts_all() {
    check_dna(
        "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAA\
         GAGTGTCTGATAGCAGC",
        [('A', 20), ('T', 21), ('C', 12), ('G', 17)]);
}
<|endoftext|>


<commit_before>use racer::Coordinate;
use racer_testutils::*;

#[test]
fn complets_static_methods_for_aliased_struct() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
            impl St {
                pub fn new() -> Self {
                    St { mem1: "a".to_owned(), mem2: 5 }
                }
            }
        }
        fn main() {
            use mymod::St as S;
            let s = S::ne~
        }
    "#;
    assert_eq!(get_only_completion(src, None).matchstr, "new");
}

#[test]
fn completes_names_for_aliased_module() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
            impl St {
                pub fn new() -> Self {
                    St { mem1: "a".to_owned(), mem2: 5 }
                }
            }
        }
        fn main() {
            use mymod as m;
            let s = m::St::ne~
        }
    "#;
    assert_eq!(get_only_completion(src, None).matchstr, "new");
}

#[test]
fn finds_definition_of_use_as() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
        }
        fn main() {
            use mymod::St as S;
            let s = S~::new();
        }
    "#;
    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "S");
    assert_eq!(got.coords.unwrap(), Coordinate::new(9, 29));
}

#[test]
fn finds_definition_of_use_self_as() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
        }
        fn main() {
            use mymod::{self as m, St};
            let s = m~
        }
    "#;
    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "m");
    assert_eq!(got.coords.unwrap(), Coordinate::new(9, 32));
}

// moved from system.rs
#[test]
fn follows_use_as() {
    let src2 = "
    pub fn myfn() {}
    pub fn foo() {}
    ";
    let src = "
    use src2::myfn as myfoofn;
    mod src2;
    fn main() {
        my~foofn();
    }
    ";

    let dir = TmpDir::new();
    let _src2 = dir.write_file("src2.rs", src2);
    let got = get_definition(src, Some(dir));
    assert_eq!(got.matchstr, "myfoofn");
    assert_eq!(got.contextstr, "src2::myfn as myfoofn");
}

// moved from system.rs
/// Verifies fix for https://github.com/racer-rust/racer/issues/753
#[test]
fn follows_use_as_in_braces() {
    let src = "
        mod m {
        pub struct Wrapper {
            pub x: i32,
        }

        pub struct Second {
            pub y: i32,
        }
    }

    fn main() {
        use m::{Wrapper as Wpr, Second};
        let _ = W~pr { x: 1 };
    }
    ";

    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "Wpr");
    assert_eq!(got.contextstr, "Wrapper as Wpr");
}

// moved from system.rs
#[test]
fn completes_for_type_alias() {
    let src = "
    mod inner {
        pub type Alias = MyType;
        pub struct MyType;
        impl MyType {
            pub fn method(&self) {}
        }
    }

    fn foo() -> inner::Alias {
        inner::MyType
    }

    fn main() {
        foo().~
    }
    ";

    assert_eq!(get_only_completion(src, None).matchstr, "method");
}

// for use_nested_groups
// moved from system.rs
#[test]
fn follows_use_aliased_self() {
    let src = r"
    use std::collections::{self as col, hash_map::*, HashMap};
    fn main() {
        let heap = col::BinaryHeap::ne~w();
    }
    ";

    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "new");
}

#[test]
fn completes_for_alias_with_resolved_generics() {
    let src = "
    type Svec = Vec<String>;
    fn main() {
        let v = Svec::new();
        v[0].capa~
    }
    ";
    assert_eq!(get_only_completion(src, None).matchstr, "capacity");
}

#[test]
fn completes_for_alias_with_type_param() {
    let src = "
    struct MyError;
    impl MyError {
        fn method(&self) {}
    }
    type Result<V> = Result<V, MyError>;
    fn fail() -> Result<V> {
       Err(MyError)
    }
    fn main() {
        if let Err(e) = fail() {
            e.meth~
        }
    }
    ";
    assert_eq!(get_only_completion(src, None).matchstr, "method");
}
<commit_msg>Update alias.rs<commit_after>use racer::Coordinate;
use racer_testutils::*;

#[test]
fn completes_static_methods_for_aliased_struct() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
            impl St {
                pub fn new() -> Self {
                    St { mem1: "a".to_owned(), mem2: 5 }
                }
            }
        }
        fn main() {
            use mymod::St as S;
            let s = S::ne~
        }
    "#;
    assert_eq!(get_only_completion(src, None).matchstr, "new");
}

#[test]
fn completes_names_for_aliased_module() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
            impl St {
                pub fn new() -> Self {
                    St { mem1: "a".to_owned(), mem2: 5 }
                }
            }
        }
        fn main() {
            use mymod as m;
            let s = m::St::ne~
        }
    "#;
    assert_eq!(get_only_completion(src, None).matchstr, "new");
}

#[test]
fn finds_definition_of_use_as() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
        }
        fn main() {
            use mymod::St as S;
            let s = S~::new();
        }
    "#;
    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "S");
    assert_eq!(got.coords.unwrap(), Coordinate::new(9, 29));
}

#[test]
fn finds_definition_of_use_self_as() {
    let src = r#"
        mod mymod {
            pub struct St {
                mem1: String,
                mem2: usize,
            }
        }
        fn main() {
            use mymod::{self as m, St};
            let s = m~
        }
    "#;
    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "m");
    assert_eq!(got.coords.unwrap(), Coordinate::new(9, 32));
}

// moved from system.rs
#[test]
fn follows_use_as() {
    let src2 = "
    pub fn myfn() {}
    pub fn foo() {}
    ";
    let src = "
    use src2::myfn as myfoofn;
    mod src2;
    fn main() {
        my~foofn();
    }
    ";

    let dir = TmpDir::new();
    let _src2 = dir.write_file("src2.rs", src2);
    let got = get_definition(src, Some(dir));
    assert_eq!(got.matchstr, "myfoofn");
    assert_eq!(got.contextstr, "src2::myfn as myfoofn");
}

// moved from system.rs
/// Verifies fix for https://github.com/racer-rust/racer/issues/753
#[test]
fn follows_use_as_in_braces() {
    let src = "
        mod m {
        pub struct Wrapper {
            pub x: i32,
        }

        pub struct Second {
            pub y: i32,
        }
    }

    fn main() {
        use m::{Wrapper as Wpr, Second};
        let _ = W~pr { x: 1 };
    }
    ";

    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "Wpr");
    assert_eq!(got.contextstr, "Wrapper as Wpr");
}

// moved from system.rs
#[test]
fn completes_for_type_alias() {
    let src = "
    mod inner {
        pub type Alias = MyType;
        pub struct MyType;
        impl MyType {
            pub fn method(&self) {}
        }
    }

    fn foo() -> inner::Alias {
        inner::MyType
    }

    fn main() {
        foo().~
    }
    ";

    assert_eq!(get_only_completion(src, None).matchstr, "method");
}

// for use_nested_groups
// moved from system.rs
#[test]
fn follows_use_aliased_self() {
    let src = r"
    use std::collections::{self as col, hash_map::*, HashMap};
    fn main() {
        let heap = col::BinaryHeap::ne~w();
    }
    ";

    let got = get_definition(src, None);
    assert_eq!(got.matchstr, "new");
}

#[test]
fn completes_for_alias_with_resolved_generics() {
    let src = "
    type Svec = Vec<String>;
    fn main() {
        let v = Svec::new();
        v[0].capa~
    }
    ";
    assert_eq!(get_only_completion(src, None).matchstr, "capacity");
}

#[test]
fn completes_for_alias_with_type_param() {
    let src = "
    struct MyError;
    impl MyError {
        fn method(&self) {}
    }
    type Result<V> = Result<V, MyError>;
    fn fail() -> Result<V> {
       Err(MyError)
    }
    fn main() {
        if let Err(e) = fail() {
            e.meth~
        }
    }
    ";
    assert_eq!(get_only_completion(src, None).matchstr, "method");
}
<|endoftext|>


<commit_before>use crate::protobuf_ident::ProtobufIdent;
use crate::ProtobufRelativePath;
use std::fmt;

#[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub struct ProtobufAbsolutePath {
    pub path: String,
}

impl ProtobufAbsolutePath {
    pub fn root() -> ProtobufAbsolutePath {
        ProtobufAbsolutePath::new(String::new())
    }

    /** If given name is an fully quialified protobuf name. */
    pub fn is_abs(path: &str) -> bool {
        path.is_empty() || path.starts_with(".")
    }

    pub fn new(path: String) -> ProtobufAbsolutePath {
        assert!(ProtobufAbsolutePath::is_abs(&path), path);
        assert!(!path.ends_with("."), path);
        ProtobufAbsolutePath { path }
    }

    pub fn is_empty(&self) -> bool {
        self.path.is_empty()
    }

    pub fn from_package_path(path: Option<&str>) -> ProtobufAbsolutePath {
        match path {
            None => ProtobufAbsolutePath::root(),
            Some(path) => ProtobufAbsolutePath::from_path_without_dot(path),
        }
    }

    pub fn from_path_without_dot(path: &str) -> ProtobufAbsolutePath {
        assert!(!path.is_empty());
        assert!(!path.starts_with("."));
        assert!(!path.ends_with("."));
        ProtobufAbsolutePath::new(format!(".{}", path))
    }

    pub fn from_path_maybe_dot(path: &str) -> ProtobufAbsolutePath {
        if path.starts_with(".") {
            ProtobufAbsolutePath::new(path.to_owned())
        } else {
            ProtobufAbsolutePath::from_path_without_dot(path)
        }
    }

    pub fn push_simple(&mut self, simple: ProtobufIdent) {
        self.path.push('.');
        self.path.push_str(simple.get());
    }

    pub fn push_relative(&mut self, relative: &ProtobufRelativePath) {
        if !relative.is_empty() {
            self.path.push('.');
            self.path.push_str(&relative.path);
        }
    }

    pub fn remove_prefix(&self, prefix: &ProtobufAbsolutePath) -> Option<ProtobufRelativePath> {
        if self.path.starts_with(&prefix.path) {
            let rem = &self.path[prefix.path.len()..];
            if rem.is_empty() {
                return Some(ProtobufRelativePath::empty());
            }
            if rem.starts_with('.') {
                return Some(ProtobufRelativePath::new(rem[1..].to_owned()));
            }
        }
        None
    }

    fn parent(&self) -> Option<ProtobufAbsolutePath> {
        match self.path.rfind('.') {
            Some(pos) => Some(ProtobufAbsolutePath::new(self.path[..pos].to_owned())),
            None => {
                if self.path.is_empty() {
                    None
                } else {
                    Some(ProtobufAbsolutePath::root())
                }
            }
        }
    }

    pub fn self_and_parents(&self) -> Vec<ProtobufAbsolutePath> {
        let mut tmp = self.clone();

        let mut r = Vec::new();

        r.push(self.clone());

        while let Some(parent) = tmp.parent() {
            r.push(parent.clone());
            tmp = parent;
        }

        r
    }
}

impl From<&'_ str> for ProtobufAbsolutePath {
    fn from(s: &str) -> Self {
        ProtobufAbsolutePath::new(s.to_owned())
    }
}

impl From<String> for ProtobufAbsolutePath {
    fn from(s: String) -> Self {
        ProtobufAbsolutePath::new(s)
    }
}

impl fmt::Display for ProtobufAbsolutePath {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.path, f)
    }
}

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

    #[test]
    fn absolute_path_push_simple() {
        let mut foo = ProtobufAbsolutePath::new(".foo".to_owned());
        foo.push_simple(ProtobufIdent::from("bar"));
        assert_eq!(ProtobufAbsolutePath::new(".foo.bar".to_owned()), foo);

        let mut foo = ProtobufAbsolutePath::root();
        foo.push_simple(ProtobufIdent::from("bar"));
        assert_eq!(ProtobufAbsolutePath::new(".bar".to_owned()), foo);
    }

    #[test]
    fn absolute_path_remove_prefix() {
        assert_eq!(
            Some(ProtobufRelativePath::empty()),
            ProtobufAbsolutePath::new(".foo".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
        );
        assert_eq!(
            Some(ProtobufRelativePath::new("bar".to_owned())),
            ProtobufAbsolutePath::new(".foo.bar".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
        );
        assert_eq!(
            Some(ProtobufRelativePath::new("baz.qux".to_owned())),
            ProtobufAbsolutePath::new(".foo.bar.baz.qux".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
        );
        assert_eq!(
            None,
            ProtobufAbsolutePath::new(".foo.barbaz".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
        );
    }

    #[test]
    fn self_and_parents() {
        assert_eq!(
            vec![
                ProtobufAbsolutePath::new(".ab.cde.fghi".to_owned()),
                ProtobufAbsolutePath::new(".ab.cde".to_owned()),
                ProtobufAbsolutePath::new(".ab".to_owned()),
                ProtobufAbsolutePath::root(),
            ],
            ProtobufAbsolutePath::new(".ab.cde.fghi".to_owned()).self_and_parents()
        );
    }
}
<commit_msg>Use proper comments<commit_after>use crate::protobuf_ident::ProtobufIdent;
use crate::ProtobufRelativePath;
use std::fmt;

#[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub struct ProtobufAbsolutePath {
    pub path: String,
}

impl ProtobufAbsolutePath {
    pub fn root() -> ProtobufAbsolutePath {
        ProtobufAbsolutePath::new(String::new())
    }

    /// If given name is an fully quialified protobuf name.
    pub fn is_abs(path: &str) -> bool {
        path.is_empty() || path.starts_with(".")
    }

    pub fn new(path: String) -> ProtobufAbsolutePath {
        assert!(ProtobufAbsolutePath::is_abs(&path), path);
        assert!(!path.ends_with("."), path);
        ProtobufAbsolutePath { path }
    }

    pub fn is_empty(&self) -> bool {
        self.path.is_empty()
    }

    pub fn from_package_path(path: Option<&str>) -> ProtobufAbsolutePath {
        match path {
            None => ProtobufAbsolutePath::root(),
            Some(path) => ProtobufAbsolutePath::from_path_without_dot(path),
        }
    }

    pub fn from_path_without_dot(path: &str) -> ProtobufAbsolutePath {
        assert!(!path.is_empty());
        assert!(!path.starts_with("."));
        assert!(!path.ends_with("."));
        ProtobufAbsolutePath::new(format!(".{}", path))
    }

    pub fn from_path_maybe_dot(path: &str) -> ProtobufAbsolutePath {
        if path.starts_with(".") {
            ProtobufAbsolutePath::new(path.to_owned())
        } else {
            ProtobufAbsolutePath::from_path_without_dot(path)
        }
    }

    pub fn push_simple(&mut self, simple: ProtobufIdent) {
        self.path.push('.');
        self.path.push_str(simple.get());
    }

    pub fn push_relative(&mut self, relative: &ProtobufRelativePath) {
        if !relative.is_empty() {
            self.path.push('.');
            self.path.push_str(&relative.path);
        }
    }

    pub fn remove_prefix(&self, prefix: &ProtobufAbsolutePath) -> Option<ProtobufRelativePath> {
        if self.path.starts_with(&prefix.path) {
            let rem = &self.path[prefix.path.len()..];
            if rem.is_empty() {
                return Some(ProtobufRelativePath::empty());
            }
            if rem.starts_with('.') {
                return Some(ProtobufRelativePath::new(rem[1..].to_owned()));
            }
        }
        None
    }

    fn parent(&self) -> Option<ProtobufAbsolutePath> {
        match self.path.rfind('.') {
            Some(pos) => Some(ProtobufAbsolutePath::new(self.path[..pos].to_owned())),
            None => {
                if self.path.is_empty() {
                    None
                } else {
                    Some(ProtobufAbsolutePath::root())
                }
            }
        }
    }

    pub fn self_and_parents(&self) -> Vec<ProtobufAbsolutePath> {
        let mut tmp = self.clone();

        let mut r = Vec::new();

        r.push(self.clone());

        while let Some(parent) = tmp.parent() {
            r.push(parent.clone());
            tmp = parent;
        }

        r
    }
}

impl From<&'_ str> for ProtobufAbsolutePath {
    fn from(s: &str) -> Self {
        ProtobufAbsolutePath::new(s.to_owned())
    }
}

impl From<String> for ProtobufAbsolutePath {
    fn from(s: String) -> Self {
        ProtobufAbsolutePath::new(s)
    }
}

impl fmt::Display for ProtobufAbsolutePath {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.path, f)
    }
}

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

    #[test]
    fn absolute_path_push_simple() {
        let mut foo = ProtobufAbsolutePath::new(".foo".to_owned());
        foo.push_simple(ProtobufIdent::from("bar"));
        assert_eq!(ProtobufAbsolutePath::new(".foo.bar".to_owned()), foo);

        let mut foo = ProtobufAbsolutePath::root();
        foo.push_simple(ProtobufIdent::from("bar"));
        assert_eq!(ProtobufAbsolutePath::new(".bar".to_owned()), foo);
    }

    #[test]
    fn absolute_path_remove_prefix() {
        assert_eq!(
            Some(ProtobufRelativePath::empty()),
            ProtobufAbsolutePath::new(".foo".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
        );
        assert_eq!(
            Some(ProtobufRelativePath::new("bar".to_owned())),
            ProtobufAbsolutePath::new(".foo.bar".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
        );
        assert_eq!(
            Some(ProtobufRelativePath::new("baz.qux".to_owned())),
            ProtobufAbsolutePath::new(".foo.bar.baz.qux".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
        );
        assert_eq!(
            None,
            ProtobufAbsolutePath::new(".foo.barbaz".to_owned())
                .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
        );
    }

    #[test]
    fn self_and_parents() {
        assert_eq!(
            vec![
                ProtobufAbsolutePath::new(".ab.cde.fghi".to_owned()),
                ProtobufAbsolutePath::new(".ab.cde".to_owned()),
                ProtobufAbsolutePath::new(".ab".to_owned()),
                ProtobufAbsolutePath::root(),
            ],
            ProtobufAbsolutePath::new(".ab.cde.fghi".to_owned()).self_and_parents()
        );
    }
}
<|endoftext|>


<commit_before>mod utils;
use clap::{App, Arg};

const USE_FLAG_AS_ARGUMENT: &str =
    "error: Found argument '--another-flag' which wasn't expected, or isn't valid in this context

\tIf you tried to supply `--another-flag` as a value rather than a flag, use `-- --another-flag`

USAGE:
    mycat [FLAGS] [filename]

For more information try --help";

#[test]
fn flag_using_short() {
    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "-f", "-c"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn lots_o_flags_sep() {
    let r = App::new("opts")
        .arg(Arg::from("-o... 'some flag'"))
        .try_get_matches_from(vec![
            "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
    let m = r.unwrap();
    assert!(m.is_present("o"));
    assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}

#[test]
fn lots_o_flags_combined() {
    let r = App::new("opts")
        .arg(Arg::from("-o... 'some flag'"))
        .try_get_matches_from(vec![
            "",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-ooooooooooooooooooooooooooooooooooooooooo",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
    let m = r.unwrap();
    assert!(m.is_present("o"));
    assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}

#[test]
fn flag_using_long() {
    let m = App::new("flag")
        .args(&[
            Arg::from("--flag 'some flag'"),
            Arg::from("--color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "--flag", "--color"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn flag_using_long_with_literals() {
    use clap::ErrorKind;

    let m = App::new("flag")
        .arg(Arg::new("rainbow"))
        .try_get_matches_from(vec!["", "--rainbow=false"]);
    assert!(m.is_err(), "{:#?}", m.unwrap());
    assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyValues);
}

#[test]
fn flag_using_mixed() {
    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "-f", "--color"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));

    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "--flag", "-c"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn multiple_flags_in_single() {
    let m = App::new("multe_flags")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
            Arg::from("-d, --debug 'another other flag'"),
        ])
        .get_matches_from(vec!["", "-fcd"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
    assert!(m.is_present("debug"));
}

#[test]
fn issue_1284_argument_in_flag_style() {
    let app = App::new("mycat")
        .arg(Arg::new("filename"))
        .arg(Arg::new("a-flag").long("a-flag"));

    let m = app
        .clone()
        .get_matches_from(vec!["", "--", "--another-flag"]);
    assert_eq!(m.value_of("filename"), Some("--another-flag"));

    let m = app.clone().get_matches_from(vec!["", "--a-flag"]);
    assert!(m.is_present("a-flag"));

    let m = app.clone().get_matches_from(vec!["", "--", "--a-flag"]);
    assert_eq!(m.value_of("filename"), Some("--a-flag"));

    assert!(utils::compare_output(
        app,
        "mycat --another-flag",
        USE_FLAG_AS_ARGUMENT,
        true
    ));
}

#[test]
fn issue_2308_multiple_dashes() {
    static MULTIPLE_DASHES: &str =
        "error: Found argument '-----' which wasn't expected, or isn't valid in this context

	If you tried to supply `-----` as a value rather than a flag, use `-- -----`

USAGE:
    test <arg>

For more information try --help";
    let app = App::new("test").arg(Arg::new("arg").takes_value(true).required(true));

    assert!(utils::compare_output(
        app,
        "test -----",
        MULTIPLE_DASHES,
        true
    ));
}
<commit_msg>fix(test): fix typo in `flag_using_long_with_literals`<commit_after>mod utils;
use clap::{App, Arg};

const USE_FLAG_AS_ARGUMENT: &str =
    "error: Found argument '--another-flag' which wasn't expected, or isn't valid in this context

\tIf you tried to supply `--another-flag` as a value rather than a flag, use `-- --another-flag`

USAGE:
    mycat [FLAGS] [filename]

For more information try --help";

#[test]
fn flag_using_short() {
    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "-f", "-c"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn lots_o_flags_sep() {
    let r = App::new("opts")
        .arg(Arg::from("-o... 'some flag'"))
        .try_get_matches_from(vec![
            "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o",
            "-o", "-o", "-o",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
    let m = r.unwrap();
    assert!(m.is_present("o"));
    assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}

#[test]
fn lots_o_flags_combined() {
    let r = App::new("opts")
        .arg(Arg::from("-o... 'some flag'"))
        .try_get_matches_from(vec![
            "",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo",
            "-ooooooooooooooooooooooooooooooooooooooooo",
        ]);
    assert!(r.is_ok(), "{:?}", r.unwrap_err().kind);
    let m = r.unwrap();
    assert!(m.is_present("o"));
    assert_eq!(m.occurrences_of("o"), 297); // i.e. more than u8
}

#[test]
fn flag_using_long() {
    let m = App::new("flag")
        .args(&[
            Arg::from("--flag 'some flag'"),
            Arg::from("--color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "--flag", "--color"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn flag_using_long_with_literals() {
    use clap::ErrorKind;

    let m = App::new("flag")
        .arg(Arg::new("rainbow").long("rainbow"))
        .try_get_matches_from(vec!["", "--rainbow=false"]);
    assert!(m.is_err(), "{:#?}", m.unwrap());
    assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyValues);
}

#[test]
fn flag_using_mixed() {
    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "-f", "--color"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));

    let m = App::new("flag")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
        ])
        .get_matches_from(vec!["", "--flag", "-c"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
}

#[test]
fn multiple_flags_in_single() {
    let m = App::new("multe_flags")
        .args(&[
            Arg::from("-f, --flag 'some flag'"),
            Arg::from("-c, --color 'some other flag'"),
            Arg::from("-d, --debug 'another other flag'"),
        ])
        .get_matches_from(vec!["", "-fcd"]);
    assert!(m.is_present("flag"));
    assert!(m.is_present("color"));
    assert!(m.is_present("debug"));
}

#[test]
fn issue_1284_argument_in_flag_style() {
    let app = App::new("mycat")
        .arg(Arg::new("filename"))
        .arg(Arg::new("a-flag").long("a-flag"));

    let m = app
        .clone()
        .get_matches_from(vec!["", "--", "--another-flag"]);
    assert_eq!(m.value_of("filename"), Some("--another-flag"));

    let m = app.clone().get_matches_from(vec!["", "--a-flag"]);
    assert!(m.is_present("a-flag"));

    let m = app.clone().get_matches_from(vec!["", "--", "--a-flag"]);
    assert_eq!(m.value_of("filename"), Some("--a-flag"));

    assert!(utils::compare_output(
        app,
        "mycat --another-flag",
        USE_FLAG_AS_ARGUMENT,
        true
    ));
}

#[test]
fn issue_2308_multiple_dashes() {
    static MULTIPLE_DASHES: &str =
        "error: Found argument '-----' which wasn't expected, or isn't valid in this context

	If you tried to supply `-----` as a value rather than a flag, use `-- -----`

USAGE:
    test <arg>

For more information try --help";
    let app = App::new("test").arg(Arg::new("arg").takes_value(true).required(true));

    assert!(utils::compare_output(
        app,
        "test -----",
        MULTIPLE_DASHES,
        true
    ));
}
<|endoftext|>