<commit_before>extern crate xmltree;
extern crate hyper;

use hyper::Client;
use hyper::header::Connection;
use std::io::Read;

use hyper::Url;

/// Turns "123" into 123
pub fn intify(instr: &str) -> u32{
    // TODO: Better error handling
    instr.to_owned().parse::<u32>().unwrap()
}

/// Errors in contacting TheTVDB
#[derive(Debug)]
pub enum TvdbError {
    SeriesNotFound,
    CommunicationError{reason: String},
    DataError{reason: String},
    Cancelled,
}

/// Series ID from TheTVDB.com, along with language
#[derive(Debug,Clone)]
pub struct EpisodeId{
    seriesid: u32,
    lang: String,
}

impl Into<EpisodeId> for u32{
    fn into(self) -> EpisodeId{
        EpisodeId{seriesid: self, lang: "en".to_owned()}
    }
}

impl Into<EpisodeId> for SeriesSearchResult{
    fn into(self) -> EpisodeId{
        EpisodeId{seriesid: self.seriesid, lang: self.language}
    }
}

/// Series info as returned from TheTVDB's series search method:
/// http://www.thetvdb.com/wiki/index.php?title=API:GetSeries
#[derive(Debug,Clone)]
pub struct SeriesSearchResult{
    pub seriesid: u32, // seriesid is preferred over id according to TVDB wiki
    pub seriesname: String,
    pub language: String,
    pub overview: Option<String>,
    pub banner: Option<String>,
    pub imdb_id: Option<String>,
    //pub firstaired: Date,
    pub network: Option<String>,
    pub zap2it_id: Option<String>,

    api: Tvdb,
}

/// Base episode record,
/// http://www.thetvdb.com/wiki/index.php?title=API:Base_Episode_Record
#[derive(Debug,Clone)]
pub struct EpisodeInfo{
    pub id: u32, //id
    // Combined_episodenumber
    // Combined_season
    // DVD_chapter
    // DVD_discid
    // DVD_episodenumber
    // DVD_season
    // Director
    // EpImgFlag
    pub episodename: String, // EpisodeName
    // EpisodeNumber
    // FirstAired
    // GuestStars
    // IMDB_ID
    // Language
    // Overview
    // ProductionCode
    // Rating
    // RatingCount
    // SeasonNumber
    // Writer
    // absolute_number
    // airsafter_season
    // airsbefore_episode
    // airsbefore_season
    // filename
    // lastupdated
    // seasonid
    // seriesid
    // thumb_added
    // thumb_height
    // thumb_width
}

/// Main interface
#[derive(Debug,Clone)]
pub struct Tvdb{
    key: String,
}

impl Tvdb{
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new(key: String) -> Tvdb{
        Tvdb{key: key}
    }

    /// Searches for a given series name.
    pub fn search(&self, seriesname: String, lang: String) -> Result<Vec<SeriesSearchResult>, TvdbError>{
        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/GetSeries.php?seriesname={}", seriesname);
        let url = Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());

        // Convert XML into structs
        let mut results : Vec<SeriesSearchResult> = vec![];

        for child in tree.children.iter(){

            fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
                child.get_child(x).and_then(|id_child| id_child.text.clone())
            }

            let r = SeriesSearchResult{
                seriesid:   intify(&get_text(child, "seriesid").expect("Search result XML missing 'seriesid' element")),
                seriesname: get_text(child, "SeriesName").expect("Search result XML Missing 'SeriesName' element"),
                language:   get_text(child, "language").expect("Search result XML missing 'language' element"),
                overview:   get_text(child, "Overview"),
                banner:     get_text(child, "banner"),
                imdb_id:    get_text(child, "IMDB_ID"),
                //firstaired: Date,
                network:    get_text(child, "Network"),
                zap2it_id:  get_text(child, "zap2it_id"),

                api: self.clone(), // TODO: Is there better way of allowing EpisodeInfo.episode(..) to access the key?
            };

            results.push(r);
        }

        if results.is_empty(){
            return Err(TvdbError::SeriesNotFound);
        }

        return Ok(results);
    }

    pub fn episode<T: Into<EpisodeId>>(&self, epid: T, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        // <mirrorpath>/api/<apikey>/series/{seriesid}/default/{season}/{episode}/{language}.xml

        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/{apikey}/series/{seriesid}/default/{season}/{episode}/{language}.xml",
                                    apikey=self.key,
                                    seriesid=epid.into().seriesid,
                                    language=epid.into().lang,
                                    season=season,
                                    episode=episode,
                                    );
        let url = Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        // Perform request
        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());
        let root = tree.children.first().unwrap();

        fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
            child.get_child(x).and_then(|id_child| id_child.text.clone())
        }

        // Convert XML into struct
        Ok(EpisodeInfo{
            id: intify(&get_text(root, "id").unwrap()),
            episodename: get_text(root, "EpisodeName").unwrap(),
        })
    }
}

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

    const APIKEY: &'static str = "0629B785CE550C8D";

    #[test]
    fn search() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned());
        assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
    }

    #[test]
    fn nonexist() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("ladlkgdklfgsdfglk".to_owned(), "en".to_owned());
        assert!(sr.is_err());
    }

    #[test]
    fn epinfo_default(){
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned()).ok().unwrap();
        let ep = api.episode(sr[0].clone(), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

}
<commit_msg>SeriesSearchResult no longer needs to have Tvdb<commit_after>extern crate xmltree;
extern crate hyper;

use hyper::Client;
use hyper::header::Connection;
use std::io::Read;

use hyper::Url;

/// Turns "123" into 123
fn intify(instr: &str) -> u32{
    // TODO: Better error handling
    instr.to_owned().parse::<u32>().unwrap()
}

/// Errors in contacting TheTVDB
#[derive(Debug)]
pub enum TvdbError {
    SeriesNotFound,
    CommunicationError{reason: String},
    DataError{reason: String},
    Cancelled,
}

/// Series ID from TheTVDB.com, along with language
#[derive(Debug,Clone)]
pub struct EpisodeId{
    seriesid: u32,
    lang: String,
}

impl Into<EpisodeId> for u32{
    fn into(self) -> EpisodeId{
        EpisodeId{seriesid: self, lang: "en".to_owned()}
    }
}

impl Into<EpisodeId> for SeriesSearchResult{
    fn into(self) -> EpisodeId{
        EpisodeId{seriesid: self.seriesid, lang: self.language}
    }
}

/// Series info as returned from TheTVDB's series search method:
/// http://www.thetvdb.com/wiki/index.php?title=API:GetSeries
#[derive(Debug,Clone)]
pub struct SeriesSearchResult{
    pub seriesid: u32, // seriesid is preferred over id according to TVDB wiki
    pub seriesname: String,
    pub language: String,
    pub overview: Option<String>,
    pub banner: Option<String>,
    pub imdb_id: Option<String>,
    //pub firstaired: Date,
    pub network: Option<String>,
    pub zap2it_id: Option<String>,
}

/// Base episode record,
/// http://www.thetvdb.com/wiki/index.php?title=API:Base_Episode_Record
#[derive(Debug,Clone)]
pub struct EpisodeInfo{
    pub id: u32, //id
    // Combined_episodenumber
    // Combined_season
    // DVD_chapter
    // DVD_discid
    // DVD_episodenumber
    // DVD_season
    // Director
    // EpImgFlag
    pub episodename: String, // EpisodeName
    // EpisodeNumber
    // FirstAired
    // GuestStars
    // IMDB_ID
    // Language
    // Overview
    // ProductionCode
    // Rating
    // RatingCount
    // SeasonNumber
    // Writer
    // absolute_number
    // airsafter_season
    // airsbefore_episode
    // airsbefore_season
    // filename
    // lastupdated
    // seasonid
    // seriesid
    // thumb_added
    // thumb_height
    // thumb_width
}

/// Main interface
#[derive(Debug,Clone)]
pub struct Tvdb{
    key: String,
}

impl Tvdb{
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new(key: String) -> Tvdb{
        Tvdb{key: key}
    }

    /// Searches for a given series name.
    pub fn search(&self, seriesname: String, lang: String) -> Result<Vec<SeriesSearchResult>, TvdbError>{
        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/GetSeries.php?seriesname={}", seriesname);
        let url = Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());

        // Convert XML into structs
        let mut results : Vec<SeriesSearchResult> = vec![];

        for child in tree.children.iter(){

            fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
                child.get_child(x).and_then(|id_child| id_child.text.clone())
            }

            let r = SeriesSearchResult{
                seriesid:   intify(&get_text(child, "seriesid").expect("Search result XML missing 'seriesid' element")),
                seriesname: get_text(child, "SeriesName").expect("Search result XML Missing 'SeriesName' element"),
                language:   get_text(child, "language").expect("Search result XML missing 'language' element"),
                overview:   get_text(child, "Overview"),
                banner:     get_text(child, "banner"),
                imdb_id:    get_text(child, "IMDB_ID"),
                //firstaired: Date,
                network:    get_text(child, "Network"),
                zap2it_id:  get_text(child, "zap2it_id"),
            };

