<commit_before>mod error;
pub use self::error::Error;

pub type Result<T> = std::result::Result<T, Error>;

pub struct ViewHandle(u64);

pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

pub struct View {
    pub handle: ViewHandle,
    pub rect: Rect
}

pub enum Direction {
    Vertical,
    Horizontal,
}

pub struct Container {
    pub views: Vec<View>,
}

pub struct Split {
    pub split: Option<Box<Split>>,
    pub left_top: Container,
    pub right_bottom: Container,
    pub percent: f32,
    pub direction: Direction,
}

pub struct Workspace {
    pub split: Option<Split>,
    pub view: Option<View>,
    pub rect: Rect,
}

impl Rect {
    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Rect {
        Rect {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

impl Workspace {
    pub fn new(rect: Rect) -> Result<Workspace> {
        if rect.x < 0.0 {
            return Err(Error::IllegalSize("x has to be non-negative".to_owned()));
        }

        if rect.y < 0.0 {
            return Err(Error::IllegalSize("y has to be non-negative".to_owned()));
        }

        if rect.width <= 0.0 {
            return Err(Error::IllegalSize("width has to be larger than 0.0".to_owned()));
        }

        if rect.height <= 0.0 {
            return Err(Error::IllegalSize("height has to be larger than 0.0".to_owned()));
        }

        Ok(Workspace {
            split: None,
            view: None,
            rect: rect })
    }
}

#[cfg(test)]
mod test {
    use {Workspace, Rect};

    #[test]
    fn test_validate_x_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(-0.1, 0.0, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_y_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, -0.1, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, -1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, -1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_workspace_ok() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).is_ok(), true);
    }
}
<commit_msg>WIP on the system<commit_after>mod error;
pub use self::error::Error;

pub type Result<T> = std::result::Result<T, Error>;

pub struct ViewHandle(u64);

pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

impl Rect {
    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Rect {
        Rect {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

pub struct View {
    pub handle: ViewHandle,
    pub rect: Rect
}

pub enum Direction {
    Vertical,
    Horizontal,
    Full,
}

pub struct Container {
    pub views: Vec<View>,
}

pub struct Split {
    pub split: Option<Box<Split>>,
    pub left_top: Container,
    pub right_bottom: Container,
    pub percent: f32,
    pub direction: Direction,
}

pub struct Workspace {
    pub split: Option<Box<Split>>,
    pub rect: Rect,
}

impl Workspace {
    /// Construct a new workspace. The rect has to be y >= 0, x >= 0, width > 0 and height > 0
    pub fn new(rect: Rect) -> Result<Workspace> {
        if rect.x < 0.0 {
            return Err(Error::IllegalSize("x has to be non-negative".to_owned()));
        }

        if rect.y < 0.0 {
            return Err(Error::IllegalSize("y has to be non-negative".to_owned()));
        }

        if rect.width <= 0.0 {
            return Err(Error::IllegalSize("width has to be larger than 0.0".to_owned()));
        }

        if rect.height <= 0.0 {
            return Err(Error::IllegalSize("height has to be larger than 0.0".to_owned()));
        }

        Ok(Workspace {
            split: None,
            rect: rect })
    }
}

#[cfg(test)]
mod test {
    use {Workspace, Rect};

    #[test]
    fn test_validate_x_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(-0.1, 0.0, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_y_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, -0.1, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, -1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, -1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_workspace_ok() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).is_ok(), true);
    }
}
<|endoftext|>


<commit_before>// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]
#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain!{
        foreign_links {
            Io(::std::io::Error) #[cfg(unix)];
        }
    }
}
use errors::*;

extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

#[macro_use]
extern crate lazy_static;
extern crate regex;
use regex::Regex;

use std::fs::File;
use std::io::{Read, BufReader};
use std::io::{Write, BufWriter};

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// Read input from file or stdin
    ///
    /// # Examples
    /// ```
    /// ```
    pub fn get_input(&self, input_source: Option<&str>) -> Result<String> {
        let mut input_data = String::new();

        let mut input_file: File;
        let mut stdin = std::io::stdin();

        let reader: &mut Read = match input_source {
            Some(file_name) => {
                info!(self.logger, "Reading from file";
                      "file_name" => file_name);
                input_file = File::open(file_name)
                    .chain_err(|| format!("File \"{}\" not found", file_name))?;
                &mut input_file
            }
            None => {
                info!(self.logger, "Reading from stdin");
                &mut stdin
            }
        };
        let mut reader = BufReader::new(reader);
        reader
            .read_to_string(&mut input_data)
            .chain_err(|| "Could not read input")?;

        Ok(input_data)
    }

    /// Write output to file or stdout
    pub fn put_output(&self, output_dest: Option<&str>, output: Vec<String>) -> Result<()> {
        let mut stdout = std::io::stdout();
        let mut output_file: std::fs::File;

        let writer: &mut Write = match output_dest {
            Some(file_name) => {
                info!(self.logger, "Writing to file";
                      "file_name" => file_name);
                output_file = std::fs::OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(file_name)
                    .chain_err(|| format!("Could not open file \"{}\" to write", file_name))?;
                &mut output_file
            }
            None => {
                info!(self.logger, "Writing to stdout");
                // stdout.lock();
                &mut stdout
            }
        };

        let mut writer = BufWriter::new(writer);

        for o in output {
            writer
                .write_all(o.as_bytes())
                .chain_err(|| "Failed to write output")?;
        }

        writer.flush().chain_err(|| "Failed to write output")?;

        Ok(())
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// Inspire-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ADS-formatted BibTeX Key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{1998PhRvD..58h4020O}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("1998PhRvD..58h4020O"));
    /// ```
    ///
    /// ## biber
    ///
    /// Inspire-formatted BibLaTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            // TODO: check on the exact characters allowed in keys
            static ref AUX_REGEX: Regex = Regex::new(
                r"(\\citation|\\abx@aux@cite)\{(.+)\}").expect("aux regex compiled during development");
        }

        AUX_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// The blg2key function extracts missing references from bibtex logs
    ///
    /// # Examples
    ///
    /// ADS-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r##"
    /// This is BibTeX, Version 0.99d (TeX Live 2016/Arch Linux)
    /// Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
    /// The top-level auxiliary file: test_bibtex.aux
    /// The style file: unsrt.bst
    /// Database file #1: test_bibtex.bib
    /// Warning--I didn't find a database entry for "2015CQGra..32g4001L"
    /// You've used 0 entries,
    /// ....
    /// "##.to_string();
    ///
    /// assert_eq!(inspirer.blg2key(input), vec!("2015CQGra..32g4001L"));
    /// ```
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            static ref BLG_REGEX: Regex = Regex::new(
                r#"(Warning--|WARN - )I didn't find a database entry for ["'](.+)["']"#,
            ).expect("blg regex compiled during development");
        }

        BLG_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            Sources::Ads(k) => {
                debug!(self.logger, "Got ADS record"; "key" => k.bibcode);
                self.ads.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads(libads::BibCode<'a>),
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
///
/// ```
/// extern crate inspirer;
/// extern crate libads;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("1999PhRvL..83.3370R"),
///     inspirer::Sources::Ads(libads::BibCode::new("1999PhRvL..83.3370R").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else if libads::validate_bib_code(s) {
            Sources::Ads(libads::BibCode::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
            .to_string();

        assert_eq!(
            Inspirer::init(None).aux2key(input),
            vec!["Abramovici:1992ah"]
        );
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
            .to_string();

        assert_eq!(
            Inspirer::init(None).aux2key(input),
            vec!["Abramovici:1992ah", "Thorne:1992sdb"]
        );
    }
}
<commit_msg>fix: Clarify log info when parsing record type<commit_after>// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]
#[macro_use]
extern crate error_chain;

// We'll put our errors in an `errors` module, and other modules in
// this crate will `use errors::*;` to get access to everything
// `error_chain!` creates.
pub mod errors {
    // Create the Error, ErrorKind, ResultExt, and Result types
    error_chain!{
        foreign_links {
            Io(::std::io::Error) #[cfg(unix)];
        }
    }
}
use errors::*;

extern crate libinspire;
extern crate libads;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

#[macro_use]
extern crate lazy_static;
extern crate regex;
use regex::Regex;

use std::fs::File;
use std::io::{Read, BufReader};
use std::io::{Write, BufWriter};

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
    ads: libads::Api,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
            ads: libads::Api::init(None),
        }
    }

    /// Read input from file or stdin
    ///
    /// # Examples
    /// ```
    /// ```
    pub fn get_input(&self, input_source: Option<&str>) -> Result<String> {
        let mut input_data = String::new();

        let mut input_file: File;
        let mut stdin = std::io::stdin();

        let reader: &mut Read = match input_source {
            Some(file_name) => {
                info!(self.logger, "Reading from file";
                      "file_name" => file_name);
                input_file = File::open(file_name)
                    .chain_err(|| format!("File \"{}\" not found", file_name))?;
                &mut input_file
            }
            None => {
                info!(self.logger, "Reading from stdin");
                &mut stdin
            }
        };
        let mut reader = BufReader::new(reader);
        reader
            .read_to_string(&mut input_data)
            .chain_err(|| "Could not read input")?;

        Ok(input_data)
    }

    /// Write output to file or stdout
    pub fn put_output(&self, output_dest: Option<&str>, output: Vec<String>) -> Result<()> {
        let mut stdout = std::io::stdout();
        let mut output_file: std::fs::File;

        let writer: &mut Write = match output_dest {
            Some(file_name) => {
                info!(self.logger, "Writing to file";
                      "file_name" => file_name);
                output_file = std::fs::OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(file_name)
                    .chain_err(|| format!("Could not open file \"{}\" to write", file_name))?;
                &mut output_file
            }
            None => {
                info!(self.logger, "Writing to stdout");
                // stdout.lock();
                &mut stdout
            }
        };

        let mut writer = BufWriter::new(writer);

        for o in output {
            writer
                .write_all(o.as_bytes())
                .chain_err(|| "Failed to write output")?;
        }

        writer.flush().chain_err(|| "Failed to write output")?;

        Ok(())
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// Inspire-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ADS-formatted BibTeX Key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{1998PhRvD..58h4020O}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("1998PhRvD..58h4020O"));
    /// ```
    ///
    /// ## biber
    ///
    /// Inspire-formatted BibLaTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            // TODO: check on the exact characters allowed in keys
            static ref AUX_REGEX: Regex = Regex::new(
                r"(\\citation|\\abx@aux@cite)\{(.+)\}").expect("aux regex compiled during development");
        }

        AUX_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// The blg2key function extracts missing references from bibtex logs
    ///
    /// # Examples
    ///
    /// ADS-formatted BibTeX key:
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r##"
    /// This is BibTeX, Version 0.99d (TeX Live 2016/Arch Linux)
    /// Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
    /// The top-level auxiliary file: test_bibtex.aux
    /// The style file: unsrt.bst
    /// Database file #1: test_bibtex.bib
    /// Warning--I didn't find a database entry for "2015CQGra..32g4001L"
    /// You've used 0 entries,
    /// ....
    /// "##.to_string();
    ///
    /// assert_eq!(inspirer.blg2key(input), vec!("2015CQGra..32g4001L"));
    /// ```
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        lazy_static! {
            static ref BLG_REGEX: Regex = Regex::new(
                r#"(Warning--|WARN - )I didn't find a database entry for ["'](.+)["']"#,
            ).expect("blg regex compiled during development");
        }

        BLG_REGEX
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            // TODO just return the iterator: makes more sense with rayon
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = Sources::from(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Record type: Inspire"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            Sources::Ads(k) => {
                debug!(self.logger, "Record type: ADS"; "key" => k.bibcode);
                self.ads.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Record type: unknown");
                None
            }
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads(libads::BibCode<'a>),
    Arxiv,
    None,
}