            results.push(r);
        }

        if results.is_empty(){
            return Err(TvdbError::SeriesNotFound);
        }

        return Ok(results);
    }

    fn episode_inner(&self, epid: EpisodeId, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        // <mirrorpath>/api/<apikey>/series/{seriesid}/default/{season}/{episode}/{language}.xml

        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/{apikey}/series/{seriesid}/default/{season}/{episode}/{language}.xml",
                                    apikey=self.key,
                                    seriesid=epid.seriesid,
                                    language=epid.lang,
                                    season=season,
                                    episode=episode,
                                    );
        let url = Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        // Perform request
        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());
        let root = tree.children.first().unwrap();

        fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
            child.get_child(x).and_then(|id_child| id_child.text.clone())
        }

        // Convert XML into struct
        Ok(EpisodeInfo{
            id: intify(&get_text(root, "id").unwrap()),
            episodename: get_text(root, "EpisodeName").unwrap(),
        })
    }

    pub fn episode<T: Into<EpisodeId>>(&self, epid: T, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        self.episode_inner(epid.into(), season, episode)
    }
}

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

    const APIKEY: &'static str = "0629B785CE550C8D";

    #[test]
    fn search() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned());
        assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
    }

    #[test]
    fn nonexist() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("ladlkgdklfgsdfglk".to_owned(), "en".to_owned());
        assert!(sr.is_err());
    }

    #[test]
    fn epinfo_default(){
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned()).ok().unwrap();
        let ep = api.episode(sr[0].clone(), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

pub use self::column::Column;
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::insert::InsertStatement;
pub use self::parser::*;
pub use self::select::SelectStatement;
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod column;
mod common;
mod condition;
mod insert;
mod select;
mod table;
<commit_msg>Make `FieldExpression` public<commit_after>#[macro_use]
extern crate nom;

pub use self::column::{Column, FieldExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::insert::InsertStatement;
pub use self::parser::*;
pub use self::select::SelectStatement;
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod column;
mod common;
mod condition;
mod insert;
mod select;
mod table;
<|endoftext|>


<commit_before>extern crate bytes;
#[macro_use]
extern crate futures;
extern crate futures_state_stream;
extern crate imap_proto;
extern crate native_tls;
extern crate nom;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;

pub mod client;
pub mod proto;

pub use client::Client;

pub mod types {
    pub use imap_proto::types::*;
}
<commit_msg>Implement general linting strategy<commit_after>#![deny(warnings)]
#![deny(unused)]
#![deny(future_incompatible)]
#![deny(bad_style)]

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate futures_state_stream;
extern crate imap_proto;
extern crate native_tls;
extern crate nom;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;

pub mod client;
pub mod proto;

pub use client::Client;

pub mod types {
    pub use imap_proto::types::*;
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![feature(collections)]

extern crate libc;
extern crate winapi;

pub use ffi::*;

use libc::funcs::extra::kernel32;
use libc::c_void;
use winapi::HANDLE;
use std::{ ptr, mem, io };
use std::io::{Error, ErrorKind};

mod ffi;

pub struct Connection {
	// Pointer to the serial connection
	comm_handle: HANDLE
}

impl Connection {
	pub fn new(port: &str, baud_rate: u32) -> io::Result<Connection> {
		let (comm_handle, cf_result) = unsafe {
			let mut port_u16: Vec<_> = port.utf16_units().collect();
			port_u16.push(0);
			(
				kernel32::CreateFileW(port_u16.as_ptr(),
					winapi::GENERIC_READ | winapi::GENERIC_WRITE,
					0,
					ptr::null_mut(),
					winapi::OPEN_EXISTING,
					0,
					ptr::null_mut()),
				kernel32::GetLastError()
			)
		};

		if comm_handle == winapi::INVALID_HANDLE_VALUE {
			Err(match cf_result {
				winapi::ERROR_ACCESS_DENIED =>
					Error::new(ErrorKind::AlreadyExists, "Access denied, port might be busy"),
				winapi::ERROR_FILE_NOT_FOUND =>
					Error::new(ErrorKind::NotFound, "COM port does not exist"),
				_ => Error::new(ErrorKind::Other, "Invalid COM port handle")
			})
		} else {
			let mut conn = Connection{ comm_handle: comm_handle };
			match conn.set_baud_rate(baud_rate) {
				Ok(_) => Ok(conn),
				Err(e) => Err(Error::new(ErrorKind::Other, "Error setting baud rate")),
			}
		}
	}

	pub fn set_baud_rate(&mut self, baud_rate: u32) -> Result<(), ()> {
		unsafe {
			let mut dcb = mem::zeroed();
			if GetCommState(self.comm_handle, &mut dcb) <= 0 {
				Err(())
			} else {
				dcb.BaudRate = baud_rate;
				if SetCommState(self.comm_handle, &mut dcb) <= 0 {
					Err(())
				} else {
					Ok(())
				}
			}
		}
	}
}
impl io::Read for Connection {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		let mut n_bytes_read = 0;

		let (succeded, err) = unsafe { (
			kernel32::ReadFile(self.comm_handle,
				buf.as_mut_ptr() as *mut c_void,
				buf.len() as u32,
				&mut n_bytes_read,
				ptr::null_mut()) > 0,
			kernel32::GetLastError()
		) };

		if succeded {
			Ok(n_bytes_read as usize)
		} else {
			Err(match err {
				winapi::ERROR_INVALID_USER_BUFFER =>
					Error::new(ErrorKind::InvalidInput, "Supplied buffer is invalid"),
				winapi::ERROR_NOT_ENOUGH_MEMORY =>
					Error::new(ErrorKind::Other, "Too many I/O requests"),
				winapi::ERROR_OPERATION_ABORTED =>
					Error::new(ErrorKind::Interrupted, "Operation was canceled"),
				_ => Error::new(ErrorKind::Other, format!("Read failed with 0x{:x}", err))
			})
		}
	}
}

#[test]
fn test() {
	let con = Connection::new("COM8", 9600).unwrap();
}<commit_msg>impl Write for Connection<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![feature(collections)]

extern crate libc;
extern crate winapi;

pub use ffi::*;

use libc::funcs::extra::kernel32;
use libc::c_void;
use winapi::HANDLE;
use std::{ ptr, mem, io };
use std::io::{Error, ErrorKind};

mod ffi;

pub struct Connection {
	// Pointer to the serial connection
	comm_handle: HANDLE
}

impl Connection {
	pub fn new(port: &str, baud_rate: u32) -> io::Result<Connection> {
		let (comm_handle, cf_result) = unsafe {
			let mut port_u16: Vec<_> = port.utf16_units().collect();
			port_u16.push(0);
			(
				kernel32::CreateFileW(port_u16.as_ptr(),
					winapi::GENERIC_READ | winapi::GENERIC_WRITE,
					0,
					ptr::null_mut(),
					winapi::OPEN_EXISTING,
					0,
					ptr::null_mut()),
				kernel32::GetLastError()
			)
		};

		if comm_handle == winapi::INVALID_HANDLE_VALUE {
			Err(match cf_result {
				winapi::ERROR_ACCESS_DENIED =>
					Error::new(ErrorKind::AlreadyExists, "Access denied, port might be busy"),
				winapi::ERROR_FILE_NOT_FOUND =>
					Error::new(ErrorKind::NotFound, "COM port does not exist"),
				_ => Error::new(ErrorKind::Other, "Invalid COM port handle")
			})
		} else {
			let mut conn = Connection{ comm_handle: comm_handle };
			match conn.set_baud_rate(baud_rate) {
				Ok(_) => Ok(conn),
				Err(_) => Err(Error::new(ErrorKind::Other, "Error setting baud rate")),
			}
		}
	}

	pub fn set_baud_rate(&mut self, baud_rate: u32) -> Result<(), ()> {
		unsafe {
			let mut dcb = mem::zeroed();
			if GetCommState(self.comm_handle, &mut dcb) <= 0 {
				Err(())
			} else {
				dcb.BaudRate = baud_rate;
				if SetCommState(self.comm_handle, &mut dcb) <= 0 {
					Err(())
				} else {
					Ok(())
				}
			}
		}
	}
}
impl io::Read for Connection {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		let mut n_bytes_read = 0;

		let (succeded, err) = unsafe { (
			kernel32::ReadFile(self.comm_handle,
				buf.as_mut_ptr() as *mut c_void,
				buf.len() as u32,
				&mut n_bytes_read,
				ptr::null_mut()) > 0,
			kernel32::GetLastError()
		) };

		if succeded {
			Ok(n_bytes_read as usize)
		} else {
			Err(match err {
				winapi::ERROR_INVALID_USER_BUFFER =>
					Error::new(ErrorKind::InvalidInput, "Supplied buffer is invalid"),
				winapi::ERROR_NOT_ENOUGH_MEMORY =>
					Error::new(ErrorKind::Other, "Too many I/O requests"),
				winapi::ERROR_OPERATION_ABORTED =>
					Error::new(ErrorKind::Interrupted, "Operation was canceled"),
				_ => Error::new(ErrorKind::Other, format!("Read failed with 0x{:x}", err))
			})
		}
	}
}
impl io::Write for Connection {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		let mut n_bytes_written = 0;

		let (succeded, err) = unsafe { (
			kernel32::WriteFile(self.comm_handle,
				mem::transmute(buf.as_ptr()),
				buf.len() as u32,
				&mut n_bytes_written,
				ptr::null_mut()) > 0,
			kernel32::GetLastError()
		) };

		if succeded {
			Ok(n_bytes_written as usize)
		} else {
			Err(match err {
				winapi::ERROR_INVALID_USER_BUFFER =>
					Error::new(ErrorKind::InvalidInput, "Supplied buffer is invalid"),
				winapi::ERROR_NOT_ENOUGH_MEMORY =>
					Error::new(ErrorKind::Other, "Too many I/O requests"),
				winapi::ERROR_OPERATION_ABORTED =>
					Error::new(ErrorKind::Interrupted, "Operation was canceled"),
				_ => Error::new(ErrorKind::Other, format!("Write failed with 0x{:x}", err))
			})
		}
	}

	fn flush(&mut self) -> io::Result<()> {
		Ok(())
	}
}

#[test]
fn test() {
	let con = Connection::new("COM8", 9600).unwrap();
}<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/semver/0.0.0")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)]
#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
#![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))]
#![allow(
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::doc_markdown,
    clippy::items_after_statements,
    clippy::match_bool,
    clippy::missing_errors_doc,
    clippy::must_use_candidate,
    clippy::needless_doctest_main,
    clippy::option_if_let_else,
    clippy::ptr_as_ptr,
    clippy::redundant_else,
    clippy::similar_names,
    clippy::unnested_or_patterns,
    clippy::unseparated_literal_suffix,
    clippy::wildcard_imports
)]

#[cfg(not(no_alloc_crate))]
extern crate alloc;

mod backport;
mod display;
mod error;
mod eval;
mod identifier;
mod impls;
mod parse;

#[cfg(feature = "serde")]
mod serde;

use crate::alloc::vec::Vec;
use crate::identifier::Identifier;
use core::str::FromStr;

#[allow(unused_imports)]
use crate::backport::*;

pub use crate::parse::Error;

/// **SemVer version** as defined by <https://semver.org>.
///
/// # Syntax
///
/// - The major, minor, and patch numbers may be any integer 0 through u64::MAX.
///   When representing a SemVer version as a string, each number is written as
///   a base 10 integer. For example, `1.0.119`.
///
/// - Leading zeros are forbidden in those positions. For example `1.01.00` is
///   invalid as a SemVer version.
///
/// - The pre-release identifier, if present, must conform to the syntax
///   documented for [`Prerelease`].
///
/// - The build metadata, if present, must conform to the syntax documneted for
///   [`BuildMetadata`].
///
/// - Whitespace is not allowed anywhere in the version.
///
/// # Total ordering
///
/// Given any two SemVer versions, one is less than, greater than, or equal to
/// the other. Versions may be compared against one another using Rust's usual
/// comparison operators.
///
/// - The major, minor, and patch number are compared numerically from left to
/// right, lexicographically ordered as a 3-tuple of integers. So for example
/// version `1.5.0` is less than version `1.19.0`, despite the fact that
/// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5
/// as real numbers.
///
/// - When major, minor, and patch are equal, a pre-release version is
///   considered less than the ordinary release: version `1.0.0-alpha.1` is
///   less than version `1.0.0`.
///
/// - Two pre-releases of the same major, minor, patch are compared by
///   lexicographic ordering of dot-separated components of the pre-release
///   string.
///
///   - Identifiers consisting of only digits are compared
///     numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`.
///
///   - Identifiers that contain a letter or hyphen are compared in ASCII sort
///     order: `1.0.0-pre12` is less than `1.0.0-pre8`.
///
///   - Any numeric identifier is always less than any non-numeric
///     identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`.
///
/// Example: `1.0.0-alpha` < `1.0.0-alpha.1` < `1.0.0-alpha.beta` < `1.0.0-beta` < `1.0.0-beta.2` < `1.0.0-beta.11` < `1.0.0-rc.1` < `1.0.0`
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Version {
    pub major: u64,
    pub minor: u64,
    pub patch: u64,
    pub pre: Prerelease,
    pub build: BuildMetadata,
}

/// **SemVer version requirement** describing the intersection of some version
/// comparators, such as `>=1.2.3, <1.8`.
///
/// # Syntax
///
/// - Either `*` (meaning "any"), or one or more comma-separated comparators.
///
/// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated
///   by optional whitespace. For example `>=1.0.0` or `>=1.0`.
///
/// - Build metadata is syntactically permitted on the partial versions, but is
///   completely ignored, as it's never relevant to whether any comparator
///   matches a particular version.
///
/// - Whitespace is permitted around commas and around operators. Whitespace is
///   not permitted within a partial version, i.e. anywhere between the major
///   version number and its minor, patch, pre-release, or build metadata.
#[derive(Default, Clone, Eq, PartialEq, Hash, Debug)]
pub struct VersionReq {
    pub comparators: Vec<Comparator>,
}

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Comparator {
    pub op: Op,
    pub major: u64,
    pub minor: Option<u64>,
    pub patch: Option<u64>,
    pub pre: Prerelease,
}

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[cfg_attr(not(no_non_exhaustive), non_exhaustive)]
pub enum Op {
    Exact,
    Greater,
    GreaterEq,
    Less,
    LessEq,
    Tilde,
    Caret,
    Wildcard,

    #[cfg(no_non_exhaustive)] // rustc <1.40
    #[doc(hidden)]
    __NonExhaustive,
}

#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct Prerelease {
    identifier: Identifier,
}

#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct BuildMetadata {
    identifier: Identifier,
}

impl Version {
    /// Create `Version` with an empty pre-release and build metadata.
    ///
    /// Equivalent to:
    ///
    /// ```
    /// # use semver::{BuildMetadata, Prerelease, Version};
    /// #
    /// # const fn new(major: u64, minor: u64, patch: u64) -> Version {
    /// Version {
    ///     major,
    ///     minor,
    ///     patch,
    ///     pre: Prerelease::EMPTY,
    ///     build: BuildMetadata::EMPTY,
    /// }
    /// # }
    /// ```
    pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
        Version {
            major,
            minor,
            patch,
            pre: Prerelease::EMPTY,
            build: BuildMetadata::EMPTY,
        }
    }

    /// Create `Version` by parsing from string representation.
    ///
    /// # Errors
    ///
    /// Possible reasons for the parse to fail include:
    ///
    /// - `1.0` — too few numeric components. A SemVer version must have
    ///   exactly three. If you are looking at something that has fewer than
    ///   three numbers in it, it's possible it is a `VersionReq` instead (with
    ///   an implicit default `^` comparison operator).
    ///
    /// - `1.0.01` — a numeric component has a leading zero.
    ///
    /// - `1.0.unknown` — unexpected character in one of the components.
    ///
    /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are
    ///   indicated present but empty.
    ///
    /// - `1.0.0-alpha_123` — pre-release or build metadata have something
    ///   outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`,
    ///   and `.` (dot).
    ///
    /// - `23456789999999999999.0.0` — overflow of a u64.
    pub fn parse(text: &str) -> Result<Self, Error> {
        Version::from_str(text)
    }
}

impl VersionReq {
    /// A `VersionReq` with no constraint on the version numbers it matches.
    /// Equivalent to `VersionReq::parse("*").unwrap()`.
    ///
    /// In terms of comparators this is equivalent to `>=0.0.0`.
    ///
    /// Counterintuitively a `*` VersionReq does not match every possible
    /// version number. In particular, in order for *any* `VersionReq` to match
    /// a pre-release version, the `VersionReq` must contain at least one
    /// `Comparator` that has an explicit major, minor, and patch version
    /// identical to the pre-release being matched, and that has a nonempty
    /// pre-release component. Since `*` is not written with an explicit major,
    /// minor, and patch version, and does not contain a nonempty pre-release
    /// component, it does not match any pre-release versions.
    #[cfg(not(no_const_vec_new))] // rustc <1.39
    pub const STAR: Self = VersionReq {
        comparators: Vec::new(),
    };

    /// Create `VersionReq` by parsing from string representation.
    ///
    /// # Errors
    ///
    /// Possible reasons for the parse to fail include:
    ///
    /// - `>a.b` — unexpected characters in the partial version.
    ///
    /// - `@1.0.0` — unrecognized comparison operator.
    ///
    /// - `^1.0.0, ` — unexpected end of input.
    ///
    /// - `>=1.0 <2.0` — missing comma between comparators.
    ///
    /// - `*.*` — unsupported wildcard syntax.
    pub fn parse(text: &str) -> Result<Self, Error> {
        VersionReq::from_str(text)
    }