/// Guess a likely source for a BibTeX key
///
/// Returns `Sources::None` if unable to make a good guess.
///
/// # Examples
/// ```
/// extern crate inspirer;
/// extern crate libinspire;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("Randall:1999ee"),
///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
/// );
/// ```
///
/// ```
/// extern crate inspirer;
/// extern crate libads;
/// let inspirer = inspirer::Inspirer::init(None);
///
/// assert_eq!(
///     inspirer::Sources::from("1999PhRvL..83.3370R"),
///     inspirer::Sources::Ads(libads::BibCode::new("1999PhRvL..83.3370R").unwrap())
/// );
/// ```
impl<'a> From<&'a str> for Sources<'a> {
    fn from(s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else if libads::validate_bib_code(s) {
            Sources::Ads(libads::BibCode::new(s).unwrap())
        } else {
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
            .to_string();

        assert_eq!(
            Inspirer::init(None).aux2key(input),
            vec!["Abramovici:1992ah"]
        );
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
            .to_string();

        assert_eq!(
            Inspirer::init(None).aux2key(input),
            vec!["Abramovici:1992ah", "Thorne:1992sdb"]
        );
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

/// POD (*plain old data*) type: scalar, fixed-size array or compound (struct).
/// May be arbitrarily nested.
#[derive(Clone, PartialEq, Debug)]
pub enum Type {
    /// 1-byte signed integer
    Int8,
    /// 2-byte signed integer
    Int16,
    /// 4-byte signed integer
    Int32,
    /// 8-byte signed integer
    Int64,
    /// pointer-sized signed integer
    ISize,
    /// 1-byte unsigned integer
    UInt8,
    /// 2-byte unsigned integer
    UInt16,
    /// 3-byte unsigned integer
    UInt32,
    /// 4-byte unsigned integer
    UInt64,
    /// pointer-sized unsigned integer
    USize,
    /// 4-byte floating-point number
    Float32,
    /// 8-byte floating-point number
    Float64,
    /// character type
    Char,
    /// 1-byte boolean type
    Bool,
    /// fixed-size array with POD elements
    Array(Box<Type>, usize),
    /// compound type whose fields are POD
    Compound(Vec<Field>, usize),
}

impl Type {
    /// Returns the total size of a type value in bytes.
    pub fn size(&self) -> usize {
        match *self {
            Type::Int8 | Type::UInt8 | Type::Bool => 1,
            Type::Int16 | Type::UInt16 => 2,
            Type::Int32 | Type::UInt32 | Type::Float32 => 4,
            Type::Int64 | Type::UInt64 | Type::Float64 => 8,
            Type::Char => ::std::mem::size_of::<char>(),
            Type::USize => ::std::mem::size_of::<usize>(),
            Type::ISize => ::std::mem::size_of::<isize>(),
            Type::Array(ref ty, num) => ty.size() * num,
            Type::Compound(_, size) => size,
        }
    }

    /// Returns true if the underlying type is a scalar.
    pub fn is_scalar(&self) -> bool {
        !self.is_array() && !self.is_compound()
    }

    /// Returns true if the underlying type is a fixed-size array.
    pub fn is_array(&self) -> bool {
        if let Type::Array(_, _) = *self { true } else { false }
    }

    /// Returns true if the underlying type is compound.
    pub fn is_compound(&self) -> bool {
        if let Type::Compound(_, _) = *self { true } else { false }
    }
}

/// Field of a compound type: type, name and offset from the beginning of the struct.
#[derive(Clone, PartialEq, Debug)]
pub struct Field {
    /// field value type
    pub ty: Type,
    /// field name
    pub name: String,
    /// offset to the beginning of the struct
    pub offset: usize,
}

impl Field {
    pub fn new<S, U>(ty: &Type, name: S, offset: U) -> Field
    where S: Into<String>, U: Into<usize> {
        Field {
            ty: ty.clone(),
            name: name.into(),
            offset: offset.into()
        }
    }
}

pub trait TypeInfo: Copy {
    /// Returns the runtime type information for the implementing type.
    fn type_info() -> Type;
}

macro_rules! impl_scalar {
    ($t:ty, $i:ident) => (
        impl $crate::TypeInfo for $t {
            #[inline(always)]
            fn type_info() -> $crate::Type {
                $crate::Type::$i
            }
        }
    )
}

// implement TypeInfo for built-in scalar types
impl_scalar!(i8, Int8);
impl_scalar!(i16, Int16);
impl_scalar!(i32, Int32);
impl_scalar!(i64, Int64);
impl_scalar!(isize, ISize);
impl_scalar!(u8, UInt8);
impl_scalar!(u16, UInt16);
impl_scalar!(u32, UInt32);
impl_scalar!(u64, UInt64);
impl_scalar!(usize, USize);
impl_scalar!(f32, Float32);
impl_scalar!(f64, Float64);
impl_scalar!(char, Char);
impl_scalar!(bool, Bool);

macro_rules! impl_array {
    ($($n:expr),*$(,)*) => {
        $(
            impl<T: $crate::TypeInfo> $crate::TypeInfo for [T; $n] {
                #[inline(always)]
                fn type_info() -> $crate::Type {
                    $crate::Type::Array(
                        Box::new(<T as $crate::TypeInfo>::type_info()),
                        $n
                    )
                }
            }
        )*
    };
}

// implement TypeInfo for fixed-size arrays of lengths 0..63
impl_array!(
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
);

#[macro_export]
macro_rules! def {
    // private struct, private fields
    ($($(#[$attr:meta])* struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, private fields
    ($($(#[$attr:meta])* pub struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, public fields
    ($($(#[$attr:meta])* pub struct $s:ident { $(pub $i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { pub $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // implement TypeInfo trait
    (@impl $s:ident { $($i:ident: $t:ty),+ }) => (
        impl $crate::TypeInfo for $s {
            fn type_info() -> $crate::Type {
                let base = 0usize as *const $s;
                $crate::Type::Compound(vec![$(
                    $crate::Field::new(
                        &<$t as $crate::TypeInfo>::type_info(),
                        stringify!($i),
                        unsafe { &((*base).$i) as *const $t as usize}
                    )
                ),*], ::std::mem::size_of::<$s>())
            }
        }
    );
}

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

    def! {
        #[derive(Debug)]
        pub struct Foo {
            pub a: bool,
            pub b: i32,
        }

        pub struct Bar {
            pub foo: [Foo; 2],
            pub s: f64
        }
    }

    #[test]
    fn test_smoke() {
        println!("{:#?}", Bar::type_info());
    }
}
<commit_msg>Size of char in Rust is always 4<commit_after>#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

/// POD (*plain old data*) type: scalar, fixed-size array or compound (struct).
/// May be arbitrarily nested.
#[derive(Clone, PartialEq, Debug)]
pub enum Type {
    /// 1-byte signed integer
    Int8,
    /// 2-byte signed integer
    Int16,
    /// 4-byte signed integer
    Int32,
    /// 8-byte signed integer
    Int64,
    /// pointer-sized signed integer
    ISize,
    /// 1-byte unsigned integer
    UInt8,
    /// 2-byte unsigned integer
    UInt16,
    /// 3-byte unsigned integer
    UInt32,
    /// 4-byte unsigned integer
    UInt64,
    /// pointer-sized unsigned integer
    USize,
    /// 4-byte floating-point number
    Float32,
    /// 8-byte floating-point number
    Float64,
    /// character type
    Char,
    /// 1-byte boolean type
    Bool,
    /// fixed-size array with POD elements
    Array(Box<Type>, usize),
    /// compound type whose fields are POD
    Compound(Vec<Field>, usize),
}

impl Type {
    /// Returns the total size of a type value in bytes.
    pub fn size(&self) -> usize {
        match *self {
            Type::Int8 | Type::UInt8 | Type::Bool => 1,
            Type::Int16 | Type::UInt16 => 2,
            Type::Int32 | Type::UInt32 | Type::Float32 | Type::Char => 4,
            Type::Int64 | Type::UInt64 | Type::Float64 => 8,
            Type::USize => ::std::mem::size_of::<usize>(),
            Type::ISize => ::std::mem::size_of::<isize>(),
            Type::Array(ref ty, num) => ty.size() * num,
            Type::Compound(_, size) => size,
        }
    }

    /// Returns true if the underlying type is a scalar.
    pub fn is_scalar(&self) -> bool {
        !self.is_array() && !self.is_compound()
    }

    /// Returns true if the underlying type is a fixed-size array.
    pub fn is_array(&self) -> bool {
        if let Type::Array(_, _) = *self { true } else { false }
    }

    /// Returns true if the underlying type is compound.
    pub fn is_compound(&self) -> bool {
        if let Type::Compound(_, _) = *self { true } else { false }
    }
}

/// Field of a compound type: type, name and offset from the beginning of the struct.
#[derive(Clone, PartialEq, Debug)]
pub struct Field {
    /// field value type
    pub ty: Type,
    /// field name
    pub name: String,
    /// offset to the beginning of the struct
    pub offset: usize,
}

impl Field {
    pub fn new<S, U>(ty: &Type, name: S, offset: U) -> Field
    where S: Into<String>, U: Into<usize> {
        Field {
            ty: ty.clone(),
            name: name.into(),
            offset: offset.into()
        }
    }
}

pub trait TypeInfo: Copy {
    /// Returns the runtime type information for the implementing type.
    fn type_info() -> Type;
}

macro_rules! impl_scalar {
    ($t:ty, $i:ident) => (
        impl $crate::TypeInfo for $t {
            #[inline(always)]
            fn type_info() -> $crate::Type {
                $crate::Type::$i
            }
        }
    )
}

// implement TypeInfo for built-in scalar types
impl_scalar!(i8, Int8);
impl_scalar!(i16, Int16);
impl_scalar!(i32, Int32);
impl_scalar!(i64, Int64);
impl_scalar!(isize, ISize);
impl_scalar!(u8, UInt8);
impl_scalar!(u16, UInt16);
impl_scalar!(u32, UInt32);
impl_scalar!(u64, UInt64);
impl_scalar!(usize, USize);
impl_scalar!(f32, Float32);
impl_scalar!(f64, Float64);
impl_scalar!(char, Char);
impl_scalar!(bool, Bool);

macro_rules! impl_array {
    ($($n:expr),*$(,)*) => {
        $(
            impl<T: $crate::TypeInfo> $crate::TypeInfo for [T; $n] {
                #[inline(always)]
                fn type_info() -> $crate::Type {
                    $crate::Type::Array(
                        Box::new(<T as $crate::TypeInfo>::type_info()),
                        $n
                    )
                }
            }
        )*
    };
}

// implement TypeInfo for fixed-size arrays of lengths 0..63
impl_array!(
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
);

#[macro_export]
macro_rules! def {
    // private struct, private fields
    ($($(#[$attr:meta])* struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, private fields
    ($($(#[$attr:meta])* pub struct $s:ident { $($i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // public struct, public fields
    ($($(#[$attr:meta])* pub struct $s:ident { $(pub $i:ident: $t:ty),+$(,)* })*) => (
        $(
            #[allow(dead_code)]
            #[derive(Clone, Copy)]
            $(#[$attr])*
            pub struct $s { pub $($i: $t),* }
            def!(@impl $s { $($i: $t),+ } );
        )*
    );

    // implement TypeInfo trait
    (@impl $s:ident { $($i:ident: $t:ty),+ }) => (
        impl $crate::TypeInfo for $s {
            fn type_info() -> $crate::Type {
                let base = 0usize as *const $s;
                $crate::Type::Compound(vec![$(
                    $crate::Field::new(
                        &<$t as $crate::TypeInfo>::type_info(),
                        stringify!($i),
                        unsafe { &((*base).$i) as *const $t as usize}
                    )
                ),*], ::std::mem::size_of::<$s>())
            }
        }
    );
}

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

    def! {
        #[derive(Debug)]
        pub struct Foo {
            pub a: bool,
            pub b: i32,
        }

        pub struct Bar {
            pub foo: [Foo; 2],
            pub s: f64
        }
    }

    #[test]
    fn test_smoke() {
        println!("{:#?}", Bar::type_info());
    }
}
<|endoftext|>


<commit_before>//! Preferred system exit codes as defined by sysexits.h
//!
//! Exit code constants intended to be passed to
//! `std::env::set_exit_status!()` or `std::process::exit()`
//!
//! # Example:
//! ```
//! use exitcode;
//!
//! ::std::process::exit(exitcode::OK);
//! ```

/// Successful exit
pub const OK: i32 = 0;

/// The command was used incorrectly, e.g., with the
/// wrong number of arguments, a bad flag, a bad syntax
/// in a parameter, etc.
pub const USAGE: i32 = 64;

/// The input data was incorrect in some way.  This
/// should only be used for user's data and not system
/// files.
pub const DATAERR: i32 = 65;

/// An input file (not a system file) did not exist or
/// was not readable.  This could also include errors
/// like "No message" to a mailer (if it cared to
/// catch it).
pub const NOINPUT: i32 = 66;

/// The user specified did not exist.  This might be
/// used for mail addresses or remote logins.
pub const NOUSER: i32 = 67;

/// The host specified did not exist.  This is used in
/// mail addresses or network requests.
pub const NOHOST: i32 = 68;

/// A service is unavailable.  This can occur if a sup
/// port program or file does not exist.  This can also
/// be used as a catchall message when something you
/// wanted to do doesn't work, but you don't know why.
pub const UNAVAILABLE: i32 = 69;

/// An internal software error has been detected.  This
/// should be limited to non-operating system related
/// errors as possible.
pub const SOFTWARE: i32 = 70;

/// An operating system error has been detected.  This
/// is intended to be used for such things as "cannot
/// fork", "cannot create pipe", or the like.  It
/// includes things like getuid returning a user that
/// does not exist in the passwd file.
pub const OSERR: i32 = 71;

/// Some system file (e.g., /etc/passwd, /var/run/utmp,
/// etc.) does not exist, cannot be opened, or has some
/// sort of error (e.g., syntax error).
pub const OSFILE: i32 = 72;

/// A (user specified) output file cannot be created.
pub const CANTCREAT: i32 = 73;

/// An error occurred while doing I/O on some file.
pub const IOERR: i32 = 74;

/// Temporary failure, indicating something that is not
/// really an error.  In sendmail, this means that a
/// mailer (e.g.) could not create a connection, and
/// the request should be reattempted later.
pub const TEMPFAIL: i32 = 75;

/// The remote system returned something that was
/// "not possible" during a protocol exchange.
pub const PROTOCOL: i32 = 76;

/// You did not have sufficient permission to perform
/// the operation.  This is not intended for file system
/// problems, which should use `NOINPUT` or `CANTCREAT`,
/// but rather for higher level permissions.
pub const NOPERM: i32 = 77;

/// Something was found in an unconfigured or misconfigured state.
pub const CONFIG: i32 = 78;

/// Check if exit code given by `code` is successful
///
/// # Example:
/// ```
/// use exitcode;
/// assert!(exitcode::is_success(exitcode::OK));
/// assert!(!exitcode::is_success(exitcode::USAGE));
/// ```
pub fn is_success(code: i32) -> bool {
    code == OK
}

/// Check if exit code given by `code` is an error
///
/// # Example:
/// ```
/// use exitcode;
/// assert!(exitcode::is_error(exitcode::USAGE));
/// assert!(!exitcode::is_error(exitcode::OK));
/// ```
pub fn is_error(code: i32) -> bool {
    !is_success(code)
}
<commit_msg>Remove bogus whitespace<commit_after>//! Preferred system exit codes as defined by sysexits.h
//!
//! Exit code constants intended to be passed to
//! `std::env::set_exit_status!()` or `std::process::exit()`
//!
//! # Example:
//! ```
//! use exitcode;
//!
//! ::std::process::exit(exitcode::OK);
//! ```

/// Successful exit
pub const OK: i32 = 0;

/// The command was used incorrectly, e.g., with the
/// wrong number of arguments, a bad flag, a bad syntax
/// in a parameter, etc.
pub const USAGE: i32 = 64;

/// The input data was incorrect in some way.  This
/// should only be used for user's data and not system
/// files.
pub const DATAERR: i32 = 65;

/// An input file (not a system file) did not exist or
/// was not readable.  This could also include errors
/// like "No message" to a mailer (if it cared to
/// catch it).
pub const NOINPUT: i32 = 66;

/// The user specified did not exist.  This might be
/// used for mail addresses or remote logins.
pub const NOUSER: i32 = 67;

/// The host specified did not exist.  This is used in
/// mail addresses or network requests.
pub const NOHOST: i32 = 68;

/// A service is unavailable.  This can occur if a
/// support program or file does not exist. This can also
/// be used as a catchall message when something you
/// wanted to do doesn't work, but you don't know why.
pub const UNAVAILABLE: i32 = 69;

/// An internal software error has been detected.  This
/// should be limited to non-operating system related
/// errors as possible.
pub const SOFTWARE: i32 = 70;

/// An operating system error has been detected.  This
/// is intended to be used for such things as "cannot
/// fork", "cannot create pipe", or the like.  It
/// includes things like getuid returning a user that
/// does not exist in the passwd file.
pub const OSERR: i32 = 71;

/// Some system file (e.g., /etc/passwd, /var/run/utmp,
/// etc.) does not exist, cannot be opened, or has some
/// sort of error (e.g., syntax error).
pub const OSFILE: i32 = 72;

/// A (user specified) output file cannot be created.
pub const CANTCREAT: i32 = 73;

/// An error occurred while doing I/O on some file.
pub const IOERR: i32 = 74;

/// Temporary failure, indicating something that is not
/// really an error.  In sendmail, this means that a
/// mailer (e.g.) could not create a connection, and
/// the request should be reattempted later.
pub const TEMPFAIL: i32 = 75;

/// The remote system returned something that was
/// "not possible" during a protocol exchange.
pub const PROTOCOL: i32 = 76;

/// You did not have sufficient permission to perform
/// the operation.  This is not intended for file system
/// problems, which should use `NOINPUT` or `CANTCREAT`,
/// but rather for higher level permissions.
pub const NOPERM: i32 = 77;

/// Something was found in an unconfigured or misconfigured state.
pub const CONFIG: i32 = 78;

/// Check if exit code given by `code` is successful
///
/// # Example:
/// ```
/// use exitcode;
/// assert!(exitcode::is_success(exitcode::OK));
/// assert!(!exitcode::is_success(exitcode::USAGE));
/// ```
pub fn is_success(code: i32) -> bool {
    code == OK
}

/// Check if exit code given by `code` is an error
///
/// # Example:
/// ```
/// use exitcode;
/// assert!(exitcode::is_error(exitcode::USAGE));
/// assert!(!exitcode::is_error(exitcode::OK));
/// ```
pub fn is_error(code: i32) -> bool {
    !is_success(code)
}
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::STD_INPUT_HANDLE,
    };

    unsafe {
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                kernel32::GetConsoleMode(kernel32::GetStdHandle(winapi::STD_INPUT_HANDLE),
                                         &mut out) != 0
            }
            out => {
                let name = match out {
                    Stream::Stdout => b"CONOUT$\0",
                    Stream::Stderr => b"CONERR$\0",
                    _ => unreachable!(),
                };
                let handle = kernel32::CreateFileA(name.as_ptr() as *const i8,
                                                   winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                                                   winapi::FILE_SHARE_WRITE,
                                                   ptr::null_mut(),
                                                   winapi::OPEN_EXISTING,
                                                   0,
                                                   ptr::null_mut());
                // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
                let mut buffer_info = ::std::mem::uninitialized();
                let ret = kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer_info);
                let last_err = kernel32::GetLastError();
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                       winapi::INVALID_HANDLE_VALUE == std_handle,
                       ret,
                       last_err);
                ret != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<commit_msg>qualify<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::STD_INPUT_HANDLE,
    };

    unsafe {
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                kernel32::GetConsoleMode(kernel32::GetStdHandle(winapi::STD_INPUT_HANDLE),
                                         &mut out) != 0
            }
            out => {
                let name = match out {
                    Stream::Stdout => b"CONOUT$\0",
                    Stream::Stderr => b"CONERR$\0",
                    _ => unreachable!(),
                };
                let handle = kernel32::CreateFileA(name.as_ptr() as *const i8,
                                                   winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                                                   winapi::FILE_SHARE_WRITE,
                                                   ptr::null_mut(),
                                                   winapi::OPEN_EXISTING,
                                                   0,
                                                   ::std::ptr::null_mut());
                // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
                let mut buffer_info = ::std::mem::uninitialized();
                let ret = kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer_info);
                let last_err = kernel32::GetLastError();
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                       winapi::INVALID_HANDLE_VALUE == handle,
                       ret,
                       last_err);
                ret != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<|endoftext|>


<commit_before>/// for HTTPS
extern crate hyper;
/// to decode JSON data
extern crate rustc_serialize;

static TESTAPIKEY: &'static str = "YOUR API KEY FROM themoviedb.org";

pub mod themoviedb_api {
	use std::fmt;
	use std::io::Read;
	use std::result::{Result};
	use rustc_serialize::json::{Json, Object};
	use hyper;

	/// the struct to keep
	pub struct TheMovieDB {
		/// the all mighty api key we need for each request
		api_key: &'static str,
		/// the base url for themoviedb.org
		base_url: &'static str,
		/// the base url for all images, comes from the /configuration URL
		image_base_url: String,
		/// the HTTPS client we use for getting data from the API
		http_client: hyper::Client,
	}

	#[derive(Default)]
	#[derive(Debug)]
	pub struct TheMovieDBMovie {
		pub title: Option<String>,
		pub original_title: Option<String>
	}

	pub enum TheMovieDBItem {
		Movie(TheMovieDBMovie),
		TVShow {original_title: String}
	}

	impl fmt::Debug for TheMovieDB {
	    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        write!(f, "TheMovieDB => ApiKey: {}, BaseURL: {}, ImageBaseURL: {}",
			 self.api_key,
			 self.base_url,
			 self.image_base_url)
	    }
	}

	impl TheMovieDB {
		/// Constructs a new TheMovieDB instance.
		///
		pub fn new(themoviedb_api_key: &'static str) -> Result<TheMovieDB, String> {
			let mut new_instance = TheMovieDB{api_key: themoviedb_api_key,
				base_url: "https://api.themoviedb.org/3",
				image_base_url: "".to_string(),
				http_client: hyper::Client::new()};

			let configuration_data = try!(new_instance.get_json_data_for("/configuration".to_string()));

			let json_obj = match configuration_data.as_object() {
				Some(o) => o,
				None => return Err("Error while getting JSON object".to_string())
			};

			new_instance.image_base_url = json_obj.get("images").unwrap().as_object().unwrap().get("secure_base_url").unwrap().to_string();

			Ok(new_instance)
		}

		pub fn search(& self, search_term: &'static str, maximum_results: usize) -> Result<Vec<TheMovieDBItem>, String> {
			// we start at the first page
			let mut page = 1;

			// find the higher number between number of results
			// requested and number returned from API
			let mut final_maximum_results = maximum_results;

			// here we save all results and return them
			let mut results: Vec<TheMovieDBItem> = vec![];

			// now loop until we have enough results
			// or if there aren't anymore
			loop {
				// download data
				let search_data = try!(self.get_json_data_for(format!("/search/multi?query={}&page={}", search_term, page)));

				// create a JSON object from the result
				let json_object = match search_data.as_object() {
					Some(o) => o,
					None => return Err("JSON Data is no object".to_string())
				};

				// get the total number of results
				let search_totals = match TheMovieDB::get_object_field_as_u64(json_object, "total_results") {
					Some(r) => r as usize,
					None => return Err("No results returned".to_string())
				};

				// get the total number of pages
				let page_totals = match TheMovieDB::get_object_field_as_u64(json_object, "total_pages") {
					Some(r) => r as usize,
					None => return Err("No page results returned".to_string())
				};

				if final_maximum_results > search_totals {
					final_maximum_results = search_totals;
				}

				// get the total number of results
				let search_results_json = match json_object.get("results") {
					Some(r) => r,
					None => return Err("No results returned".to_string())
				};

				let search_results = match search_results_json.as_array() {
					Some(r) => r,
					None => return Err("total_results not a number?!?!?".to_string())
				};

				for search_result in search_results {
					let result_object = match search_result.as_object() {
						Some(r) => r,
						None => continue
					};

					let mut new_movie: TheMovieDBMovie = Default::default();
					new_movie.original_title = TheMovieDB::get_object_field_as_string(result_object, "original_title");
					new_movie.title = TheMovieDB::get_object_field_as_string(result_object, "title");
					results.push(TheMovieDBItem::Movie(new_movie));

					if results.len() == final_maximum_results {
						return Ok(results);
					}
				}

				if page >= page_totals {
					return Ok(results);
				}

				page += 1;
			};
		}

		fn get_object_field_as_string(json_object: &Object, field_name: &'static str) -> Option<String> {
			let field = match json_object.get(field_name) {
				Some(f) => f,
				None => return None
			};

			let field_value = match field.as_string() {
				Some(v) => v,
				None => return None
			};

			Some(field_value.to_string())
		}

		fn get_object_field_as_u64(json_object: &Object, field_name: &'static str) -> Option<u64> {
			let field = match json_object.get(field_name) {
				Some(f) => f,
				None => return None
			};

			let field_value = match field.as_u64() {
				Some(v) => v,
				None => return None
			};

			Some(field_value)
		}

		/// Returns a URL as String for the given API method
		///
		/// It also automatically adds the api key
		fn get_url_for(& self, url_string: String) -> Result<hyper::Url, String> {
			if url_string.contains("?") {
				let result_url = match hyper::Url::parse(&format!("{}{}&api_key={}", self.base_url, url_string, self.api_key)) {
					Ok(u) => u,
					Err(_) => return Err(format!("Error buildign URL"))
				};
				Ok(result_url)
			 } else {
				 let result_url = match hyper::Url::parse(&format!("{}{}?api_key={}", self.base_url, url_string, self.api_key)) {
	 				Ok(u) => u,
	 				Err(_) => return Err(format!("Error buildign URL"))
	 			};
	 			Ok(result_url)
			}
		}

		/// Returns the data for a given API method or an error string if something has failed
		fn get_json_data_for(& self, url_string: String) -> Result<Json, String> {
			let call_url = try!(self.get_url_for(url_string));

			let call_url_string = format!("{}", call_url);
			let mut response = match self.http_client.get(call_url).send() {
				Ok(r) => r,
				Err(_) => {
					return Err(format!("Error during HTTPS request with URL {}", call_url_string));
				}
	 		};

			if hyper::Ok != response.status {
				return Err(format!("No HTTPS Status 200 (OK) for url: {}", call_url_string));
			}

			let mut result = String::new();
			if response.read_to_string(& mut result).is_err() {
				return Err("Error reading response".to_string());
			}

			let json_data = match Json::from_str(&result) {
				Ok(d) => d,
				Err(_) => return Err("Error while readin JSON data".to_string())
			};

			Ok(json_data)
		}
	}
}

// #[test]
// fn initialization_test() {
// 	TheMovieDB::new(TESTAPIKEY).unwrap();
// }

#[test]
fn search_test() {
	let themoviedb = themoviedb_api::TheMovieDB::new(TESTAPIKEY).unwrap();
	let search_result = themoviedb.search("Tinker Bell", 25).unwrap();

//	assert!(303 == search_result.len());

	for item in search_result {
		match item {
			themoviedb_api::TheMovieDBItem::Movie(movie) => {
				if movie.title.is_some() {
					println!("Found movie: {}", movie.title.unwrap());
				}
				if movie.original_title.is_some() {
					println!("Found original movie: {}", movie.original_title.unwrap());
				}
			},
			_ => continue
		}
	}
}
<commit_msg>Formatted using rustfmt<commit_after>/// for HTTPS
extern crate hyper;
/// to decode JSON data
extern crate rustc_serialize;

static TESTAPIKEY: &'static str = "YOUR API KEY FROM themoviedb.org";

pub mod themoviedb_api {
    use std::fmt;
    use std::io::Read;
    use std::result::Result;
    use rustc_serialize::json::{Json, Object};
    use hyper;

    /// the struct to keep
    pub struct TheMovieDB {
        /// the all mighty api key we need for each request
        api_key: &'static str,
        /// the base url for themoviedb.org
        base_url: &'static str,
        /// the base url for all images, comes from the /configuration URL
        image_base_url: String,
        /// the HTTPS client we use for getting data from the API
        http_client: hyper::Client,
    }

    #[derive(Default)]
    #[derive(Debug)]
    pub struct TheMovieDBMovie {
        pub title: Option<String>,
        pub original_title: Option<String>,
    }

    pub enum TheMovieDBItem {
        Movie(TheMovieDBMovie),
        TVShow {
            original_title: String,
        },
    }

    impl fmt::Debug for TheMovieDB {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f,
                   "TheMovieDB => ApiKey: {}, BaseURL: {}, ImageBaseURL: {}",
                   self.api_key,
                   self.base_url,
                   self.image_base_url)
        }
	}

    impl TheMovieDB {
        /// Constructs a new TheMovieDB instance.
        ///
        pub fn new(themoviedb_api_key: &'static str) -> Result<TheMovieDB, String> {
            let mut new_instance = TheMovieDB {
                api_key: themoviedb_api_key,
                base_url: "https://api.themoviedb.org/3",
                image_base_url: "".to_string(),
                http_client: hyper::Client::new(),
            };

            let configuration_data = try!(new_instance.get_json_data_for("/configuration"
                                                                             .to_string()));

            let json_obj = match configuration_data.as_object() {
                Some(o) => o,
                None => return Err("Error while getting JSON object".to_string()),
            };

            new_instance.image_base_url = json_obj.get("images")
                                                  .unwrap()
                                                  .as_object()
                                                  .unwrap()
                                                  .get("secure_base_url")
                                                  .unwrap()
                                                  .to_string();

            Ok(new_instance)
        }

        pub fn search(&self,
                      search_term: &'static str,
                      maximum_results: usize)
                      -> Result<Vec<TheMovieDBItem>, String> {
            // we start at the first page
            let mut page = 1;

            // find the higher number between number of results
            // requested and number returned from API
            let mut final_maximum_results = maximum_results;

            // here we save all results and return them
            let mut results: Vec<TheMovieDBItem> = vec![];

            // now loop until we have enough results
            // or if there aren't anymore
            loop {
                // download data
                let search_data = try!(self.get_json_data_for(format!("/search/multi?query={}&p\
                                                                       age={}",
                                                                      search_term,
                                                                      page)));

                // create a JSON object from the result
                let json_object = match search_data.as_object() {
                    Some(o) => o,
                    None => return Err("JSON Data is no object".to_string()),
                };

                // get the total number of results
                let search_totals = match TheMovieDB::get_object_field_as_u64(json_object,
                                                                              "total_results") {
                    Some(r) => r as usize,
                    None => return Err("No results returned".to_string()),
                };

                // get the total number of pages
                let page_totals = match TheMovieDB::get_object_field_as_u64(json_object,
                                                                            "total_pages") {
                    Some(r) => r as usize,
                    None => return Err("No page results returned".to_string()),
                };

                if final_maximum_results > search_totals {
                    final_maximum_results = search_totals;
                }

                // get the total number of results
                let search_results_json = match json_object.get("results") {
                    Some(r) => r,
                    None => return Err("No results returned".to_string()),
                };

                let search_results = match search_results_json.as_array() {
                    Some(r) => r,
                    None => return Err("total_results not a number?!?!?".to_string()),
                };

                for search_result in search_results {
                    let result_object = match search_result.as_object() {
                        Some(r) => r,
                        None => continue,
                    };

                    let mut new_movie: TheMovieDBMovie = Default::default();
                    new_movie.original_title =
                        TheMovieDB::get_object_field_as_string(result_object, "original_title");
                    new_movie.title = TheMovieDB::get_object_field_as_string(result_object,
                                                                             "title");
                    results.push(TheMovieDBItem::Movie(new_movie));

                    if results.len() == final_maximum_results {
                        return Ok(results);
                    }
                }

                if page >= page_totals {
                    return Ok(results);
                }

                page += 1;
            }
        }

        fn get_object_field_as_string(json_object: &Object,
                                      field_name: &'static str)
                                      -> Option<String> {
            let field = match json_object.get(field_name) {
                Some(f) => f,
                None => return None,
            };

            let field_value = match field.as_string() {
                Some(v) => v,
                None => return None,
            };

            Some(field_value.to_string())
        }

        fn get_object_field_as_u64(json_object: &Object, field_name: &'static str) -> Option<u64> {
            let field = match json_object.get(field_name) {
                Some(f) => f,
                None => return None,
            };

            let field_value = match field.as_u64() {
                Some(v) => v,
                None => return None,
            };

            Some(field_value)
        }

        /// Returns a URL as String for the given API method
        ///
        /// It also automatically adds the api key
        fn get_url_for(&self, url_string: String) -> Result<hyper::Url, String> {
            if url_string.contains("?") {
                let result_url = match hyper::Url::parse(&format!("{}{}&api_key={}",
                                                                  self.base_url,
                                                                  url_string,
                                                                  self.api_key)) {
                    Ok(u) => u,
                    Err(_) => return Err(format!("Error buildign URL")),
                };
                Ok(result_url)
            } else {
                let result_url = match hyper::Url::parse(&format!("{}{}?api_key={}",
                                                                  self.base_url,
                                                                  url_string,
                                                                  self.api_key)) {
                    Ok(u) => u,
                    Err(_) => return Err(format!("Error buildign URL")),
                };
                Ok(result_url)
            }
        }

        /// Returns the data for a given API method or an error string if something has failed
        fn get_json_data_for(&self, url_string: String) -> Result<Json, String> {
            let call_url = try!(self.get_url_for(url_string));

            let call_url_string = format!("{}", call_url);
            let mut response = match self.http_client.get(call_url).send() {
                Ok(r) => r,
                Err(_) => {
                    return Err(format!("Error during HTTPS request with URL {}", call_url_string));
                }
            };

            if hyper::Ok != response.status {
                return Err(format!("No HTTPS Status 200 (OK) for url: {}", call_url_string));
            }

            let mut result = String::new();
            if response.read_to_string(&mut result).is_err() {
                return Err("Error reading response".to_string());
            }

            let json_data = match Json::from_str(&result) {
                Ok(d) => d,
                Err(_) => return Err("Error while readin JSON data".to_string()),
            };

            Ok(json_data)
        }
	}
}

// #[test]
// fn initialization_test() {
// 	TheMovieDB::new(TESTAPIKEY).unwrap();
// }

#[test]
fn search_test() {
    let themoviedb = themoviedb_api::TheMovieDB::new(TESTAPIKEY).unwrap();
    let search_result = themoviedb.search("Tinker Bell", 25).unwrap();

    // assert!(303 == search_result.len());

    for item in search_result {
        match item {
            themoviedb_api::TheMovieDBItem::Movie(movie) => {
                if movie.title.is_some() {
                    println!("Found movie: {}", movie.title.unwrap());
                }
                if movie.original_title.is_some() {
                    println!("Found original movie: {}", movie.original_title.unwrap());
                }
            }
            _ => continue,
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ptr::null;
use std::ptr::null_mut;
use std::ffi::CString;

mod ffi {
    use libc::c_void;
    use libc::c_char;

    pub enum DNSService {}
    pub type DNSServiceRef = *mut DNSService;

    #[repr(i32)]
    #[allow(dead_code)]
    #[derive(Copy,Clone,Debug,PartialEq,Eq)]
    pub enum DNSServiceErrorType {
        NoError = 0,
        Unknown = -65537,
        NoSuchName = -65538,
        NoMemory = -65539,
        BadParam = -65540,
        BadReference = -65541,
        BadState = -65542,
        BadFlags = -65543,
        Unsupported = -65544,
        NotInitialized = -65545,
        AlreadyRegistered = -65547,
        NameConflict = -65548,
        Invalid = -65549,
        Firewall = -65550,
        Incompatible = -65551,
        BadInterfaceIndex = -65552,
        Refused = -65553,
        NoSuchRecord = -65554,
        NoAuth = -65555,
        NoSuchKey = -65556,
        NATTraversal = -65557,
        DoubleNAT = -65558,
        BadTime = -65559,
        BadSig = -65560,
        BadKey = -65561,
        Transient = -65562,
        ServiceNotRunning = -65563,
        NATPortMappingUnsupported = -65564,
        NATPortMappingDisabled = -65565,
        NoRouter = -65566,
        PollingMode = -65567,
        Timeout = -65568,
    }

    pub type DNSServiceFlags = u32;
    pub type DNSServiceRegisterReply = Option<extern "C" fn(DNSServiceRef,
                                                            DNSServiceFlags,
                                                            DNSServiceErrorType,
                                                            *const c_char,
                                                            *const c_char,
                                                            *const c_char,
                                                            *mut c_void)
                                                           >;

    extern "C" {
        pub fn DNSServiceRegister(sdRef: *mut DNSServiceRef,
                                  flags: DNSServiceFlags,
                                  interfaceIndex: u32,
                                  name: *const c_char,
                                  regtype: *const c_char,
                                  domain: *const c_char,
                                  host: *const c_char,
                                  port: u16,
                                  txtLen: u16,
                                  txtRecord: *const u8,
                                  callBack: DNSServiceRegisterReply,
                                  context: *mut c_void)
                                  -> DNSServiceErrorType;

        pub fn DNSServiceRefDeallocate(sdRef: DNSServiceRef);
    }
}

#[derive(Debug)]
pub struct DNSService {
    sd_ref: ffi::DNSServiceRef,
}

#[derive(Debug)]
pub struct DNSError(ffi::DNSServiceErrorType);

impl std::fmt::Display for DNSError {
    fn fmt(&self, format: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(format, "DNS-SD Error: {:?}", self.0)
    }
}

impl std::error::Error for DNSError {
    fn description(&self) -> &str {
        "DNS-SD Error"
    }
}

impl DNSService {
    pub fn register(name: Option<&str>,
                    regtype: &str,
                    domain: Option<&str>,
                    host: Option<&str>,
                    port: u16,
                    txt: &[&str])
                    -> std::result::Result<DNSService, DNSError> {
        let mut sd_ref: ffi::DNSServiceRef = null_mut();

        let txt_data: Vec<u8> = txt.into_iter()
                                   .flat_map(|value| {
                                       std::iter::once(value.len() as u8).chain(value.bytes())
                                   })
                                   .collect();

        let name = name.map(|s| CString::new(s).unwrap());
        let regtype = CString::new(regtype).unwrap();
        let domain = domain.map(|s| CString::new(s).unwrap());
        let host = host.map(|s| CString::new(s).unwrap());

        let err = unsafe {
            ffi::DNSServiceRegister(&mut sd_ref as *mut _,
                                    0,
                                    0,
                                    name.map_or(null(), |s| s.as_ptr()),
                                    regtype.as_ptr(),
                                    domain.map_or(null(), |s| s.as_ptr()),
                                    host.map_or(null(), |s| s.as_ptr()),
                                    port.to_be(),
                                    txt_data.len() as u16,
                                    if txt_data.len() == 0 {
                                        null()
                                    } else {
                                        txt_data.as_ptr()
                                    },
                                    None,
                                    null_mut())
        };

        if err == ffi::DNSServiceErrorType::NoError {
            Ok(DNSService { sd_ref: sd_ref })
        } else {
            Err(DNSError(err))
        }
    }
}

impl Drop for DNSService {
    fn drop(&mut self) {
        unsafe {
            ffi::DNSServiceRefDeallocate(self.sd_ref);
        }
    }
}
<commit_msg>Don’t move out the CStrings when calling map_or by calling by_ref first.<commit_after>extern crate libc;

use std::ptr::null;
use std::ptr::null_mut;
use std::ffi::CString;

mod ffi {
    use libc::c_void;
    use libc::c_char;

    pub enum DNSService {}
    pub type DNSServiceRef = *mut DNSService;

    #[repr(i32)]
    #[allow(dead_code)]
    #[derive(Copy,Clone,Debug,PartialEq,Eq)]
    pub enum DNSServiceErrorType {
        NoError = 0,
        Unknown = -65537,
        NoSuchName = -65538,
        NoMemory = -65539,
        BadParam = -65540,
        BadReference = -65541,
        BadState = -65542,
        BadFlags = -65543,
        Unsupported = -65544,
        NotInitialized = -65545,
        AlreadyRegistered = -65547,
        NameConflict = -65548,
        Invalid = -65549,
        Firewall = -65550,
        Incompatible = -65551,
        BadInterfaceIndex = -65552,
        Refused = -65553,
        NoSuchRecord = -65554,
        NoAuth = -65555,
        NoSuchKey = -65556,
        NATTraversal = -65557,
        DoubleNAT = -65558,
        BadTime = -65559,
        BadSig = -65560,
        BadKey = -65561,
        Transient = -65562,
        ServiceNotRunning = -65563,
        NATPortMappingUnsupported = -65564,
        NATPortMappingDisabled = -65565,
        NoRouter = -65566,
        PollingMode = -65567,
        Timeout = -65568,
    }

    pub type DNSServiceFlags = u32;
    pub type DNSServiceRegisterReply = Option<extern "C" fn(DNSServiceRef,
                                                            DNSServiceFlags,
                                                            DNSServiceErrorType,
                                                            *const c_char,
                                                            *const c_char,
                                                            *const c_char,
                                                            *mut c_void)
                                                           >;

    extern "C" {
        pub fn DNSServiceRegister(sdRef: *mut DNSServiceRef,
                                  flags: DNSServiceFlags,
                                  interfaceIndex: u32,
                                  name: *const c_char,
                                  regtype: *const c_char,
                                  domain: *const c_char,
                                  host: *const c_char,
                                  port: u16,
                                  txtLen: u16,
                                  txtRecord: *const u8,
                                  callBack: DNSServiceRegisterReply,
                                  context: *mut c_void)
                                  -> DNSServiceErrorType;

        pub fn DNSServiceRefDeallocate(sdRef: DNSServiceRef);
    }
}

#[derive(Debug)]
pub struct DNSService {
    sd_ref: ffi::DNSServiceRef,
}

#[derive(Debug)]
pub struct DNSError(ffi::DNSServiceErrorType);

impl std::fmt::Display for DNSError {
    fn fmt(&self, format: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(format, "DNS-SD Error: {:?}", self.0)
    }
}

impl std::error::Error for DNSError {
    fn description(&self) -> &str {
        "DNS-SD Error"
    }
}

impl DNSService {
    pub fn register(name: Option<&str>,
                    regtype: &str,
                    domain: Option<&str>,
                    host: Option<&str>,
                    port: u16,
                    txt: &[&str])
                    -> std::result::Result<DNSService, DNSError> {
        let mut sd_ref: ffi::DNSServiceRef = null_mut();

        let txt_data: Vec<u8> = txt.into_iter()
                                   .flat_map(|value| {
                                       std::iter::once(value.len() as u8).chain(value.bytes())
                                   })
                                   .collect();

        let name = name.map(|s| CString::new(s).unwrap());
        let regtype = CString::new(regtype).unwrap();
        let domain = domain.map(|s| CString::new(s).unwrap());
        let host = host.map(|s| CString::new(s).unwrap());

        let err = unsafe {
            ffi::DNSServiceRegister(&mut sd_ref as *mut _,
                                    0,
                                    0,
                                    name.as_ref().map_or(null(), |s| s.as_ptr()),
                                    regtype.as_ptr(),
                                    domain.as_ref().map_or(null(), |s| s.as_ptr()),
                                    host.as_ref().map_or(null(), |s| s.as_ptr()),
                                    port.to_be(),
                                    txt_data.len() as u16,
                                    if txt_data.is_empty() {
                                        null()
                                    } else {
                                        txt_data.as_ptr()
                                    },
                                    None,
                                    null_mut())
        };

        // We must be sure these stay are still alive during the DNSServiceRegister call
        // Because we pass them as raw pointers, rust's borrow checker is useless there
        // If they are still valid at this point, then we're good
        drop(name);
        drop(regtype);
        drop(domain);
        drop(host);
        drop(txt_data);

        if err == ffi::DNSServiceErrorType::NoError {
            Ok(DNSService { sd_ref: sd_ref })
        } else {
            Err(DNSError(err))
        }
    }
}

impl Drop for DNSService {
    fn drop(&mut self) {
        unsafe {
            ffi::DNSServiceRefDeallocate(self.sd_ref);
        }
    }
}
<|endoftext|>


<commit_before>//! Crate ruma_api contains core types used to define the requests and responses for each endpoint
//! in the various [Matrix](https://matrix.org) API specifications.
//! These types can be shared by client and server code for all Matrix APIs.
//!
//! When implementing a new Matrix API, each endpoint have a type that implements `Endpoint`, plus
//! any necessary associated types.
//! An implementation of `Endpoint` contains all the information about the HTTP method, the path and
//! input parameters for requests, and the structure of a successful response.
//! Such types can then be used by client code to make requests, and by server code to fulfill
//! those requests.
//!
//! # Example
//!
//! ```rust,no_run
//! # #![feature(proc_macro)]
//! #
//! # extern crate ruma_api;
//! # extern crate ruma_identifiers;
//! # #[macro_use]
//! # extern crate serde_derive;
//! #
//! # fn main() {
//! /// PUT /_matrix/client/r0/directory/room/:room_alias
//! pub mod create {
//!     use ruma_api;
//!     use ruma_identifiers::{RoomAliasId, RoomId};
//!
//!     /// This API endpoint's body parameters.
//!     #[derive(Clone, Debug, Deserialize, Serialize)]
//!     pub struct BodyParams {
//!         pub room_id: RoomId,
//!     }
//!
//!     /// This API endpoint's path parameters.
//!     pub struct PathParams {
//!         pub room_alias: RoomAliasId,
//!     }
//!
//!     /// Details about this API endpoint.
//!     pub struct Endpoint;
//!
//!     impl ruma_api::Endpoint for Endpoint {
//!         type BodyParams = BodyParams;
//!         type PathParams = PathParams;
//!         type QueryParams = ();
//!         type Response = ();
//!
//!         fn method() -> ruma_api::Method {
//!             ruma_api::Method::Put
//!         }
//!
//!         fn request_path(params: Self::PathParams) -> String {
//!             format!("/_matrix/client/r0/directory/room/{}", params.room_alias)
//!         }
//!
//!         fn router_path() -> String {
//!             "/_matrix/client/r0/directory/room/:room_alias".to_string()
//!         }
//!     }
//! }
//! # }

#![deny(missing_docs)]

extern crate serde;

use serde::{Deserialize, Serialize};

/// HTTP request methods used in Matrix APIs.
#[derive(Clone, Copy, Debug)]
pub enum Method {
    /// DELETE
    Delete,
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
}

/// An API endpoint.
pub trait Endpoint {
    /// Request parameters supplied via the body of the HTTP request.
    type BodyParams: Deserialize + Serialize;

    /// Request parameters supplied via the URL's path.
    type PathParams;

    /// Parameters supplied via the URL's query string.
    type QueryParams: Deserialize + Serialize;

    /// The body of the response.
    type Response: Deserialize + Serialize;

    /// Returns the HTTP method used by this endpoint.
    fn method() -> Method;

    /// Generates the path component of the URL for this endpoint using the supplied parameters.
    fn request_path(params: Self::PathParams) -> String;

    /// Generates a generic path component of the URL for this endpoint, suitable for `Router` from
    /// the router crate.
    fn router_path() -> String;
}
<commit_msg>Add flags and change String to &'static str<commit_after>//! Crate ruma_api contains core types used to define the requests and responses for each endpoint
//! in the various [Matrix](https://matrix.org) API specifications.
//! These types can be shared by client and server code for all Matrix APIs.
//!
//! When implementing a new Matrix API, each endpoint have a type that implements `Endpoint`, plus
//! any necessary associated types.
//! An implementation of `Endpoint` contains all the information about the HTTP method, the path and
//! input parameters for requests, and the structure of a successful response.
//! Such types can then be used by client code to make requests, and by server code to fulfill
//! those requests.
//!
//! # Example
//!
//! ```rust,no_run
//! # #![feature(proc_macro)]
//! #
//! # extern crate ruma_api;
//! # extern crate ruma_identifiers;
//! # #[macro_use]
//! # extern crate serde_derive;
//! #
//! # fn main() {
//! /// PUT /_matrix/client/r0/directory/room/:room_alias
//! pub mod create {
//!     use ruma_api;
//!     use ruma_identifiers::{RoomAliasId, RoomId};
//!
//!     /// This API endpoint's body parameters.
//!     #[derive(Clone, Debug, Deserialize, Serialize)]
//!     pub struct BodyParams {
//!         pub room_id: RoomId,
//!     }
//!
//!     /// This API endpoint's path parameters.
//!     #[derive(Clone, Debug)]
//!     pub struct PathParams {
//!         pub room_alias: RoomAliasId,
//!     }
//!
//!     /// Details about this API endpoint.
//!     pub struct Endpoint;
//!
//!     impl ruma_api::Endpoint for Endpoint {
//!         type BodyParams = BodyParams;
//!         type PathParams = PathParams;
//!         type QueryParams = ();
//!         type Response = ();
//!
//!         fn method() -> ruma_api::Method {
//!             ruma_api::Method::Put
//!         }
//!
//!         fn request_path(params: Self::PathParams) -> String {
//!             format!("/_matrix/client/r0/directory/room/{}", params.room_alias)
//!         }
//!
//!         fn router_path() -> &'static str {
//!             "/_matrix/client/r0/directory/room/:room_alias"
//!         }
//!
//!         fn name() -> &'static str {
//!             "room_directory"
//!         }
//!
//!         fn description() -> &'static str {
//!             "Matrix implementation of room directory."
//!         }
//!
//!         fn requires_authentication() -> bool {
//!             true
//!         }
//!
//!         fn rate_limited() -> bool {
//!             false
//!         }
//!     }
//! }
//! # }

#![deny(missing_docs)]

extern crate serde;

use serde::{Deserialize, Serialize};

/// HTTP request methods used in Matrix APIs.
#[derive(Clone, Copy, Debug)]
pub enum Method {
    /// DELETE
    Delete,
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
}

/// An API endpoint.
pub trait Endpoint {
    /// Request parameters supplied via the body of the HTTP request.
    type BodyParams: Deserialize + Serialize;

    /// Request parameters supplied via the URL's path.
    type PathParams;

    /// Parameters supplied via the URL's query string.
    type QueryParams: Deserialize + Serialize;

    /// The body of the response.
    type Response: Deserialize + Serialize;

    /// Returns the HTTP method used by this endpoint.
    fn method() -> Method;

    /// Generates the path component of the URL for this endpoint using the supplied parameters.
    fn request_path(params: Self::PathParams) -> String;

    /// Generates a generic path component of the URL for this endpoint, suitable for `Router` from
    /// the router crate.
    fn router_path() -> &'static str;

    /// A unique identifier for this endpoint, suitable for `Router` from the router crate.
    fn name() -> &'static str;

    /// A human-readable description of the endpoint.
    fn description() -> &'static str;

    /// Whether or not this endpoint requires an authenticated user.
    fn requires_authentication() -> bool;

    /// Whether or not this endpoint is rate limited.
    fn rate_limited() -> bool;
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

#[macro_use] extern crate enum_primitive;
extern crate num;
use num::traits::FromPrimitive;

#[macro_export]
macro_rules! strenum {
    ($e:ident => $( $t:ident ),*  ) => {
		enum_from_primitive! {
        #[derive(Debug)]
        enum $e { $($t,)* }
		}
        impl Strenum for $e {
            fn enumify(command: &str) -> Option<$e> {
                match command {
                    $( stringify!($t) => Some($e::$t), )*
                    _ => None
                }
            }

            fn stringify() -> String {
                let mut buf = Vec::<String>::new();
                let mut n: u8 = 0;

                while let Some(val) = <Self>::from_u8(n) {
                    buf.push(format!("{:?}", val));
                    n += 1;
                }

                buf.connect("\n")
            }
        }
    }
}

pub trait Strenum {
    fn enumify(command: &str) -> Option<Self>;
    fn stringify() -> String;
}

strenum! {
    testenum => a, b
}

#[test]
fn stringify() {
    assert_eq!(&*<testenum>::stringify(), "a\nb");
}

#[test]
fn enumify() {
    match <testenum>::enumify("b").unwrap() {
        testenum::b => "success",
        testenum::a => panic!("Got a instead of b"),
    };
}

<commit_msg>Fix warning<commit_after>#![allow(non_camel_case_types)]

#[macro_use] extern crate enum_primitive;
extern crate num;
use num::traits::FromPrimitive;

#[macro_export]
macro_rules! strenum {
    ($e:ident => $( $t:ident ),*  ) => {
		enum_from_primitive! {
        #[derive(Debug)]
        enum $e { $($t,)* }
		}
        impl Strenum for $e {
            fn enumify(command: &str) -> Option<$e> {
                match command {
                    $( stringify!($t) => Some($e::$t), )*
                    _ => None
                }
            }

            fn stringify() -> String {
                let mut buf = Vec::<String>::new();
                let mut n: u8 = 0;

                while let Some(val) = <Self>::from_u8(n) {
                    buf.push(format!("{:?}", val));
                    n += 1;
                }

                buf.join("\n")
            }
        }
    }
}

pub trait Strenum {
    fn enumify(command: &str) -> Option<Self>;
    fn stringify() -> String;
}

strenum! {
    testenum => a, b
}

#[test]
fn stringify() {
    assert_eq!(&*<testenum>::stringify(), "a\nb");
}

#[test]
fn enumify() {
    match <testenum>::enumify("b").unwrap() {
        testenum::b => "success",
        testenum::a => panic!("Got a instead of b"),
    };
}
<|endoftext|>


<commit_before>//! A simple library for reading and writing Riegl .sdc files.
//!
//! .sdc files are simple binary tables of discrete-return LiDAR data.

extern crate byteorder;

pub mod error;
pub mod file;
pub mod point;
mod result;

pub use file::File;
<commit_msg>Re-export Point<commit_after>//! A simple library for reading and writing Riegl .sdc files.
//!
//! .sdc files are simple binary tables of discrete-return LiDAR data.

extern crate byteorder;

pub mod error;
pub mod file;
pub mod point;
mod result;

pub use file::File;
pub use point::Point;
<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;
extern crate llvm;

#[macro_use]
extern crate util;

use llvm::*;
use llvm::Attribute::*;

use std::mem;

#[test]
pub fn test() {
  let ctx = Context::new();
  let module = Module::parse_bitcode(&ctx, "tests/test-module.bc").expect("loading test-module.bc failed...");
  module.verify().expect("verifying the module failed...");

  for x in module.into_iter() {
  	x.add_attribute(Attribute::AlwaysInline);
  }

  module.dump();

  let ee = JitEngine::new(&module, JitOptions {opt_level: 0}).unwrap();

  let func1 = ee.find_function("test_func1").expect("No such a function: test_func1");
	let f1: fn(f64) -> f64;
  f1 = match unsafe { ee.get_function_raw(func1) } {
  	Some(f) => unsafe { mem::transmute(f)},
  	_       => panic!("get_function_raw:: no such function" )
  };

  assert_eq!(98.0f64, f1(98.0f64));

  let func2 = ee.find_function("test_func2").expect("No such a function: test_func2");
	let f2: fn(f64) -> f64;
  f2 = match unsafe { ee.get_function_raw(func2) } {
  	Some(f) => unsafe { mem::transmute(f)},
  	_       => panic!("get_function_raw:: no such function" )
  };

  assert_eq!(98.0f64, f2(98.0f64));
}<commit_msg>Add an unit test to verify the function signature.<commit_after>#![feature(libc)]

extern crate libc;
extern crate llvm;

#[macro_use]
extern crate util;

use llvm::*;
use llvm::Attribute::*;

use std::mem;

fn test_func_find(name: &str, lang: &str) {
  let ctx = Context::new();
  let module = Module::parse_bitcode(&ctx, "tests/test-module.bc").expect("loading test-module.bc failed...");
  module.verify().expect("verifying the module failed...");

  for x in module.into_iter() {
  	x.add_attribute(Attribute::AlwaysInline);
  }

  let ee = JitEngine::new(&module, JitOptions {opt_level: 0}).unwrap();
  let func = ee.find_function(name).expect(&format!("find_function: couldn't find {} from {}", name, lang));
	let f: fn(f64) -> f64;
  f = match unsafe { ee.get_function_raw(func) } {
  	Some(f) => unsafe { mem::transmute(f)},
  	_       => panic!("get_function_raw: couldn't find {} from {}", name, lang)
  };

  assert_eq!(98.0f64, f(98.0f64));
}

#[test]
pub fn test_func_declaration() {
  let ctx = Context::new();
  let module = Module::parse_bitcode(&ctx, "tests/test-module.bc").expect("loading test-module.bc failed...");
  module.verify().expect("verifying the module failed...");

  for x in module.into_iter() {
  	x.add_attribute(Attribute::AlwaysInline);
  }

  let func = module.get_function("test_func1").unwrap();
  assert_eq!(1, func.num_params());

  let param = &func[0];
  assert_eq!(Type::get::<f64>(&ctx), param.get_type());
}

#[test]
pub fn test_c_func() {
  test_func_find("test_func1", "c");
}

#[test]
pub fn test_rust_func() {
  test_func_find("test_func2", "rust");
}<|endoftext|>