    /// Evaluate whether the given `Version` satisfies the version requirement
    /// described by `self`.
    pub fn matches(&self, version: &Version) -> bool {
        eval::matches_req(self, version)
    }
}

impl Comparator {
    pub fn parse(text: &str) -> Result<Self, Error> {
        Comparator::from_str(text)
    }

    pub fn matches(&self, version: &Version) -> bool {
        eval::matches_comparator(self, version)
    }
}

impl Prerelease {
    pub const EMPTY: Self = Prerelease {
        identifier: Identifier::empty(),
    };

    pub fn new(text: &str) -> Result<Self, Error> {
        Prerelease::from_str(text)
    }

    pub fn as_str(&self) -> &str {
        self.identifier.as_str()
    }

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

impl BuildMetadata {
    pub const EMPTY: Self = BuildMetadata {
        identifier: Identifier::empty(),
    };

    pub fn new(text: &str) -> Result<Self, Error> {
        BuildMetadata::from_str(text)
    }

    pub fn as_str(&self) -> &str {
        self.identifier.as_str()
    }

    pub fn is_empty(&self) -> bool {
        self.identifier.is_empty()
    }
}
<commit_msg>Document Comparator<commit_after>#![doc(html_root_url = "https://docs.rs/semver/0.0.0")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)]
#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
#![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))]
#![allow(
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::doc_markdown,
    clippy::items_after_statements,
    clippy::match_bool,
    clippy::missing_errors_doc,
    clippy::must_use_candidate,
    clippy::needless_doctest_main,
    clippy::option_if_let_else,
    clippy::ptr_as_ptr,
    clippy::redundant_else,
    clippy::similar_names,
    clippy::unnested_or_patterns,
    clippy::unseparated_literal_suffix,
    clippy::wildcard_imports
)]

#[cfg(not(no_alloc_crate))]
extern crate alloc;

mod backport;
mod display;
mod error;
mod eval;
mod identifier;
mod impls;
mod parse;

#[cfg(feature = "serde")]
mod serde;

use crate::alloc::vec::Vec;
use crate::identifier::Identifier;
use core::str::FromStr;

#[allow(unused_imports)]
use crate::backport::*;

pub use crate::parse::Error;

/// **SemVer version** as defined by <https://semver.org>.
///
/// # Syntax
///
/// - The major, minor, and patch numbers may be any integer 0 through u64::MAX.
///   When representing a SemVer version as a string, each number is written as
///   a base 10 integer. For example, `1.0.119`.
///
/// - Leading zeros are forbidden in those positions. For example `1.01.00` is
///   invalid as a SemVer version.
///
/// - The pre-release identifier, if present, must conform to the syntax
///   documented for [`Prerelease`].
///
/// - The build metadata, if present, must conform to the syntax documneted for
///   [`BuildMetadata`].
///
/// - Whitespace is not allowed anywhere in the version.
///
/// # Total ordering
///
/// Given any two SemVer versions, one is less than, greater than, or equal to
/// the other. Versions may be compared against one another using Rust's usual
/// comparison operators.
///
/// - The major, minor, and patch number are compared numerically from left to
/// right, lexicographically ordered as a 3-tuple of integers. So for example
/// version `1.5.0` is less than version `1.19.0`, despite the fact that
/// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5
/// as real numbers.
///
/// - When major, minor, and patch are equal, a pre-release version is
///   considered less than the ordinary release: version `1.0.0-alpha.1` is
///   less than version `1.0.0`.
///
/// - Two pre-releases of the same major, minor, patch are compared by
///   lexicographic ordering of dot-separated components of the pre-release
///   string.
///
///   - Identifiers consisting of only digits are compared
///     numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`.
///
///   - Identifiers that contain a letter or hyphen are compared in ASCII sort
///     order: `1.0.0-pre12` is less than `1.0.0-pre8`.
///
///   - Any numeric identifier is always less than any non-numeric
///     identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`.
///
/// Example: `1.0.0-alpha` < `1.0.0-alpha.1` < `1.0.0-alpha.beta` < `1.0.0-beta` < `1.0.0-beta.2` < `1.0.0-beta.11` < `1.0.0-rc.1` < `1.0.0`
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Version {
    pub major: u64,
    pub minor: u64,
    pub patch: u64,
    pub pre: Prerelease,
    pub build: BuildMetadata,
}

/// **SemVer version requirement** describing the intersection of some version
/// comparators, such as `>=1.2.3, <1.8`.
///
/// # Syntax
///
/// - Either `*` (meaning "any"), or one or more comma-separated comparators.
///
/// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated
///   by optional whitespace. For example `>=1.0.0` or `>=1.0`.
///
/// - Build metadata is syntactically permitted on the partial versions, but is
///   completely ignored, as it's never relevant to whether any comparator
///   matches a particular version.
///
/// - Whitespace is permitted around commas and around operators. Whitespace is
///   not permitted within a partial version, i.e. anywhere between the major
///   version number and its minor, patch, pre-release, or build metadata.
#[derive(Default, Clone, Eq, PartialEq, Hash, Debug)]
pub struct VersionReq {
    pub comparators: Vec<Comparator>,
}

/// A pair of comparison operator and partial version, such as `>=1.2`. Forms
/// one piece of a VersionReq.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Comparator {
    pub op: Op,
    pub major: u64,
    pub minor: Option<u64>,
    pub patch: Option<u64>,
    pub pre: Prerelease,
}

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[cfg_attr(not(no_non_exhaustive), non_exhaustive)]
pub enum Op {
    Exact,
    Greater,
    GreaterEq,
    Less,
    LessEq,
    Tilde,
    Caret,
    Wildcard,

    #[cfg(no_non_exhaustive)] // rustc <1.40
    #[doc(hidden)]
    __NonExhaustive,
}

#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct Prerelease {
    identifier: Identifier,
}

#[derive(Default, Clone, Eq, PartialEq, Hash)]
pub struct BuildMetadata {
    identifier: Identifier,
}

impl Version {
    /// Create `Version` with an empty pre-release and build metadata.
    ///
    /// Equivalent to:
    ///
    /// ```
    /// # use semver::{BuildMetadata, Prerelease, Version};
    /// #
    /// # const fn new(major: u64, minor: u64, patch: u64) -> Version {
    /// Version {
    ///     major,
    ///     minor,
    ///     patch,
    ///     pre: Prerelease::EMPTY,
    ///     build: BuildMetadata::EMPTY,
    /// }
    /// # }
    /// ```
    pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
        Version {
            major,
            minor,
            patch,
            pre: Prerelease::EMPTY,
            build: BuildMetadata::EMPTY,
        }
    }

    /// Create `Version` by parsing from string representation.
    ///
    /// # Errors
    ///
    /// Possible reasons for the parse to fail include:
    ///
    /// - `1.0` — too few numeric components. A SemVer version must have
    ///   exactly three. If you are looking at something that has fewer than
    ///   three numbers in it, it's possible it is a `VersionReq` instead (with
    ///   an implicit default `^` comparison operator).
    ///
    /// - `1.0.01` — a numeric component has a leading zero.
    ///
    /// - `1.0.unknown` — unexpected character in one of the components.
    ///
    /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are
    ///   indicated present but empty.
    ///
    /// - `1.0.0-alpha_123` — pre-release or build metadata have something
    ///   outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`,
    ///   and `.` (dot).
    ///
    /// - `23456789999999999999.0.0` — overflow of a u64.
    pub fn parse(text: &str) -> Result<Self, Error> {
        Version::from_str(text)
    }
}

impl VersionReq {
    /// A `VersionReq` with no constraint on the version numbers it matches.
    /// Equivalent to `VersionReq::parse("*").unwrap()`.
    ///
    /// In terms of comparators this is equivalent to `>=0.0.0`.
    ///
    /// Counterintuitively a `*` VersionReq does not match every possible
    /// version number. In particular, in order for *any* `VersionReq` to match
    /// a pre-release version, the `VersionReq` must contain at least one
    /// `Comparator` that has an explicit major, minor, and patch version
    /// identical to the pre-release being matched, and that has a nonempty
    /// pre-release component. Since `*` is not written with an explicit major,
    /// minor, and patch version, and does not contain a nonempty pre-release
    /// component, it does not match any pre-release versions.
    #[cfg(not(no_const_vec_new))] // rustc <1.39
    pub const STAR: Self = VersionReq {
        comparators: Vec::new(),
    };

    /// Create `VersionReq` by parsing from string representation.
    ///
    /// # Errors
    ///
    /// Possible reasons for the parse to fail include:
    ///
    /// - `>a.b` — unexpected characters in the partial version.
    ///
    /// - `@1.0.0` — unrecognized comparison operator.
    ///
    /// - `^1.0.0, ` — unexpected end of input.
    ///
    /// - `>=1.0 <2.0` — missing comma between comparators.
    ///
    /// - `*.*` — unsupported wildcard syntax.
    pub fn parse(text: &str) -> Result<Self, Error> {
        VersionReq::from_str(text)
    }

    /// Evaluate whether the given `Version` satisfies the version requirement
    /// described by `self`.
    pub fn matches(&self, version: &Version) -> bool {
        eval::matches_req(self, version)
    }
}

impl Comparator {
    pub fn parse(text: &str) -> Result<Self, Error> {
        Comparator::from_str(text)
    }

    pub fn matches(&self, version: &Version) -> bool {
        eval::matches_comparator(self, version)
    }
}

impl Prerelease {
    pub const EMPTY: Self = Prerelease {
        identifier: Identifier::empty(),
    };

    pub fn new(text: &str) -> Result<Self, Error> {
        Prerelease::from_str(text)
    }

    pub fn as_str(&self) -> &str {
        self.identifier.as_str()
    }

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

impl BuildMetadata {
    pub const EMPTY: Self = BuildMetadata {
        identifier: Identifier::empty(),
    };

    pub fn new(text: &str) -> Result<Self, Error> {
        BuildMetadata::from_str(text)
    }

    pub fn as_str(&self) -> &str {
        self.identifier.as_str()
    }

    pub fn is_empty(&self) -> bool {
        self.identifier.is_empty()
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * TODO: shortcuts to select text in the command line entry.
 * TODO: shortcut to move the cursor at the other end of the selection.
 * TODO: smart selection (select all on first time, select all except the prefix on the second).
 * TODO: remove blocking dialogs?
 * FIXME: can block in input mode.
 * TODO: use MainLoop::new() instead of gtk::main()?
 * FIXME: the commands in the config file are not executed.
 * TODO: take advantage of IntoOption and IntoPair.
 * TODO: automatically connect the AppClose message to Quit if it exists.
 * TODO: thread example (using a oneshot).
 * TODO: change all unneeded &mut self to &self.
 * TODO: set the size of the status bar according to the size of the font.
 * TODO: different event for activate event of special commands.
 * TODO: use the gtk::Statusbar widget?
 * TODO: Associate a color with modes.
 */

//! Minimal UI library based on GTK+.

#![feature(unboxed_closures)]
#![warn(
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_qualifications,
)]

extern crate gdk;
extern crate glib;
extern crate gtk;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mg_settings;
extern crate pango;
#[macro_use]
extern crate relm;
#[macro_use]
extern crate relm_derive;

mod app;
pub mod completion;
mod file;
mod key_converter;

/// List of modes
pub type Modes = &'static [Mode];

/// A mode contains a prefix (i.e. "i") and a name (i.e. "insert").
/// It can only specify whether a count can be shown for it.
#[derive(Clone)]
pub struct Mode {
    pub name: &'static str,
    pub prefix: &'static str,
    pub show_count: bool,
}

pub use app::{Mg, parse_config};
pub use app::Msg::{
    Alert,
    AppClose,
    CloseWin,
    Completers,
    CompletionViewChange,
    CustomCommand,
    CustomDialog,
    DarkTheme,
    DeleteCompletionItem,
    Error,
    Info,
    Message,
    ModeChanged,
    Question,
    SetMode,
    SetSetting,
    SettingChanged,
    StatusBarVisible,
    Title,
    Variables,
    Warning,
};
pub use app::dialog::{
    BlockingInputDialog,
    DialogBuilder,
    DialogResult,
    InputDialog,
    Responder,
    blocking_dialog,
    blocking_input,
    blocking_question,
    blocking_yes_no_question,
    input,
    question,
    yes_no_question,
};
pub use app::settings::{DefaultConfig, NoSettings};
pub use app::status_bar::{StatusBar, StatusBarItem};
pub use app::status_bar::ItemMsg::{Color, Text};

#[macro_export]
macro_rules! hash {
    ($($ident:expr => $value:expr,)*) => {{
        let mut hash_map: ::mg::completion::Completers = ::std::collections::HashMap::new();
        $(hash_map.insert($ident, $value);)*
        hash_map
    }};
}

#[macro_export]
macro_rules! char_slice {
    ($( $val:expr ),*) => {{
        static SLICE: &'static [char] = &[$($val),*];
        SLICE
    }};
}

#[macro_export]
macro_rules! static_slice {
    ($( $val:expr ),* ; $typ:ty) => {{
        static SLICE: &'static [$typ] = &[$($val),*];
        SLICE
    }};
}
<commit_msg>Remove `#![feature(unboxed_closures)]`<commit_after>/*
 * Copyright (c) 2016 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * TODO: shortcuts to select text in the command line entry.
 * TODO: shortcut to move the cursor at the other end of the selection.
 * TODO: smart selection (select all on first time, select all except the prefix on the second).
 * TODO: remove blocking dialogs?
 * FIXME: can block in input mode.
 * TODO: use MainLoop::new() instead of gtk::main()?
 * FIXME: the commands in the config file are not executed.
 * TODO: take advantage of IntoOption and IntoPair.
 * TODO: automatically connect the AppClose message to Quit if it exists.
 * TODO: thread example (using a oneshot).
 * TODO: change all unneeded &mut self to &self.
 * TODO: set the size of the status bar according to the size of the font.
 * TODO: different event for activate event of special commands.
 * TODO: use the gtk::Statusbar widget?
 * TODO: Associate a color with modes.
 */

//! Minimal UI library based on GTK+.

#![warn(
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_qualifications,
)]

extern crate gdk;
extern crate glib;
extern crate gtk;
#[macro_use]
extern crate log;
#[macro_use]
extern crate mg_settings;
extern crate pango;
#[macro_use]
extern crate relm;
#[macro_use]
extern crate relm_derive;

mod app;
pub mod completion;
mod file;
mod key_converter;

/// List of modes
pub type Modes = &'static [Mode];

/// A mode contains a prefix (i.e. "i") and a name (i.e. "insert").
/// It can only specify whether a count can be shown for it.
#[derive(Clone)]
pub struct Mode {
    pub name: &'static str,
    pub prefix: &'static str,
    pub show_count: bool,
}

pub use app::{Mg, parse_config};
pub use app::Msg::{
    Alert,
    AppClose,
    CloseWin,
    Completers,
    CompletionViewChange,
    CustomCommand,
    CustomDialog,
    DarkTheme,
    DeleteCompletionItem,
    Error,
    Info,
    Message,
    ModeChanged,
    Question,
    SetMode,
    SetSetting,
    SettingChanged,
    StatusBarVisible,
    Title,
    Variables,
    Warning,
};
pub use app::dialog::{
    BlockingInputDialog,
    DialogBuilder,
    DialogResult,
    InputDialog,
    Responder,
    blocking_dialog,
    blocking_input,
    blocking_question,
    blocking_yes_no_question,
    input,
    question,
    yes_no_question,
};
pub use app::settings::{DefaultConfig, NoSettings};
pub use app::status_bar::{StatusBar, StatusBarItem};
pub use app::status_bar::ItemMsg::{Color, Text};

#[macro_export]
macro_rules! hash {
    ($($ident:expr => $value:expr,)*) => {{
        let mut hash_map: ::mg::completion::Completers = ::std::collections::HashMap::new();
        $(hash_map.insert($ident, $value);)*
        hash_map
    }};
}

#[macro_export]
macro_rules! char_slice {
    ($( $val:expr ),*) => {{
        static SLICE: &'static [char] = &[$($val),*];
        SLICE
    }};
}

#[macro_export]
macro_rules! static_slice {
    ($( $val:expr ),* ; $typ:ty) => {{
        static SLICE: &'static [$typ] = &[$($val),*];
        SLICE
    }};
}
<|endoftext|>


<commit_before>//! A simple and easy wrapper around `Vec` to implement a FIFO queue. This is
//! no fancy, advanced data type but something simple you can use easily until
//! or unless you need something different.
//!
//! # Example
//!
//! ```
//! use queue::Queue;
//!
//! let mut q = Queue::new();
//!
//! q.queue("hello").unwrap();
//! q.queue("out").unwrap();
//! q.queue("there!").unwrap();
//!
//! while let Some(item) = q.dequeue() {
//!     println!("{}", item);
//! }
//! ```
//!
//! Outputs:
//!
//! ```text
//! hello
//! out
//! there!
//! ```

#[cfg(test)]
mod tests;

/// A first in, first out queue built around `Vec`.
///
/// An optional capacity can be set (or changed) to ensure the `Queue` never
/// grows past a certain size. If the capacity is not specified (ie set to
/// `None`) then the `Queue` will grow as needed. If you're worried about
/// memory allocation, set a capacity and the necessary memory will be
/// allocated at that time. Otherwise memory could be allocated, deallocated
/// and reallocated as the `Queue` changes size.
///
/// The only requirement of the type used is that it implements the `Clone`
/// trait.
///
/// # Example
///
/// ```
/// use queue::Queue;
///
/// let mut q = Queue::with_capacity(5);
///
/// for i in 0..5 {
/// 	q.queue(i).unwrap();
/// }
///
/// for i in 0..5 {
/// 	assert_eq!(q.dequeue(), Some(i));
/// }
/// ```
#[derive(Clone, Debug)]
pub struct Queue<T> {
	vec: Vec<T>,
	cap: Option<usize>,
}

impl<T: Clone> Queue<T> {
	/// Constructs a new `Queue<T>`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::new();
	/// ```
	pub fn new() -> Queue<T> {
		Queue {
			vec: Vec::new(),
			cap: None,
		}
	}

	/// Constructs a new `Queue<T>` with a specified capacity.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::with_capacity(20);
	/// ```
	pub fn with_capacity(cap: usize) -> Queue<T> {
		Queue {
			vec: Vec::with_capacity(cap),
			cap: Some(cap),
		}
	}

	/// Add an item to the end of the `Queue`. Returns `Ok(usize)` with the new
	/// length of the `Queue`, or `Err(())` if there is no more room.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// assert_eq!(q.peek(), Some("hello"));
	/// ```
	pub fn queue(&mut self, item: T) -> Result<usize, ()> {
		if let Some(cap) = self.cap {
			if self.vec.len() >= cap {
				Err(())
			} else {
				self.vec.push(item);
				Ok(self.vec.len())
			}
		} else {
			self.vec.push(item);
			Ok(self.vec.len())
		}
	}

	/// Forcefully ad an item to the end of the `Queue`. If the `Queue` is at
	/// capacity, the first item will be removed to make room. Returns `usize`
	/// with the new length of the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(1);
	/// q.queue("hello").unwrap();
	/// let _ = q.force_queue("world");
	/// assert_eq!(q.peek(), Some("world"));
	/// ```
	pub fn force_queue(&mut self, item: T) -> usize {
		if let Ok(len) = self.queue(item.clone()) {
			return len;
		} else {
			let _ = self.dequeue();
			return self.queue(item.clone()).unwrap();
		}
	}

	/// Remove the next item from the `Queue`. Returns `Option<T>` so it will
	/// return either `Some(T)` or `None` depending on if there's anything in
	/// the `Queue` to get.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// q.queue("world").unwrap();
	/// assert_eq!(q.dequeue(), Some("hello"));
	/// ```
	pub fn dequeue(&mut self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec.remove(0))
		} else {
			None
		}
	}

	/// Peek at the next item in the `Queue`, if there's something there.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue(12).unwrap();
	/// assert_eq!(q.peek(), Some(12));
	/// ```
	pub fn peek(&self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec[0].clone())
		} else {
			None
		}
	}

	/// The number of items currently in the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(8);
	/// q.queue(1).unwrap();
	/// q.queue(2).unwrap();
	/// assert_eq!(q.len(), 2);
	/// ```
	pub fn len(&self) -> usize {
		self.vec.len()
	}

	/// Check if the `Queue` is empty.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// assert_eq!(q.is_empty(), true);
	/// q.queue(1).unwrap();
	/// assert_eq!(q.is_empty(), false);
	/// ```
	pub fn is_empty(&self) -> bool {
		self.vec.is_empty()
	}

	/// Query the capacity for a `Queue`. If there is no capacity set (the
	/// `Queue` can grow as needed) then `None` will be returned, otherwise
	/// it will be `Some(usize)`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let q: Queue<u8> = Queue::with_capacity(12);
	/// assert_eq!(q.capacity(), Some(12));
	/// ```
	pub fn capacity(&self) -> Option<usize> {
		self.cap
	}

	/// Modify the capacity of a `Queue`. If set to `None`, the `Queue` will
	/// grow automatically, as needed. Otherwise, it will be limited to the
	/// specified number of items. If there are more items in the `Queue` than
	/// the requested capacity, `Err(())` will be returned, otherwise the
	/// operation will succeed and `Ok(())` will be returned. If the capacity
	/// is shrunk, the underlying `Vec` will be shrunk also, which would free
	/// up whatever extra memory was allocated for the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<u8> = Queue::new();
	/// q.set_capacity(12).unwrap();
	/// q.set_capacity(None).unwrap();
	/// ```
	pub fn set_capacity<C: Into<Option<usize>>>(&mut self, cap: C) -> Result<(), ()> {
		let cap = cap.into();

		if cap == None {
			self.cap = None;
			return Ok(());
		}

		if cap == self.cap {
			return Ok(());
		}

		let cap = cap.unwrap();

		if cap < self.vec.len() {
			return Err(());
		}

		if let Some(scap) = self.cap {
			if cap < scap {
				self.vec.shrink_to_fit();
			}
		}

		let r = cap - self.vec.len();
		self.vec.reserve_exact(r);
		self.cap = Some(cap);

		Ok(())
	}
}
<commit_msg>derive Default<commit_after>//! A simple and easy wrapper around `Vec` to implement a FIFO queue. This is
//! no fancy, advanced data type but something simple you can use easily until
//! or unless you need something different.
//!
//! # Example
//!
//! ```
//! use queue::Queue;
//!
//! let mut q = Queue::new();
//!
//! q.queue("hello").unwrap();
//! q.queue("out").unwrap();
//! q.queue("there!").unwrap();
//!
//! while let Some(item) = q.dequeue() {
//!     println!("{}", item);
//! }
//! ```
//!
//! Outputs:
//!
//! ```text
//! hello
//! out
//! there!
//! ```

#[cfg(test)]
mod tests;

/// A first in, first out queue built around `Vec`.
///
/// An optional capacity can be set (or changed) to ensure the `Queue` never
/// grows past a certain size. If the capacity is not specified (ie set to
/// `None`) then the `Queue` will grow as needed. If you're worried about
/// memory allocation, set a capacity and the necessary memory will be
/// allocated at that time. Otherwise memory could be allocated, deallocated
/// and reallocated as the `Queue` changes size.
///
/// The only requirement of the type used is that it implements the `Clone`
/// trait.
///
/// # Example
///
/// ```
/// use queue::Queue;
///
/// let mut q = Queue::with_capacity(5);
///
/// for i in 0..5 {
/// 	q.queue(i).unwrap();
/// }
///
/// for i in 0..5 {
/// 	assert_eq!(q.dequeue(), Some(i));
/// }
/// ```
#[derive(Clone, Debug, Default)]
pub struct Queue<T> {
	vec: Vec<T>,
	cap: Option<usize>,
}

impl<T: Clone> Queue<T> {
	/// Constructs a new `Queue<T>`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::new();
	/// ```
	pub fn new() -> Queue<T> {
		Queue {
			vec: Vec::new(),
			cap: None,
		}
	}

	/// Constructs a new `Queue<T>` with a specified capacity.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<String> = Queue::with_capacity(20);
	/// ```
	pub fn with_capacity(cap: usize) -> Queue<T> {
		Queue {
			vec: Vec::with_capacity(cap),
			cap: Some(cap),
		}
	}

	/// Add an item to the end of the `Queue`. Returns `Ok(usize)` with the new
	/// length of the `Queue`, or `Err(())` if there is no more room.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// assert_eq!(q.peek(), Some("hello"));
	/// ```
	pub fn queue(&mut self, item: T) -> Result<usize, ()> {
		if let Some(cap) = self.cap {
			if self.vec.len() >= cap {
				Err(())
			} else {
				self.vec.push(item);
				Ok(self.vec.len())
			}
		} else {
			self.vec.push(item);
			Ok(self.vec.len())
		}
	}

	/// Forcefully ad an item to the end of the `Queue`. If the `Queue` is at
	/// capacity, the first item will be removed to make room. Returns `usize`
	/// with the new length of the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(1);
	/// q.queue("hello").unwrap();
	/// let _ = q.force_queue("world");
	/// assert_eq!(q.peek(), Some("world"));
	/// ```
	pub fn force_queue(&mut self, item: T) -> usize {
		if let Ok(len) = self.queue(item.clone()) {
			return len;
		} else {
			let _ = self.dequeue();
			return self.queue(item.clone()).unwrap();
		}
	}

	/// Remove the next item from the `Queue`. Returns `Option<T>` so it will
	/// return either `Some(T)` or `None` depending on if there's anything in
	/// the `Queue` to get.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue("hello").unwrap();
	/// q.queue("world").unwrap();
	/// assert_eq!(q.dequeue(), Some("hello"));
	/// ```
	pub fn dequeue(&mut self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec.remove(0))
		} else {
			None
		}
	}

	/// Peek at the next item in the `Queue`, if there's something there.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// q.queue(12).unwrap();
	/// assert_eq!(q.peek(), Some(12));
	/// ```
	pub fn peek(&self) -> Option<T> {
		if !self.vec.is_empty() {
			Some(self.vec[0].clone())
		} else {
			None
		}
	}

	/// The number of items currently in the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::with_capacity(8);
	/// q.queue(1).unwrap();
	/// q.queue(2).unwrap();
	/// assert_eq!(q.len(), 2);
	/// ```
	pub fn len(&self) -> usize {
		self.vec.len()
	}

	/// Check if the `Queue` is empty.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q = Queue::new();
	/// assert_eq!(q.is_empty(), true);
	/// q.queue(1).unwrap();
	/// assert_eq!(q.is_empty(), false);
	/// ```
	pub fn is_empty(&self) -> bool {
		self.vec.is_empty()
	}

	/// Query the capacity for a `Queue`. If there is no capacity set (the
	/// `Queue` can grow as needed) then `None` will be returned, otherwise
	/// it will be `Some(usize)`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let q: Queue<u8> = Queue::with_capacity(12);
	/// assert_eq!(q.capacity(), Some(12));
	/// ```
	pub fn capacity(&self) -> Option<usize> {
		self.cap
	}

	/// Modify the capacity of a `Queue`. If set to `None`, the `Queue` will
	/// grow automatically, as needed. Otherwise, it will be limited to the
	/// specified number of items. If there are more items in the `Queue` than
	/// the requested capacity, `Err(())` will be returned, otherwise the
	/// operation will succeed and `Ok(())` will be returned. If the capacity
	/// is shrunk, the underlying `Vec` will be shrunk also, which would free
	/// up whatever extra memory was allocated for the `Queue`.
	///
	/// # Example
	///
	/// ```
	/// # use queue::Queue;
	/// let mut q: Queue<u8> = Queue::new();
	/// q.set_capacity(12).unwrap();
	/// q.set_capacity(None).unwrap();
	/// ```
	pub fn set_capacity<C: Into<Option<usize>>>(&mut self, cap: C) -> Result<(), ()> {
		let cap = cap.into();

		if cap == None {
			self.cap = None;
			return Ok(());
		}

		if cap == self.cap {
			return Ok(());
		}

		let cap = cap.unwrap();

		if cap < self.vec.len() {
			return Err(());
		}

		if let Some(scap) = self.cap {
			if cap < scap {
				self.vec.shrink_to_fit();
			}
		}

		let r = cap - self.vec.len();
		self.vec.reserve_exact(r);
		self.cap = Some(cap);

		Ok(())
	}
}
<|endoftext|>


<commit_before>// Anima Engine. The quirky game engine
// Copyright (C) 2016  Dragoș Tiselice
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use math::Quaternion;

/// A simple vector `struct` tailored specifically for graphics.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vector {
    /// `f32` *x* coordinate value
    pub x: f32,
    /// `f32` *y* coordinate value
    pub y: f32,
    /// `f32` *z* coordinate value
    pub z: f32
}

impl Vector {
    /// Creates a vector using 3 values.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(0.0, 1.0, 2.0);
    ///
    /// assert_eq!(v, Vector { x: 0.0, y: 1.0, z: 2.0 });
    /// ```
    pub fn new(x: f32, y: f32, z: f32) -> Vector {
        Vector { x: x, y: y, z: z }
    }

    /// Creates a vector using an array.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new_arr([0.0, 1.0, 2.0]);
    ///
    /// assert_eq!(v, Vector { x: 0.0, y: 1.0, z: 2.0 });
    /// ```
    pub fn new_arr(array: [f32; 3]) -> Vector {
        Vector { x: array[0], y: array[1], z: array[2] }
    }

    /// Creates a uniform vector using 1 value.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new_unf(1.0);
    ///
    /// assert_eq!(v, Vector { x: 1.0, y: 1.0, z: 1.0 });
    /// ```
    pub fn new_unf(v: f32) -> Vector {
        Vector { x: v, y: v, z: v }
    }

    /// Creates a zero (0.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::zero(), Vector { x: 0.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn zero() -> Vector {
        Vector { x: 0.0, y: 0.0, z: 0.0 }
    }

    /// Creates a one (1.0, 1.0, 1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::one(), Vector { x: 1.0, y: 1.0, z: 1.0 });
    /// ```
    pub fn one() -> Vector {
        Vector { x: 1.0, y: 1.0, z: 1.0 }
    }

    /// Creates a back (0.0, 0.0, -1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::back(), Vector { x: 0.0, y: 0.0, z: -1.0 });
    /// ```
    pub fn back() -> Vector {
        Vector { x: 0.0, y: 0.0, z: -1.0 }
    }

    /// Creates a down (0.0, -1.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::down(), Vector { x: 0.0, y: -1.0, z: 0.0 });
    /// ```
    pub fn down() -> Vector {
        Vector { x: 0.0, y: -1.0, z: 0.0 }
    }

    /// Creates a forward (0.0, 0.0, 1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::forward(), Vector { x: 0.0, y: 0.0, z: 1.0 });
    /// ```
    pub fn forward() -> Vector {
        Vector { x: 0.0, y: 0.0, z: 1.0 }
    }

    /// Creates a left (-1.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::left(), Vector { x: -1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn left() -> Vector {
        Vector { x: -1.0, y: 0.0, z: 0.0 }
    }

    /// Creates a right (1.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::right(), Vector { x: 1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn right() -> Vector {
        Vector { x: 1.0, y: 0.0, z: 0.0 }
    }

    /// Creates an up (0.0, 1.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::up(), Vector { x: 0.0, y: 1.0, z: 0.0 });
    /// ```
    pub fn up() -> Vector {
        Vector { x: 0.0, y: 1.0, z: 0.0 }
    }

    /// Computes the length of a vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(1.0, 2.0, 2.0);
    ///
    /// assert_eq!(v.length(), 3.0);
    /// ```
    pub fn length(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
    }

    /// Computes the normalized version of a vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(1.0, 2.0, 2.0);
    /// let n = v.norm();
    ///
    /// assert_eq!(n.length(), 1.0); // Keep precision in mind when comparing floats.
    /// ```
    pub fn norm(&self) -> Vector {
        let length = self.length();

        Vector {
            x: self.x / length,
            y: self.y / length,
            z: self.z / length
        }
    }

    /// Computes the dot product between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(1.0, 2.0, 2.0);
    /// let v2 = Vector::new(3.0, 3.0, 1.0);
    ///
    /// assert_eq!(v1.dot(v2), 11.0);
    /// ```
    pub fn dot(&self, other: Vector) -> f32 {
        self.x * other.x +
        self.y * other.y +
        self.z * other.z
    }

    /// Computes the cross product between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(1.0, 2.0, 2.0);
    /// let v2 = Vector::new(3.0, 3.0, 1.0);
    ///
    /// assert_eq!(v1.cross(v2), Vector { x: -4.0, y: 5.0, z: -3.0 });
    /// ```
    pub fn cross(&self, other: Vector) -> Vector {
        Vector {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x
        }
    }

    /// Rotates a vector according to the rotation represented by the quaternion.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use anima::math::Quaternion;
    /// let q = Quaternion::new(0.0, 1.0, 0.0, 0.0);
    /// let v = Vector::new(1.0, 0.0, 0.0);
    ///
    /// assert_eq!(v.rot(q), Vector { x: -1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn rot(&self, quaternion: Quaternion) -> Vector {
        let conjugate = quaternion.conj();
        let result = quaternion *
                     Quaternion::new(self.x, self.y, self.z, 0.0) *
                     conjugate;

        Vector { x: result.x, y: result.y, z: result.z }
    }

    /// Rotates a vector according to the rotation represented by the quaternion around a point.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use anima::math::Quaternion;
    /// let q = Quaternion::new(0.0, 1.0, 0.0, 0.0);
    /// let v = Vector::new(1.0, 0.0, 0.0);
    /// let p = Vector::new(2.0, 0.0, 0.0);
    ///
    /// assert_eq!(v.rot_around(q, p), Vector { x: 3.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn rot_around(self, quaternion: Quaternion, point: Vector) -> Vector {
        (self - point).rot(quaternion) + point
    }

    /// Computes the angle in radians between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use std::f32::consts;
    /// let v1 = Vector::new(1.0, 0.0, 0.0);
    /// let v2 = Vector::new(0.0, 1.0, 0.0);
    ///
    /// assert_eq!(v1.angle(v2), consts::PI / 2.0);
    /// ```
    pub fn angle(&self, other: Vector) -> f32 {
        self.dot(other).acos()
    }

    /// Computes the distance between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(0.0, 0.0, 0.0);
    /// let v2 = Vector::new(0.0, 1.0, 0.0);
    ///
    /// assert_eq!(v1.dist(v2), 1.0);
    /// ```
    pub fn dist(self, other: Vector) -> f32 {
        (self - other).length()
    }

    /// Converts a vector to an array of homogeneous coordinates.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(1.0, 2.0, 3.0);
    ///
    /// assert_eq!(v.to_array(), [1.0, 2.0, 3.0, 1.0]);
    /// ```
    pub fn to_array(&self) -> [f32; 4] {
        [self.x, self.y, self.z, 1.0]
    }
}

use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::ops::Neg;
use std::cmp::Ordering;

impl Add for Vector {
    type Output = Vector;

    fn add(self, other: Vector) -> Vector {
        Vector {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}

impl Sub for Vector {
    type Output = Vector;

    fn sub(self, other: Vector) -> Vector {
        Vector {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<Vector> for Vector {
    type Output = Vector;

    fn mul(self, other: Vector) -> Vector {
        Vector {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }
}

impl Mul<f32> for Vector {
    type Output = Vector;

    fn mul(self, scalar: f32) -> Vector {
        Vector {
            x: self.x * scalar,
            y: self.y * scalar,
            z: self.z * scalar
        }
    }
}

impl Mul<Vector> for f32 {
    type Output = Vector;

    fn mul(self, vector: Vector) -> Vector {
        Vector {
            x: vector.x * self,
            y: vector.y * self,
            z: vector.z * self
        }
    }
}

impl Neg for Vector {
    type Output = Vector;

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

impl PartialOrd for Vector {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.length().partial_cmp(&other.length())
    }
}
<commit_msg>Removed method because it shouldn't be visible nor here.<commit_after>// Anima Engine. The quirky game engine
// Copyright (C) 2016  Dragoș Tiselice
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use math::Quaternion;

/// A simple vector `struct` tailored specifically for graphics.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vector {
    /// `f32` *x* coordinate value
    pub x: f32,
    /// `f32` *y* coordinate value
    pub y: f32,
    /// `f32` *z* coordinate value
    pub z: f32
}

impl Vector {
    /// Creates a vector using 3 values.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(0.0, 1.0, 2.0);
    ///
    /// assert_eq!(v, Vector { x: 0.0, y: 1.0, z: 2.0 });
    /// ```
    pub fn new(x: f32, y: f32, z: f32) -> Vector {
        Vector { x: x, y: y, z: z }
    }

    /// Creates a vector using an array.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new_arr([0.0, 1.0, 2.0]);
    ///
    /// assert_eq!(v, Vector { x: 0.0, y: 1.0, z: 2.0 });
    /// ```
    pub fn new_arr(array: [f32; 3]) -> Vector {
        Vector { x: array[0], y: array[1], z: array[2] }
    }

    /// Creates a uniform vector using 1 value.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new_unf(1.0);
    ///
    /// assert_eq!(v, Vector { x: 1.0, y: 1.0, z: 1.0 });
    /// ```
    pub fn new_unf(v: f32) -> Vector {
        Vector { x: v, y: v, z: v }
    }

    /// Creates a zero (0.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::zero(), Vector { x: 0.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn zero() -> Vector {
        Vector { x: 0.0, y: 0.0, z: 0.0 }
    }

    /// Creates a one (1.0, 1.0, 1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::one(), Vector { x: 1.0, y: 1.0, z: 1.0 });
    /// ```
    pub fn one() -> Vector {
        Vector { x: 1.0, y: 1.0, z: 1.0 }
    }

    /// Creates a back (0.0, 0.0, -1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::back(), Vector { x: 0.0, y: 0.0, z: -1.0 });
    /// ```
    pub fn back() -> Vector {
        Vector { x: 0.0, y: 0.0, z: -1.0 }
    }

    /// Creates a down (0.0, -1.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::down(), Vector { x: 0.0, y: -1.0, z: 0.0 });
    /// ```
    pub fn down() -> Vector {
        Vector { x: 0.0, y: -1.0, z: 0.0 }
    }

    /// Creates a forward (0.0, 0.0, 1.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::forward(), Vector { x: 0.0, y: 0.0, z: 1.0 });
    /// ```
    pub fn forward() -> Vector {
        Vector { x: 0.0, y: 0.0, z: 1.0 }
    }

    /// Creates a left (-1.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::left(), Vector { x: -1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn left() -> Vector {
        Vector { x: -1.0, y: 0.0, z: 0.0 }
    }

    /// Creates a right (1.0, 0.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::right(), Vector { x: 1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn right() -> Vector {
        Vector { x: 1.0, y: 0.0, z: 0.0 }
    }

    /// Creates an up (0.0, 1.0, 0.0) Vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// assert_eq!(Vector::up(), Vector { x: 0.0, y: 1.0, z: 0.0 });
    /// ```
    pub fn up() -> Vector {
        Vector { x: 0.0, y: 1.0, z: 0.0 }
    }

    /// Computes the length of a vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(1.0, 2.0, 2.0);
    ///
    /// assert_eq!(v.length(), 3.0);
    /// ```
    pub fn length(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
    }

    /// Computes the normalized version of a vector.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v = Vector::new(1.0, 2.0, 2.0);
    /// let n = v.norm();
    ///
    /// assert_eq!(n.length(), 1.0); // Keep precision in mind when comparing floats.
    /// ```
    pub fn norm(&self) -> Vector {
        let length = self.length();

        Vector {
            x: self.x / length,
            y: self.y / length,
            z: self.z / length
        }
    }

    /// Computes the dot product between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(1.0, 2.0, 2.0);
    /// let v2 = Vector::new(3.0, 3.0, 1.0);
    ///
    /// assert_eq!(v1.dot(v2), 11.0);
    /// ```
    pub fn dot(&self, other: Vector) -> f32 {
        self.x * other.x +
        self.y * other.y +
        self.z * other.z
    }

    /// Computes the cross product between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(1.0, 2.0, 2.0);
    /// let v2 = Vector::new(3.0, 3.0, 1.0);
    ///
    /// assert_eq!(v1.cross(v2), Vector { x: -4.0, y: 5.0, z: -3.0 });
    /// ```
    pub fn cross(&self, other: Vector) -> Vector {
        Vector {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x
        }
    }

    /// Rotates a vector according to the rotation represented by the quaternion.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use anima::math::Quaternion;
    /// let q = Quaternion::new(0.0, 1.0, 0.0, 0.0);
    /// let v = Vector::new(1.0, 0.0, 0.0);
    ///
    /// assert_eq!(v.rot(q), Vector { x: -1.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn rot(&self, quaternion: Quaternion) -> Vector {
        let conjugate = quaternion.conj();
        let result = quaternion *
                     Quaternion::new(self.x, self.y, self.z, 0.0) *
                     conjugate;

        Vector { x: result.x, y: result.y, z: result.z }
    }

    /// Rotates a vector according to the rotation represented by the quaternion around a point.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use anima::math::Quaternion;
    /// let q = Quaternion::new(0.0, 1.0, 0.0, 0.0);
    /// let v = Vector::new(1.0, 0.0, 0.0);
    /// let p = Vector::new(2.0, 0.0, 0.0);
    ///
    /// assert_eq!(v.rot_around(q, p), Vector { x: 3.0, y: 0.0, z: 0.0 });
    /// ```
    pub fn rot_around(self, quaternion: Quaternion, point: Vector) -> Vector {
        (self - point).rot(quaternion) + point
    }

    /// Computes the angle in radians between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// # use std::f32::consts;
    /// let v1 = Vector::new(1.0, 0.0, 0.0);
    /// let v2 = Vector::new(0.0, 1.0, 0.0);
    ///
    /// assert_eq!(v1.angle(v2), consts::PI / 2.0);
    /// ```
    pub fn angle(&self, other: Vector) -> f32 {
        self.dot(other).acos()
    }

    /// Computes the distance between two vectors.
    ///
    /// # Example
    ///
    /// ```
    /// # use anima::math::Vector;
    /// let v1 = Vector::new(0.0, 0.0, 0.0);
    /// let v2 = Vector::new(0.0, 1.0, 0.0);
    ///
    /// assert_eq!(v1.dist(v2), 1.0);
    /// ```
    pub fn dist(self, other: Vector) -> f32 {
        (self - other).length()
    }
}

use std::ops::Add;
use std::ops::Sub;
use std::ops::Mul;
use std::ops::Neg;
use std::cmp::Ordering;

impl Add for Vector {
    type Output = Vector;

    fn add(self, other: Vector) -> Vector {
        Vector {
            x: self.x + other.x,
            y: self.y + other.y,
            z: self.z + other.z
        }
    }
}

impl Sub for Vector {
    type Output = Vector;

    fn sub(self, other: Vector) -> Vector {
        Vector {
            x: self.x - other.x,
            y: self.y - other.y,
            z: self.z - other.z
        }
    }
}

impl Mul<Vector> for Vector {
    type Output = Vector;

    fn mul(self, other: Vector) -> Vector {
        Vector {
            x: self.x * other.x,
            y: self.y * other.y,
            z: self.z * other.z
        }
    }
}

impl Mul<f32> for Vector {
    type Output = Vector;

    fn mul(self, scalar: f32) -> Vector {
        Vector {
            x: self.x * scalar,
            y: self.y * scalar,
            z: self.z * scalar
        }
    }
}

impl Mul<Vector> for f32 {
    type Output = Vector;

    fn mul(self, vector: Vector) -> Vector {
        Vector {
            x: vector.x * self,
            y: vector.y * self,
            z: vector.z * self
        }
    }
}

impl Neg for Vector {
    type Output = Vector;

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

impl PartialOrd for Vector {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.length().partial_cmp(&other.length())
    }
}
<|endoftext|>