<commit_before>use std::convert::From;
use std::error::Error;
use std::fmt;
use std::num::ParseIntError;

use ansi_term::{ANSIString, Color, Style};

use util::Shell;

/// Representation of config options that all modules have
#[derive(Clone)]
pub struct ModuleOptions {
    /// String to display to the left of the content
    pub padding_left: String,
    /// String to display to the right of the content
    pub padding_right: String,
    /// String to print out after the content and right padding
    pub separator: String,
    /// Background color, foreground color, etc.
    pub style: ModuleStyle,
}

/// Representation of how to style a module
#[derive(Clone)]
pub struct ModuleStyle {
    /// Color behind the text
    pub background: Option<Color>,
    /// Color of the text
    pub foreground: Option<Color>,
    /// Optional combination of attributes like bold, italicized, etc.
    pub text_properties: Option<Style>,
}

/// Formats a string with the given `ModuleOptions` for a specific
/// `Shell`.
///
/// # Parameters
///
/// - `s` - the contents of the module to be formatted
/// - `options` - the background, foreground, padding, etc. to apply
/// - `next_bg` - the background color, if any, of the next visible module
/// - `shell` - the type of shell to format the string for
pub fn format_for_module(s: &str,
                         options: ModuleOptions,
                         next_bg: Option<Color>,
                         shell: Shell)
                         -> ANSIString<'static> {

    let style = style_from_modulestyle(&options.style);

    // Each shell keeps track of the number of characters that make up
    // the prompt. The ANSI escape-sequences that color the text will
    // be accidentally included in this length *unless* we prefix and
    // suffix them with these shell-specific escape-sequences. We
    // don't want the shell to mistakenly think there's fewer
    // characters remaining on the current line than there actually
    // are.
    let (len_esc_prefix, len_esc_suffix) = match shell {
        Shell::Bash => ("\\[", "\\]"),
        Shell::Zsh => ("%{", "%}"),
    };

    unimplemented!();
}

/// Converts a `ModuleStyle` into an `ansi_term::Style`.
fn style_from_modulestyle(s: &ModuleStyle) -> Style {
    let mut style = s.text_properties.unwrap_or_default();
    if let Some(bg) = s.background {
        style = style.on(bg);
    }
    if let Some(fg) = s.foreground {
        style = style.fg(fg);
    }
    style
}

// We use methods of the form "try_*_from_*" because the user should
// just be able to specify (in their config) what color/style they
// want, and we have to be able to parse what they say into a
// meaningful type.

/// Attempts to convert a string into an `ansi_term::Color`.
///
/// Returns a `ConvertError::NoSuchMatch` if the provided string
/// doesn't match any of the colors defined in crate `ansi_term`.
///
/// # Examples
/// ```
/// assert_eq!(try_color_from_str("black"), Ok(Color::Black));
/// assert_eq!(try_color_from_str("green"), Ok(Color::Green));
/// assert_eq!(try_color_from_str("turquoise"), Err(ConvertError::NoSuchMatch));
/// ```
pub fn try_color_from_str(s: &str) -> Result<Color, ConvertError> {
    match s {
        "black" => Ok(Color::Black),
        "red" => Ok(Color::Red),
        "green" => Ok(Color::Green),
        "yellow" => Ok(Color::Yellow),
        "blue" => Ok(Color::Blue),
        "purple" => Ok(Color::Purple),
        "cyan" => Ok(Color::Cyan),
        "white" => Ok(Color::White),
        _ => Err(ConvertError::NoSuchMatch),
    }
}

/// Attempts to convert a string into an `ansi_term::Color::RGB`.
///
/// Returns a `ConvertError::InvalidForm` if the provided string is
/// not a sequence of 3 `u8`s, separated by commas.
///
/// # Examples
/// ```
/// assert_eq!(try_rgb_from_str("(14, 76, 1)"), Ok(Color::RGB(14, 76, 1)));
/// assert_eq!(try_rgb_from_str("0, 100, 0"), Ok(Color::RGB(0, 100, 0)));
/// assert_eq!(try_rgb_from_str("1000, b, c, -1"), Err(ConvertError::InvalidForm));
/// ```
pub fn try_rgb_from_str(s: &str) -> Result<Color, ConvertError> {
    // Strip out non-integer characters
    let cleaned: Vec<String> = s.split(',')
        .map(|i| i.replace(|j| j == '(' || j == ')' || j == ' ', ""))
        .collect();

    // We want to immediately return an Error if a conversion fails
    let mut ints: Vec<u8> = Vec::new();
    for i in &cleaned {
        ints.push(i.parse::<u8>()?);
    }

    // Note: somewhat-malformed input, like "()()(0, 0, 0)" can still
    // get through, but we can still make "sense" of it so it's good
    // to go.
    if ints.len() != 3 {
        Err(ConvertError::InvalidForm)
    } else {
        Ok(Color::RGB(ints[0], ints[1], ints[2]))
    }
}

// NOTE: We do not need a try_color_from_u8 OR a try_rgb_from_vec.
// The implementation would just look like:
// pub fn try_color_from_u8(i: u8) -> Color { Color::u8(i) }
// It would always succeed due to Rust's type system.

#[derive(Debug, PartialEq)]
/// Error type for when a conversion due to parsing fails
pub enum ConvertError {
    /// Input doesn't correspond to a valid result
    NoSuchMatch,
    /// Input is malformed and cannot be parsed
    InvalidForm,
}

impl fmt::Display for ConvertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl Error for ConvertError {
    fn description(&self) -> &str {
        match *self {
            ConvertError::NoSuchMatch => "no match was found for the provided input",
            ConvertError::InvalidForm => "provided input was malformed and could not be parsed",
        }
    }
}

// So that we can use try!() and ? to return early if we encounter a
// ParseIntError
impl From<ParseIntError> for ConvertError {
    fn from(_: ParseIntError) -> ConvertError {
        ConvertError::InvalidForm
    }
}

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

    #[test]
    fn test_style_from_modulestyle() {
        const CONTENT: &'static str = "Hello";

        struct Test {
            style: ModuleStyle,
            expected: String,
        }

        let tests = [// Normal text, no bg, custom fg
                     Test {
                         style: ModuleStyle {
                             background: None,
                             foreground: Some(Color::White),
                             text_properties: None,
                         },
                         expected: format!("\x1B[37m{}\x1B[0m", CONTENT),
                     },
                     // Bold text, no fg, custom bg
                     Test {
                         style: ModuleStyle {
                             background: Some(Color::Blue),
                             foreground: None,
                             text_properties: Some(Style::default().bold()),
                         },
                         expected: format!("\x1B[1;44m{}\x1B[0m", CONTENT),
                     },
                     // Underlined text, custom bg and fg
                     Test {
                         style: ModuleStyle {
                             background: Some(Color::Blue),
                             foreground: Some(Color::White),
                             text_properties: Some(Style::default().underline()),
                         },
                         expected: format!("\x1B[4;44;37m{}\x1B[0m", CONTENT),
                     },
                     // Normal text, no bg nor fg
                     Test {
                         style: ModuleStyle {
                             background: None,
                             foreground: None,
                             text_properties: None,
                         },
                         expected: format!("{}", CONTENT),
                     }];

        for test in &tests {
            let result = format!("{}", style_from_modulestyle(&test.style).paint(CONTENT));
            assert_eq!(result, test.expected);
        }
    }

    #[test]
    fn test_color_try_from_str() {
        assert_eq!(try_color_from_str("blue"), Ok(Color::Blue));
        assert_eq!(try_color_from_str("teal"), Err(ConvertError::NoSuchMatch));
    }

    #[test]
    fn test_rgb_try_from_str() {
        // Valid inputs
        assert_eq!(try_rgb_from_str("(0, 0, 0)"), Ok(Color::RGB(0, 0, 0)));
        assert_eq!(try_rgb_from_str("(255, 255, 255)"),
                   Ok(Color::RGB(255, 255, 255)));

        // Questionable inputs (should still work)
        assert_eq!(try_rgb_from_str("(0, 0, 0))"), Ok(Color::RGB(0, 0, 0)));

        // Improperly formed ("too many" inputs)
        assert_eq!(try_rgb_from_str("(0, 0, 0,)"),
                   Err(ConvertError::InvalidForm));

        // Too few inputs
        assert_eq!(try_rgb_from_str("(0, 0)"), Err(ConvertError::InvalidForm));

        // Inputs aren't u8's
        assert_eq!(try_rgb_from_str("(1000, 0, 0)"),
                   Err(ConvertError::InvalidForm));
        assert_eq!(try_rgb_from_str("(0, 0, -1)"),
                   Err(ConvertError::InvalidForm));
    }
}
<commit_msg>feat: implement format_for_module<commit_after>use std::convert::From;
use std::error::Error;
use std::fmt;
use std::num::ParseIntError;

use ansi_term::{ANSIString, Color, Style};

use util::Shell;

/// Representation of config options that all modules have
#[derive(Clone)]
pub struct ModuleOptions<'a> {
    /// String to display to the left of the content
    pub padding_left: &'a str,
    /// String to display to the right of the content
    pub padding_right: &'a str,
    /// String to print out after the content and right padding
    pub separator: &'a str,
    /// Background color, foreground color, etc.
    pub style: ModuleStyle,
}

/// Representation of how to style a module
#[derive(Clone)]
pub struct ModuleStyle {
    /// Color behind the text
    pub background: Option<Color>,
    /// Color of the text
    pub foreground: Option<Color>,
    /// Combination of attributes like bold, italicized, etc.
    pub text_properties: Option<Style>,
}

/// Formats a string with the given `ModuleOptions` for a specific
/// `Shell`.
///
/// # Parameters
///
/// - `s` - the contents of the module to be formatted
/// - `options` - the background, foreground, padding, etc. to apply
/// - `next_bg` - the background color, if any, of the next visible module
/// - `shell` - the type of shell to format the string for
pub fn format_for_module(s: &str,
                         options: &ModuleOptions,
                         next_bg: Option<Color>,
                         shell: Shell)
                         -> ANSIString<'static> {

    let style = style_from_modulestyle(&options.style);

    // Each shell keeps track of the number of characters that make up
    // the prompt. The ANSI escape-sequences that color the text will
    // be accidentally included in this length *unless* we prefix and
    // suffix them with these shell-specific escape-sequences. We
    // don't want the shell to mistakenly think there's fewer
    // characters remaining on the current line than there actually
    // are.
    let (len_esc_prefix, len_esc_suffix) = match shell {
        Shell::Bash => ("\\[", "\\]"),
        Shell::Zsh => ("%{", "%}"),
    };

    // Every time there is a color escape-sequence, it must be
    // surrounded by the length escape-codes. We also include the
    // padding before and after the content.
    let content = format!("{}{}{}{}{}{}{}{}{}",
                    len_esc_prefix,
                    style.prefix(),
                    len_esc_suffix,
                    options.padding_left,
                    s,
                    options.padding_right,
                    len_esc_prefix,
                    style.suffix(),
                    len_esc_suffix,
    );

    // We must format the separator differently depending on whether
    // there exists a visible module after this one or not.
    let separator_style = ModuleStyle {
        foreground: options.style.background,
        background: next_bg,
        text_properties: options.style.text_properties,
    };
    let separator_style = style_from_modulestyle(&separator_style);
    let separator = format!("{}{}{}{}{}{}{}",
                            len_esc_prefix,
                            separator_style.prefix(),
                            len_esc_suffix,
                            options.separator,
                            len_esc_prefix,
                            separator_style.suffix(),
                            len_esc_suffix);

    ANSIString::from(format!("{}{}", content, separator))
}

/// Converts a `ModuleStyle` into an `ansi_term::Style`.
fn style_from_modulestyle(s: &ModuleStyle) -> Style {
    let mut style = s.text_properties.unwrap_or_default();
    if let Some(bg) = s.background {
        style = style.on(bg);
    }
    if let Some(fg) = s.foreground {
        style = style.fg(fg);
    }
    style
}

// We use methods of the form "try_*_from_*" because the user should
// just be able to specify (in their config) what color/style they
// want, and we have to be able to parse what they say into a
// meaningful type.

/// Attempts to convert a string into an `ansi_term::Color`.
///
/// Returns a `ConvertError::NoSuchMatch` if the provided string
/// doesn't match any of the colors defined in crate `ansi_term`.
///
/// # Examples
/// ```
/// assert_eq!(try_color_from_str("black"), Ok(Color::Black));
/// assert_eq!(try_color_from_str("green"), Ok(Color::Green));
/// assert_eq!(try_color_from_str("turquoise"), Err(ConvertError::NoSuchMatch));
/// ```
pub fn try_color_from_str(s: &str) -> Result<Color, ConvertError> {
    match s.to_lowercase().as_ref() {
        "black" => Ok(Color::Black),
        "red" => Ok(Color::Red),
        "green" => Ok(Color::Green),
        "yellow" => Ok(Color::Yellow),
        "blue" => Ok(Color::Blue),
        "purple" => Ok(Color::Purple),
        "cyan" => Ok(Color::Cyan),
        "white" => Ok(Color::White),
        _ => Err(ConvertError::NoSuchMatch),
    }
}

/// Attempts to convert a string into an `ansi_term::Color::RGB`.
///
/// Returns a `ConvertError::InvalidForm` if the provided string is
/// not a sequence of 3 `u8`s, separated by commas.
///
/// # Examples
/// ```
/// assert_eq!(try_rgb_from_str("(14, 76, 1)"), Ok(Color::RGB(14, 76, 1)));
/// assert_eq!(try_rgb_from_str("0, 100, 0"), Ok(Color::RGB(0, 100, 0)));
/// assert_eq!(try_rgb_from_str("1000, b, c, -1"), Err(ConvertError::InvalidForm));
/// ```
pub fn try_rgb_from_str(s: &str) -> Result<Color, ConvertError> {
    // Strip out non-integer characters
    let cleaned: Vec<String> =
        s.split(',').map(|i| i.replace(|j| j == '(' || j == ')' || j == ' ', "")).collect();

    // We want to immediately return an Error if a conversion fails
    let mut ints: Vec<u8> = Vec::new();
    for i in &cleaned {
        ints.push(i.parse::<u8>()?);
    }

    // Note: somewhat-malformed input, like "()()(0, 0, 0)" can still
    // get through, but we can still make "sense" of it so it's good
    // to go.
    if ints.len() != 3 {
        Err(ConvertError::InvalidForm)
    } else {
        Ok(Color::RGB(ints[0], ints[1], ints[2]))
    }
}

// NOTE: We do not need a try_color_from_u8 OR a try_rgb_from_vec.
// The implementation would just look like:
// pub fn try_color_from_u8(i: u8) -> Color { Color::u8(i) }
// It would always succeed due to Rust's type system.

#[derive(Debug, PartialEq)]
/// Error type for when a conversion due to parsing fails
pub enum ConvertError {
    /// Input doesn't correspond to a valid result
    NoSuchMatch,
    /// Input is malformed and cannot be parsed
    InvalidForm,
}

impl fmt::Display for ConvertError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl Error for ConvertError {
    fn description(&self) -> &str {
        match *self {
            ConvertError::NoSuchMatch => "no match was found for the provided input",
            ConvertError::InvalidForm => "provided input was malformed and could not be parsed",
        }
    }
}

// So that we can use try!() and ? to return early if we encounter a
// ParseIntError
impl From<ParseIntError> for ConvertError {
    fn from(_: ParseIntError) -> ConvertError {
        ConvertError::InvalidForm
    }
}

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

    #[test]
    fn test_format_for_module() {
        const CONTENT: &'static str = "Hello";
        const PADDING: &'static str = " ";
        const SEPARATOR: &'static str = ">";

        let options = ModuleOptions {
            padding_left: PADDING,
            padding_right: PADDING,
            separator: SEPARATOR,
            style: ModuleStyle {
                background: Some(Color::Blue),
                foreground: Some(Color::White),
                text_properties: Some(Style::default().bold()),
            },
        };

        let formatted_string = format_for_module(CONTENT, &options, None, Shell::Bash);
        assert_eq!(format!("\\[\x1B[1;44;37m\\]{}{}{}\\[\x1B[0m\\]\\[\x1B[1;34m\\]{}\\[\x1B[0m\\]",
                           PADDING,
                           CONTENT,
                           PADDING,
                           SEPARATOR),
                   format!("{}", formatted_string))
    }

    #[test]
    fn test_style_from_modulestyle() {
        const CONTENT: &'static str = "Hello";

        struct Test {
            style: ModuleStyle,
            expected: String,
        }

        let tests = [// Normal text, no bg, custom fg
                     Test {
                         style: ModuleStyle {
                             background: None,
                             foreground: Some(Color::White),
                             text_properties: None,
                         },
                         expected: format!("\x1B[37m{}\x1B[0m", CONTENT),
                     },
                     // Bold text, no fg, custom bg
                     Test {
                         style: ModuleStyle {
                             background: Some(Color::Blue),
                             foreground: None,
                             text_properties: Some(Style::default().bold()),
                         },
                         expected: format!("\x1B[1;44m{}\x1B[0m", CONTENT),
                     },
                     // Underlined text, custom bg and fg
                     Test {
                         style: ModuleStyle {
                             background: Some(Color::Blue),
                             foreground: Some(Color::White),
                             text_properties: Some(Style::default().underline()),
                         },
                         expected: format!("\x1B[4;44;37m{}\x1B[0m", CONTENT),
                     },
                     // Normal text, no bg nor fg
                     Test {
                         style: ModuleStyle {
                             background: None,
                             foreground: None,
                             text_properties: None,
                         },
                         expected: format!("{}", CONTENT),
                     }];

        for test in &tests {
            let result = format!("{}", style_from_modulestyle(&test.style).paint(CONTENT));
            assert_eq!(result, test.expected);
        }
    }

    #[test]
    fn test_color_try_from_str() {
        assert_eq!(try_color_from_str("blue"), Ok(Color::Blue));
        assert_eq!(try_color_from_str("teal"), Err(ConvertError::NoSuchMatch));
    }

    #[test]
    fn test_rgb_try_from_str() {
        // Valid inputs
        assert_eq!(try_rgb_from_str("(0, 0, 0)"), Ok(Color::RGB(0, 0, 0)));
        assert_eq!(try_rgb_from_str("(255, 255, 255)"),
                   Ok(Color::RGB(255, 255, 255)));

        // Questionable inputs (should still work)
        assert_eq!(try_rgb_from_str("(0, 0, 0))"), Ok(Color::RGB(0, 0, 0)));

        // Improperly formed ("too many" inputs)
        assert_eq!(try_rgb_from_str("(0, 0, 0,)"),
                   Err(ConvertError::InvalidForm));

        // Too few inputs
        assert_eq!(try_rgb_from_str("(0, 0)"), Err(ConvertError::InvalidForm));

        // Inputs aren't u8's
        assert_eq!(try_rgb_from_str("(1000, 0, 0)"),
                   Err(ConvertError::InvalidForm));
        assert_eq!(try_rgb_from_str("(0, 0, -1)"),
                   Err(ConvertError::InvalidForm));
    }
}
<|endoftext|>


<commit_before>use num::bigint::{RandBigInt, BigInt};
use num::{Zero, One, pow};
use std::num::{FromPrimitive};
use num::integer::Integer;
use rand::thread_rng;

/// Cryptographically useful extensions to the provided BigInt functionality.
pub trait BigIntCrypto {
    /// Find the next prime from the current BigInt
    fn next_prime(&self) -> BigInt;

    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigInt) -> (BigInt, BigInt, BigInt);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigInt) -> bool;
}

impl BigIntCrypto for BigInt {
    fn next_prime(&self) -> BigInt {
        let one: BigInt = One::one();
        let two = BigInt::from_isize(2).unwrap();
        let mut nextPrime = self.clone();
        if &nextPrime % &two == Zero::zero() {
            nextPrime = &nextPrime + &one;
        }
        while !BigInt::is_prime(&nextPrime) {
            nextPrime = &nextPrime + &two;
        }
        nextPrime
    }

    fn gcdext(&self, other: &BigInt) -> (BigInt, BigInt, BigInt) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigInt) -> bool {
        let two = BigInt::from_isize(2).unwrap();
        let three = BigInt::from_isize(3).unwrap();
        if *n == three || *n == two {
            return true;
        }
        if *n < two || n % two == Zero::zero() {
            return false;
        }
        miller_rabin(n, 100)
    }

}

/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigInt, k: usize) -> bool{
    let one: BigInt = One::one();
    let two: BigInt = &one + &one;
    let mut d: BigInt = n - &One::one();
    let mut s: BigInt = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &One::one();
    }

    for j in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_bigint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, &d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigInt
        let mut i: BigInt = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (&s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt {
    let one: BigInt = One::one();
    let two = &one + &one;
    let mut result: BigInt = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > Zero::zero() {
        if (&exp_acc % &two) == One::one() {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> One::one();
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

mod test_bigint_crypto {
    use super::{BigIntCrypto, mod_exp};
    use num::bigint::{RandBigInt, BigInt};
    use std::num::FromPrimitive;
    use num::One;
    use rand::thread_rng;

    #[test]
    fn next_prime_test() {
        let test_num = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = BigInt::from_isize(4).unwrap();
        let exponent = BigInt::from_isize(13).unwrap();
        let modulus = BigInt::from_isize(497).unwrap();
        let expected_result = BigInt::from_isize(445).unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);

        // time test, this takes a long time to do!
        let large_num = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        let a = thread_rng().gen_bigint_range(&One::one(), &large_num);
        let b = thread_rng().gen_bigint_range(&One::one(), &large_num);
        let c = thread_rng().gen_bigint_range(&One::one(), &large_num);
        for _ in 0..100 {
            mod_exp(&a, &b, &c);
        }
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigInt::is_prime(&known_prime));
    }

}
<commit_msg>Fix bug. next_prime() would return current number if number was already prime.<commit_after>use num::bigint::{RandBigInt, BigInt};
use num::{Zero, One, pow};
use std::num::{FromPrimitive};
use num::integer::Integer;
use rand::thread_rng;

/// Cryptographically useful extensions to the provided BigInt functionality.
pub trait BigIntCrypto {
    /// Find the next prime from the current BigInt
    fn next_prime(&self) -> BigInt;

    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigInt) -> (BigInt, BigInt, BigInt);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigInt) -> bool;
}

impl BigIntCrypto for BigInt {
    fn next_prime(&self) -> BigInt {
        let one: BigInt = One::one();
        let two = BigInt::from_isize(2).unwrap();
        let mut nextPrime = self.clone();
        if &nextPrime % &two == Zero::zero() {
            nextPrime = &nextPrime + &one;
        } else {
            nextPrime = &nextPrime + &two;
        }
        while !BigInt::is_prime(&nextPrime) {
            nextPrime = &nextPrime + &two;
        }
        nextPrime
    }

    fn gcdext(&self, other: &BigInt) -> (BigInt, BigInt, BigInt) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigInt) -> bool {
        let two = BigInt::from_isize(2).unwrap();
        let three = BigInt::from_isize(3).unwrap();
        if *n == three || *n == two {
            return true;
        }
        if *n < two || n % two == Zero::zero() {
            return false;
        }
        miller_rabin(n, 100)
    }

}

/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigInt, k: usize) -> bool{
    let one: BigInt = One::one();
    let two: BigInt = &one + &one;
    let mut d: BigInt = n - &One::one();
    let mut s: BigInt = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &One::one();
    }

    for j in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_bigint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, &d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigInt
        let mut i: BigInt = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (&s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt {
    let one: BigInt = One::one();
    let two = &one + &one;
    let mut result: BigInt = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > Zero::zero() {
        if (&exp_acc % &two) == One::one() {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> One::one();
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

mod test_bigint_crypto {
    use super::{BigIntCrypto, mod_exp};
    use num::bigint::{RandBigInt, BigInt};
    use std::num::FromPrimitive;
    use num::One;
    use rand::thread_rng;

    #[test]
    fn next_prime_test() {
        let test_num = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = BigInt::from_isize(4).unwrap();
        let exponent = BigInt::from_isize(13).unwrap();
        let modulus = BigInt::from_isize(497).unwrap();
        let expected_result = BigInt::from_isize(445).unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);

        // time test, this takes a long time to do!
        let large_num = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        let a = thread_rng().gen_bigint_range(&One::one(), &large_num);
        let b = thread_rng().gen_bigint_range(&One::one(), &large_num);
        let c = thread_rng().gen_bigint_range(&One::one(), &large_num);
        for _ in 0..100 {
            mod_exp(&a, &b, &c);
        }
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigInt::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigInt::is_prime(&known_prime));
    }

}
<|endoftext|>


<commit_before>//! Encoding of PPM Images

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

use color;
use color::ColorType:: {
    Gray,
    Palette,
    GrayA,
    RGB,
    RGBA,
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<'a, W: 'a> {
    w: &'a mut W
}

impl<'a, W: Write> PPMEncoder<'a, W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: &mut W) -> PPMEncoder<W> {
        PPMEncoder { w: w }
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> io::Result<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> io::Result<()> {
        write!(self.w, "P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> io::Result<()> {
        let m = max_pixel_value(pixel_type);
        write!(self.w, "{0} {1}\n{2}\n", width, height, m)
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> io::Result<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Gray(8) => {
                for i in 0..(width * height) as usize {
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                }
            }
            RGB(8)  => try!(self.w.write_all(buf)),
            RGB(16) => try!(self.w.write_all(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {
                    let _ = try!(self.w.write_all(&[x[0]]));
                    let _ = try!(self.w.write_all(&[x[1]]));
                    let _ = try!(self.w.write_all(&[x[2]]));
                }
            }
            a => panic!(format!("not implemented: {:?}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    match pixel_type {
        Gray(n)    => 2u16.pow(n as u32) - 1,
        RGB(n)     => 2u16.pow(n as u32) - 1,
        Palette(n) => 2u16.pow(n as u32) - 1,
        GrayA(n)   => 2u16.pow(n as u32) - 1,
        RGBA(n)    => 2u16.pow(n as u32) - 1,
    }
}
<commit_msg>Make 16bit ppm encoding actually work<commit_after>//! Encoding of PPM Images

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

use color;
use color::ColorType:: {
    Gray,
    Palette,
    GrayA,
    RGB,
    RGBA,
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<'a, W: 'a> {
    w: &'a mut W
}

impl<'a, W: Write> PPMEncoder<'a, W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: &mut W) -> PPMEncoder<W> {
        PPMEncoder { w: w }
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> io::Result<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> io::Result<()> {
        write!(self.w, "P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> io::Result<()> {
        let m = max_pixel_value(pixel_type);
        write!(self.w, "{0} {1}\n{2}\n", width, height, m)
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> io::Result<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Gray(8) => {
                for i in 0..(width * height) as usize {
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                }
            }
            RGB(8)  => try!(self.w.write_all(buf)),
            RGB(16) => try!(self.w.write_all(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {
                    let _ = try!(self.w.write_all(&[x[0]]));
                    let _ = try!(self.w.write_all(&[x[1]]));
                    let _ = try!(self.w.write_all(&[x[2]]));
                }
            }
            a => panic!(format!("not implemented: {:?}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    let max = match pixel_type {
        Gray(n)    => 2u32.pow(n as u32) - 1,
        RGB(n)     => 2u32.pow(n as u32) - 1,
        Palette(n) => 2u32.pow(n as u32) - 1,
        GrayA(n)   => 2u32.pow(n as u32) - 1,
        RGBA(n)    => 2u32.pow(n as u32) - 1,
    };

    if max > 65535 {
      panic!("PPM: Trying to encode image with more than 16bit per pixel");
    } else {
      max as u16
    }
}
<|endoftext|>


<commit_before>//! Get project by id.
//!
//! https://docs.gitlab.com/ce/api/projects.html#get-single-project
//!
//! # Get single project
//!
//! Get a specific project, identified by project ID or `NAMESPACE/PROJECT_NAME`, which is owned by
//! the authenticated user.
//! If using namespaced projects call make sure that the `NAMESPACE/PROJECT_NAME` is URL-encoded,
//! eg. `/api/v3/projects/diaspora%2Fdiaspora` (where `/` is represented by `%2F`).
//!
//! ```text
//! GET /projects/ID
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `id` | integer/string | yes | The ID or `NAMESPACE/PROJECT_NAME` of the project |

use BuildQuery;
use Project;
use projects::ListingId;

use ::errors::*;

#[derive(Debug, Clone)]
pub struct ProjectsLister<'a> {
    gl: &'a ::GitLab,
    id: ListingId,
}

impl<'a> ProjectsLister<'a> {
    pub fn new(gl: &'a ::GitLab, id: ListingId) -> ProjectsLister {
        ProjectsLister { gl: gl, id: id }
    }

    /// Commit the lister: Query GitLab and return a list of projects.
    pub fn list(&self) -> Result<Project> {
        // let query = serde_urlencoded::to_string(&self);
        let query = self.build_query();
        debug!("query: {:?}", query);

        self.gl.get(&query).chain_err(|| format!("cannot get query {}", query))
    }
}

impl<'a> BuildQuery for ProjectsLister<'a> {
    fn build_query(&self) -> String {
        let mut query = String::from("projects/");

        query.push_str(&match self.id {
            ListingId::Id(id) => id.to_string(),
            ListingId::NamespaceProject(ref s) => s.replace("/", "%2F"),
        });

        query
    }
}

#[cfg(test)]
mod tests {
    use projects::ListingId;
    use BuildQuery;

    const TEST_PROJECT_ID: i64 = 123;
    const TEST_PROJECT_NAME: &'static str = "group/project";

    #[test]
    fn build_query_id() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = format!("projects/{}", TEST_PROJECT_ID);
        let query = gl.projects()
            .id(ListingId::Id(TEST_PROJECT_ID))
            .build_query();
        assert_eq!(query, expected_string);

        let expected_string = format!("projects/{}",
                                      TEST_PROJECT_NAME.to_string().replace("/", "%2F"));
        let query = gl.projects()
            .id(ListingId::NamespaceProject(TEST_PROJECT_NAME.to_string()))
            .build_query();
        assert_eq!(query, expected_string);
    }
}
<commit_msg>Add `ProjectsLister::issues()` to get a list of issues from a project lister<commit_after>//! Get project by id.
//!
//! https://docs.gitlab.com/ce/api/projects.html#get-single-project
//!
//! # Get single project
//!
//! Get a specific project, identified by project ID or `NAMESPACE/PROJECT_NAME`, which is owned by
//! the authenticated user.
//! If using namespaced projects call make sure that the `NAMESPACE/PROJECT_NAME` is URL-encoded,
//! eg. `/api/v3/projects/diaspora%2Fdiaspora` (where `/` is represented by `%2F`).
//!
//! ```text
//! GET /projects/ID
//! ```
//!
//! Parameters:
//!
//! | Attribute | Type | Required | Description |
//! | --------- | ---- | -------- | ----------- |
//! | `id` | integer/string | yes | The ID or `NAMESPACE/PROJECT_NAME` of the project |

use BuildQuery;
use Project;
use projects::ListingId;

use ::errors::*;

#[derive(Debug, Clone)]
pub struct ProjectsLister<'a> {
    gl: &'a ::GitLab,
    id: ListingId,
}

impl<'a> ProjectsLister<'a> {
    pub fn new(gl: &'a ::GitLab, id: ListingId) -> ProjectsLister {
        ProjectsLister { gl: gl, id: id }
    }

    /// Commit the lister: Query GitLab and return a list of projects.
    pub fn list(&self) -> Result<Project> {
        // let query = serde_urlencoded::to_string(&self);
        let query = self.build_query();
        debug!("query: {:?}", query);

        self.gl.get(&query).chain_err(|| format!("cannot get query {}", query))
    }

    /// Return a lister for the project's issues
    pub fn issues(self) -> Result<::issues::project::IssuesLister<'a>> {
        let project = self.list().chain_err(|| "failure to find project")?;

        Ok(::issues::project::IssuesLister::new(self.gl, project.id))
    }
}

impl<'a> BuildQuery for ProjectsLister<'a> {
    fn build_query(&self) -> String {
        let mut query = String::from("projects/");

        query.push_str(&match self.id {
            ListingId::Id(id) => id.to_string(),
            ListingId::NamespaceProject(ref s) => s.replace("/", "%2F"),
        });

        query
    }
}

#[cfg(test)]
mod tests {
    use projects::ListingId;
    use BuildQuery;

    const TEST_PROJECT_ID: i64 = 123;
    const TEST_PROJECT_NAME: &'static str = "group/project";

    #[test]
    fn build_query_id() {
        let gl = ::GitLab::new(&"localhost", "XXXXXXXXXXXXXXXXXXXX").unwrap();
        // let gl: ::GitLab = Default::default();

        let expected_string = format!("projects/{}", TEST_PROJECT_ID);
        let query = gl.projects()
            .id(ListingId::Id(TEST_PROJECT_ID))
            .build_query();
        assert_eq!(query, expected_string);

        let expected_string = format!("projects/{}",
                                      TEST_PROJECT_NAME.to_string().replace("/", "%2F"));
        let query = gl.projects()
            .id(ListingId::NamespaceProject(TEST_PROJECT_NAME.to_string()))
            .build_query();
        assert_eq!(query, expected_string);
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]

pub mod ffi;

use std::mem;
use std::ptr;
use std::ffi::CString;
use std::iter::Iterator;

use error::{RuntimeError, ErrorKind};

use super::x11::ffi::Display as X11Display;
use super::xcb::ffi::xcb_window_t;

use super::x11;
use super::utils::fn_ptr::{FnPtrLoader, FnPtr};

pub type EGLNativeDisplayType = *mut X11Display;
pub type EGLNativeWindowType = xcb_window_t;

pub struct Loader;

impl Loader {
   pub fn new() -> Self {
      Loader
   }
}

impl FnPtrLoader for Loader {
   fn get_proc_addr(&self, name: &str) -> FnPtr {
      let cname = CString::new(name).unwrap().as_ptr();

      let addr = unsafe {
         ffi::eglGetProcAddress(cname)
      };
      println!("{}: {:?}", name, addr);

      addr
   }
}

pub type NativeDisplay = x11::Display;

pub enum API {
    OpenGLES,
    OpenVG,
    OpenGL,
}

impl Into<ffi::EGLenum> for API {
   #[inline]
   fn into(self) -> ffi::EGLenum {
      match self {
         API::OpenGLES => ffi::EGL_OPENGL_ES_API,
         API::OpenVG => ffi::EGL_OPENVG_API,
         API::OpenGL => ffi::EGL_OPENGL_API,
      }
   }
}

pub struct Display {
   pub ptr: ffi::EGLDisplay
}

pub struct Config {
   pub ptr: ffi::EGLConfig
}

pub struct Context {
   pub ptr: ffi::EGLContext
}

pub struct Surface {
   pub ptr: ffi::EGLSurface
}

pub struct Version {
   pub major: ffi::EGLint,
   pub minor: ffi::EGLint,
}

pub fn bind_api(api: API) -> Result<(), RuntimeError> {
   let result = unsafe {
      ffi::eglBindAPI(api.into())
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglBindAPI failed".to_string()
      ));
   }

   Ok(())
}

pub fn initialize(display: &Display) -> Result<Version, RuntimeError> {
   let mut major: ffi::EGLint = unsafe {
      mem::uninitialized()
   };
   let mut minor: ffi::EGLint = unsafe {
      mem::uninitialized()
   };

   let result = unsafe {
      ffi::eglInitialize(display.ptr, &mut major, &mut minor)
   };

   match result {
      ffi::EGL_FALSE => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "eglInitialize failed".to_string()
         ));
      },
      ffi::EGL_BAD_DISPLAY => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Not an EGL display connection".to_string()
         ));
      },
      ffi::EGL_NOT_INITIALIZED => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Display cannot be initialized".to_string()
         ));
      },
      ffi::EGL_TRUE => {
         return Ok(Version {
            major: major,
            minor: minor
         });
      },
      _ => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Unknown eglInitialize error".to_string()
         ));
      }
   }
}

pub fn configs(display: &Display) -> Result<Vec<Config>, RuntimeError> {
   let mut num_config = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglGetConfigs(
         display.ptr,
         ptr::null_mut(),
         0,
         &mut num_config,
      )
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Getting configs count eglGetConfigs failed".to_string()
      ));
   }

   let mut config_ptrs = Vec::with_capacity(num_config as usize);

   let result = unsafe {
      ffi::eglGetConfigs(
         display.ptr,
         config_ptrs.as_mut_ptr(),
         config_ptrs.capacity() as ffi::EGLint,
         &mut num_config
      )
   };

   unsafe {
      config_ptrs.set_len(num_config as usize)
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglGetConfigs failed".to_string()
      ));
   }

   let configs = config_ptrs.iter().map(|&ptr| Config {ptr: ptr}).collect();

   for config in &configs {
      print_config(display, config);
   }

   Ok(configs)
}

pub fn choose_config(display: &Display) -> Result<Config, RuntimeError> {
   let config_attribs = [
      ffi::EGL_COLOR_BUFFER_TYPE,    ffi::EGL_RGB_BUFFER,
      ffi::EGL_BUFFER_SIZE,          32,
      ffi::EGL_RED_SIZE,             8,
      ffi::EGL_GREEN_SIZE,           8,
      ffi::EGL_BLUE_SIZE,            8,
      ffi::EGL_ALPHA_SIZE,           8,

      ffi::EGL_DEPTH_SIZE,           24,
      ffi::EGL_STENCIL_SIZE,         8,

      ffi::EGL_SAMPLE_BUFFERS,       0,
      ffi::EGL_SAMPLES,              0,

      ffi::EGL_SURFACE_TYPE,         ffi::EGL_WINDOW_BIT,
      ffi::EGL_RENDERABLE_TYPE,      ffi::EGL_OPENGL_BIT,

      ffi::EGL_NONE
   ];

   let mut num_config: ffi::EGLint = unsafe {
      mem::uninitialized()
   };

   let mut configs: [ffi::EGLConfig; 64] = unsafe {
      mem::uninitialized()
   };

   let result = unsafe {
      ffi::eglChooseConfig(
         display.ptr,
         config_attribs.as_ptr() as *const _,
         configs.as_mut_ptr() as *mut *mut _,
         64,
         &mut num_config
      )
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Choosing config failed".to_string()
      ));
   }

   if num_config == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Failed to find suitable EGLConfig".to_string()
      ));
   }

   Ok(Config {
      ptr: configs[0]
   })
}

pub fn config_attrib(
   display: &Display,
   config: &Config,
   attribute: ffi::EGLint
) -> Result<ffi::EGLint, RuntimeError> {

   let mut value: ffi::EGLint = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglGetConfigAttrib(display.ptr, config.ptr, attribute, &mut value)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglGetConfigAttrib failed".to_string()
      ));
   }

   Ok(value)
}

pub fn print_config(display: &Display, config: &Config) {
   println!("-------------------------");

   pattr(display, config, "EGL_CONFIG_ID", ffi::EGL_CONFIG_ID);
   pattr(display, config, "EGL_COLOR_BUFFER_TYPE", ffi::EGL_COLOR_BUFFER_TYPE);
   pattr(display, config, "EGL_RENDERABLE_TYPE", ffi::EGL_RENDERABLE_TYPE);
   pattr(display, config, "EGL_SURFACE_TYPE", ffi::EGL_SURFACE_TYPE);
   pattr(display, config, "EGL_TRANSPARENT_TYPE", ffi::EGL_TRANSPARENT_TYPE);
   pattr(display, config, "EGL_NATIVE_VISUAL_TYPE", ffi::EGL_NATIVE_VISUAL_TYPE);
   pattr(display, config, "EGL_NATIVE_VISUAL_ID", ffi::EGL_NATIVE_VISUAL_ID);
   pattr(display, config, "EGL_BUFFER_SIZE", ffi::EGL_BUFFER_SIZE);
   pattr(display, config, "EGL_LUMINANCE_SIZE", ffi::EGL_LUMINANCE_SIZE);
   pattr(display, config, "EGL_DEPTH_SIZE", ffi::EGL_DEPTH_SIZE);
   pattr(display, config, "EGL_STENCIL_SIZE", ffi::EGL_STENCIL_SIZE);
   pattr(display, config, "EGL_RED_SIZE", ffi::EGL_RED_SIZE);
   pattr(display, config, "EGL_GREEN_SIZE", ffi::EGL_GREEN_SIZE);
   pattr(display, config, "EGL_BLUE_SIZE", ffi::EGL_BLUE_SIZE);
   pattr(display, config, "EGL_ALPHA_SIZE", ffi::EGL_ALPHA_SIZE);
   pattr(display, config, "EGL_ALPHA_MASK_SIZE", ffi::EGL_ALPHA_MASK_SIZE);
   pattr(display, config, "EGL_BIND_TO_TEXTURE_RGB", ffi::EGL_BIND_TO_TEXTURE_RGB);
   pattr(display, config, "EGL_BIND_TO_TEXTURE_RGBA", ffi::EGL_BIND_TO_TEXTURE_RGBA);
   pattr(display, config, "EGL_CONFIG_CAVEAT", ffi::EGL_CONFIG_CAVEAT);
   pattr(display, config, "EGL_CONFORMANT", ffi::EGL_CONFORMANT);
   pattr(display, config, "EGL_LEVEL", ffi::EGL_LEVEL);
   pattr(display, config, "EGL_MAX_PBUFFER_WIDTH", ffi::EGL_MAX_PBUFFER_WIDTH);
   pattr(display, config, "EGL_MAX_PBUFFER_HEIGHT", ffi::EGL_MAX_PBUFFER_HEIGHT);
   pattr(display, config, "EGL_MAX_PBUFFER_PIXELS", ffi::EGL_MAX_PBUFFER_PIXELS);
   pattr(display, config, "EGL_MAX_SWAP_INTERVAL", ffi::EGL_MAX_SWAP_INTERVAL);
   pattr(display, config, "EGL_MIN_SWAP_INTERVAL", ffi::EGL_MIN_SWAP_INTERVAL);
   pattr(display, config, "EGL_NATIVE_RENDERABLE", ffi::EGL_NATIVE_RENDERABLE);
   pattr(display, config, "EGL_SAMPLE_BUFFERS", ffi::EGL_SAMPLE_BUFFERS);
   pattr(display, config, "EGL_SAMPLES", ffi::EGL_SAMPLES);
   pattr(display, config, "EGL_TRANSPARENT_RED_VALUE", ffi::EGL_TRANSPARENT_RED_VALUE);
   pattr(display, config, "EGL_TRANSPARENT_GREEN_VALUE", ffi::EGL_TRANSPARENT_GREEN_VALUE);
   pattr(display, config, "EGL_TRANSPARENT_BLUE_VALUE", ffi::EGL_TRANSPARENT_BLUE_VALUE);

   println!("");
}

pub fn pattr(display: &Display, config: &Config, name: &str, attribute: ffi::EGLenum) {
   println!(
      "{}: {}", name, config_attrib(display, config, attribute as ffi::EGLint).unwrap()
   );
}

pub fn create_context(display: &Display, config: &Config) -> Result<Context, RuntimeError> {
   let context_attribs = [ffi::EGL_NONE];

   let context = unsafe {
      ffi::eglCreateContext(
         display.ptr,
         config.ptr as *mut _,
         ffi::EGL_NO_CONTEXT as *mut _,
         context_attribs.as_ptr() as *const _,
      )
   };
   if context.is_null() {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglCreateContext failed".to_string()
      ));
   }

   Ok(Context {
      ptr: context
   })
}

pub fn create_window_surface(
   display: &Display,
   config: &Config,
   window: &EGLNativeWindowType
) -> Result<Surface, RuntimeError> {

   let surface_attribs = [
      ffi::EGL_RENDER_BUFFER, ffi::EGL_BACK_BUFFER,
      ffi::EGL_NONE
   ];

   let surface = unsafe {
      ffi::eglCreateWindowSurface(
         display.ptr,
         config.ptr as *mut _,
         *window,
         surface_attribs.as_ptr() as *const _,
      )
   };
   if surface.is_null() {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglCreateWindowSurface failed".to_string()
      ));
   }

   Ok(Surface {
      ptr: surface
   })
}

pub fn make_current(
   display: &Display,
   draw: &Surface,
   read: &Surface,
   context: &Context,
) -> Result<(), RuntimeError> {

   let made_current = unsafe {
      ffi::eglMakeCurrent(
         display.ptr,
         draw.ptr,
         read.ptr,
         context.ptr
      )
   };

   if made_current != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglMakeCurrent failed".to_string()
      ));
   }

   Ok(())
}

pub fn query_context(
   display: &Display,
   context: &Context,
) -> Result<(), RuntimeError> {

   let mut render_buffer: ffi::EGLint = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglQueryContext(
         display.ptr,
         context.ptr,
         ffi::EGL_RENDER_BUFFER as i32,
         &mut render_buffer
      )
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglQueyContext (EGL_RENDER_BUFFER) failed".to_string()
      ));
   }

   if render_buffer == ffi::EGL_SINGLE_BUFFER as i32 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "EGL surface is single buffered".to_string()
      ));
   }

   Ok(())
}

pub fn swap_buffers(
   display: &Display,
   surface: &Surface
) -> Result<(), RuntimeError> {

   let result = unsafe {
      ffi::eglSwapBuffers(display.ptr, surface.ptr)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglSwapBuffers failed".to_string()
      ));
   }

   Ok(())
}

pub fn swap_interval(
   display: &Display,
   interval: ffi::c_int
) -> Result<(), RuntimeError> {

   let result = unsafe {
      ffi::eglSwapInterval(display.ptr, interval)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglSwapInterval failed".to_string()
      ));
   }

   Ok(())
}

impl Display {
   pub fn from_native(native_display: &NativeDisplay) -> Result<Self, RuntimeError> {
      let ptr = unsafe {
         ffi::eglGetDisplay(native_display.ptr)
      };

      if ptr.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "eglGetDisplay failed".to_string()
         ));
      }

      Ok(Display {
         ptr: ptr,
      })
   }
}
<commit_msg>Adjusting eglChooseConfig attributex<commit_after>#![cfg(target_os = "linux")]

pub mod ffi;

use std::mem;
use std::ptr;
use std::ffi::CString;
use std::iter::Iterator;

use error::{RuntimeError, ErrorKind};

use super::x11::ffi::Display as X11Display;
use super::xcb::ffi::xcb_window_t;

use super::x11;
use super::utils::fn_ptr::{FnPtrLoader, FnPtr};

pub type EGLNativeDisplayType = *mut X11Display;
pub type EGLNativeWindowType = xcb_window_t;

pub struct Loader;

impl Loader {
   pub fn new() -> Self {
      Loader
   }
}

impl FnPtrLoader for Loader {
   fn get_proc_addr(&self, name: &str) -> FnPtr {
      let cname = CString::new(name).unwrap().as_ptr();

      let addr = unsafe {
         ffi::eglGetProcAddress(cname)
      };
      println!("{}: {:?}", name, addr);

      addr
   }
}

pub type NativeDisplay = x11::Display;

pub enum API {
    OpenGLES,
    OpenVG,
    OpenGL,
}

impl Into<ffi::EGLenum> for API {
   #[inline]
   fn into(self) -> ffi::EGLenum {
      match self {
         API::OpenGLES => ffi::EGL_OPENGL_ES_API,
         API::OpenVG => ffi::EGL_OPENVG_API,
         API::OpenGL => ffi::EGL_OPENGL_API,
      }
   }
}

pub struct Display {
   pub ptr: ffi::EGLDisplay
}

pub struct Config {
   pub ptr: ffi::EGLConfig
}

pub struct Context {
   pub ptr: ffi::EGLContext
}

pub struct Surface {
   pub ptr: ffi::EGLSurface
}

pub struct Version {
   pub major: ffi::EGLint,
   pub minor: ffi::EGLint,
}

pub fn bind_api(api: API) -> Result<(), RuntimeError> {
   let result = unsafe {
      ffi::eglBindAPI(api.into())
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglBindAPI failed".to_string()
      ));
   }

   Ok(())
}

pub fn initialize(display: &Display) -> Result<Version, RuntimeError> {
   let mut major: ffi::EGLint = unsafe {
      mem::uninitialized()
   };
   let mut minor: ffi::EGLint = unsafe {
      mem::uninitialized()
   };

   let result = unsafe {
      ffi::eglInitialize(display.ptr, &mut major, &mut minor)
   };

   match result {
      ffi::EGL_FALSE => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "eglInitialize failed".to_string()
         ));
      },
      ffi::EGL_BAD_DISPLAY => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Not an EGL display connection".to_string()
         ));
      },
      ffi::EGL_NOT_INITIALIZED => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Display cannot be initialized".to_string()
         ));
      },
      ffi::EGL_TRUE => {
         return Ok(Version {
            major: major,
            minor: minor
         });
      },
      _ => {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "Unknown eglInitialize error".to_string()
         ));
      }
   }
}

pub fn configs(display: &Display) -> Result<Vec<Config>, RuntimeError> {
   let mut num_config = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglGetConfigs(
         display.ptr,
         ptr::null_mut(),
         0,
         &mut num_config,
      )
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Getting configs count eglGetConfigs failed".to_string()
      ));
   }

   let mut config_ptrs = Vec::with_capacity(num_config as usize);

   let result = unsafe {
      ffi::eglGetConfigs(
         display.ptr,
         config_ptrs.as_mut_ptr(),
         config_ptrs.capacity() as ffi::EGLint,
         &mut num_config
      )
   };

   unsafe {
      config_ptrs.set_len(num_config as usize)
   };

   if result == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglGetConfigs failed".to_string()
      ));
   }

   let configs = config_ptrs.iter().map(|&ptr| Config {ptr: ptr}).collect();

   for config in &configs {
      print_config(display, config);
   }

   Ok(configs)
}

pub fn choose_config(display: &Display) -> Result<Config, RuntimeError> {
   let config_attribs = [
      ffi::EGL_COLOR_BUFFER_TYPE,    ffi::EGL_RGB_BUFFER,
      ffi::EGL_BUFFER_SIZE,          24,
      ffi::EGL_RED_SIZE,             8,
      ffi::EGL_GREEN_SIZE,           8,
      ffi::EGL_BLUE_SIZE,            8,
      ffi::EGL_ALPHA_SIZE,           0,

      ffi::EGL_DEPTH_SIZE,           0,
      ffi::EGL_STENCIL_SIZE,         0,

      ffi::EGL_SAMPLE_BUFFERS,       0,
      ffi::EGL_SAMPLES,              0,

      ffi::EGL_SURFACE_TYPE,         ffi::EGL_WINDOW_BIT,
      ffi::EGL_RENDERABLE_TYPE,      ffi::EGL_OPENGL_BIT,

      ffi::EGL_NONE
   ];

   let mut num_config: ffi::EGLint = unsafe {
      mem::uninitialized()
   };

   let mut configs: [ffi::EGLConfig; 64] = unsafe {
      mem::uninitialized()
   };

   let result = unsafe {
      ffi::eglChooseConfig(
         display.ptr,
         config_attribs.as_ptr() as *const _,
         configs.as_mut_ptr() as *mut *mut _,
         64,
         &mut num_config
      )
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Choosing config failed".to_string()
      ));
   }

   if num_config == 0 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "Failed to find suitable EGLConfig".to_string()
      ));
   }

   Ok(Config {
      ptr: configs[0]
   })
}

pub fn config_attrib(
   display: &Display,
   config: &Config,
   attribute: ffi::EGLint
) -> Result<ffi::EGLint, RuntimeError> {

   let mut value: ffi::EGLint = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglGetConfigAttrib(display.ptr, config.ptr, attribute, &mut value)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglGetConfigAttrib failed".to_string()
      ));
   }

   Ok(value)
}

pub fn print_config(display: &Display, config: &Config) {
   println!("-------------------------");

   pattr(display, config, "EGL_CONFIG_ID", ffi::EGL_CONFIG_ID);
   pattr(display, config, "EGL_COLOR_BUFFER_TYPE", ffi::EGL_COLOR_BUFFER_TYPE);
   pattr(display, config, "EGL_RENDERABLE_TYPE", ffi::EGL_RENDERABLE_TYPE);
   pattr(display, config, "EGL_SURFACE_TYPE", ffi::EGL_SURFACE_TYPE);
   pattr(display, config, "EGL_TRANSPARENT_TYPE", ffi::EGL_TRANSPARENT_TYPE);
   pattr(display, config, "EGL_NATIVE_VISUAL_TYPE", ffi::EGL_NATIVE_VISUAL_TYPE);
   pattr(display, config, "EGL_NATIVE_VISUAL_ID", ffi::EGL_NATIVE_VISUAL_ID);
   pattr(display, config, "EGL_BUFFER_SIZE", ffi::EGL_BUFFER_SIZE);
   pattr(display, config, "EGL_LUMINANCE_SIZE", ffi::EGL_LUMINANCE_SIZE);
   pattr(display, config, "EGL_DEPTH_SIZE", ffi::EGL_DEPTH_SIZE);
   pattr(display, config, "EGL_STENCIL_SIZE", ffi::EGL_STENCIL_SIZE);
   pattr(display, config, "EGL_RED_SIZE", ffi::EGL_RED_SIZE);
   pattr(display, config, "EGL_GREEN_SIZE", ffi::EGL_GREEN_SIZE);
   pattr(display, config, "EGL_BLUE_SIZE", ffi::EGL_BLUE_SIZE);
   pattr(display, config, "EGL_ALPHA_SIZE", ffi::EGL_ALPHA_SIZE);
   pattr(display, config, "EGL_ALPHA_MASK_SIZE", ffi::EGL_ALPHA_MASK_SIZE);
   pattr(display, config, "EGL_BIND_TO_TEXTURE_RGB", ffi::EGL_BIND_TO_TEXTURE_RGB);
   pattr(display, config, "EGL_BIND_TO_TEXTURE_RGBA", ffi::EGL_BIND_TO_TEXTURE_RGBA);
   pattr(display, config, "EGL_CONFIG_CAVEAT", ffi::EGL_CONFIG_CAVEAT);
   pattr(display, config, "EGL_CONFORMANT", ffi::EGL_CONFORMANT);
   pattr(display, config, "EGL_LEVEL", ffi::EGL_LEVEL);
   pattr(display, config, "EGL_MAX_PBUFFER_WIDTH", ffi::EGL_MAX_PBUFFER_WIDTH);
   pattr(display, config, "EGL_MAX_PBUFFER_HEIGHT", ffi::EGL_MAX_PBUFFER_HEIGHT);
   pattr(display, config, "EGL_MAX_PBUFFER_PIXELS", ffi::EGL_MAX_PBUFFER_PIXELS);
   pattr(display, config, "EGL_MAX_SWAP_INTERVAL", ffi::EGL_MAX_SWAP_INTERVAL);
   pattr(display, config, "EGL_MIN_SWAP_INTERVAL", ffi::EGL_MIN_SWAP_INTERVAL);
   pattr(display, config, "EGL_NATIVE_RENDERABLE", ffi::EGL_NATIVE_RENDERABLE);
   pattr(display, config, "EGL_SAMPLE_BUFFERS", ffi::EGL_SAMPLE_BUFFERS);
   pattr(display, config, "EGL_SAMPLES", ffi::EGL_SAMPLES);
   pattr(display, config, "EGL_TRANSPARENT_RED_VALUE", ffi::EGL_TRANSPARENT_RED_VALUE);
   pattr(display, config, "EGL_TRANSPARENT_GREEN_VALUE", ffi::EGL_TRANSPARENT_GREEN_VALUE);
   pattr(display, config, "EGL_TRANSPARENT_BLUE_VALUE", ffi::EGL_TRANSPARENT_BLUE_VALUE);

   println!("");
}

pub fn pattr(display: &Display, config: &Config, name: &str, attribute: ffi::EGLenum) {
   println!(
      "{}: {}", name, config_attrib(display, config, attribute as ffi::EGLint).unwrap()
   );
}

pub fn create_context(display: &Display, config: &Config) -> Result<Context, RuntimeError> {
   let context_attribs = [ffi::EGL_NONE];

   let context = unsafe {
      ffi::eglCreateContext(
         display.ptr,
         config.ptr as *mut _,
         ffi::EGL_NO_CONTEXT as *mut _,
         context_attribs.as_ptr() as *const _,
      )
   };
   if context.is_null() {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglCreateContext failed".to_string()
      ));
   }

   Ok(Context {
      ptr: context
   })
}

pub fn create_window_surface(
   display: &Display,
   config: &Config,
   window: &EGLNativeWindowType
) -> Result<Surface, RuntimeError> {

   let surface_attribs = [
      ffi::EGL_RENDER_BUFFER, ffi::EGL_BACK_BUFFER,
      ffi::EGL_NONE
   ];

   let surface = unsafe {
      ffi::eglCreateWindowSurface(
         display.ptr,
         config.ptr as *mut _,
         *window,
         surface_attribs.as_ptr() as *const _,
      )
   };
   if surface.is_null() {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglCreateWindowSurface failed".to_string()
      ));
   }

   Ok(Surface {
      ptr: surface
   })
}

pub fn make_current(
   display: &Display,
   draw: &Surface,
   read: &Surface,
   context: &Context,
) -> Result<(), RuntimeError> {

   let made_current = unsafe {
      ffi::eglMakeCurrent(
         display.ptr,
         draw.ptr,
         read.ptr,
         context.ptr
      )
   };

   if made_current != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglMakeCurrent failed".to_string()
      ));
   }

   Ok(())
}

pub fn query_context(
   display: &Display,
   context: &Context,
) -> Result<(), RuntimeError> {

   let mut render_buffer: ffi::EGLint = unsafe { mem::uninitialized() };

   let result = unsafe {
      ffi::eglQueryContext(
         display.ptr,
         context.ptr,
         ffi::EGL_RENDER_BUFFER as i32,
         &mut render_buffer
      )
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglQueyContext (EGL_RENDER_BUFFER) failed".to_string()
      ));
   }

   if render_buffer == ffi::EGL_SINGLE_BUFFER as i32 {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "EGL surface is single buffered".to_string()
      ));
   }

   Ok(())
}

pub fn swap_buffers(
   display: &Display,
   surface: &Surface
) -> Result<(), RuntimeError> {

   let result = unsafe {
      ffi::eglSwapBuffers(display.ptr, surface.ptr)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglSwapBuffers failed".to_string()
      ));
   }

   Ok(())
}

pub fn swap_interval(
   display: &Display,
   interval: ffi::c_int
) -> Result<(), RuntimeError> {

   let result = unsafe {
      ffi::eglSwapInterval(display.ptr, interval)
   };

   if result != ffi::EGL_TRUE {
      return Err(RuntimeError::new(
         ErrorKind::EGL,
         "eglSwapInterval failed".to_string()
      ));
   }

   Ok(())
}

impl Display {
   pub fn from_native(native_display: &NativeDisplay) -> Result<Self, RuntimeError> {
      let ptr = unsafe {
         ffi::eglGetDisplay(native_display.ptr)
      };

      if ptr.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::EGL,
            "eglGetDisplay failed".to_string()
         ));
      }

      Ok(Display {
         ptr: ptr,
      })
   }
}
<|endoftext|>


<commit_before>extern crate syscall;

use std::{env, mem, slice, thread};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use std::cell::Cell;

use color::Color;
use event::{Event, EVENT_RESIZE};
use renderer::Renderer;
use WindowFlag;
use Mode;

pub fn get_display_size() -> Result<(u32, u32), String> {
    let display_path = try!(env::var("DISPLAY").or(Err("DISPLAY not set")));
    match File::open(&display_path) {
        Ok(display) => {
            let mut buf: [u8; 4096] = [0; 4096];
            let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf).map_err(|err| format!("{}", err))?;
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            let res = path.split(":").nth(1).unwrap_or("");
            let width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
            let height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
            Ok((width, height))
        },
        Err(err) => Err(format!("{}", err))
    }
}

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// True if the window should not wait for events
    async: bool,
    /// True if the window can be resized
    resizable: bool,
    /// Drawing mode
    mode: Cell<Mode>,
    /// The input scheme
    file: File,
    /// Window data
    data: &'static mut [Color],
}

impl Renderer for Window {
    /// Get width
    fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    fn height(&self) -> u32 {
        self.h
    }

    /// Access pixel buffer
    fn data(&self) -> &[Color] {
        &self.data
    }

    /// Access pixel buffer mutably
    fn data_mut(&mut self) -> &mut [Color] {
        &mut self.data
    }

    /// Flip the buffer
    fn sync(&mut self) -> bool {
        self.file.sync_data().is_ok()
    }

    /// Set/get mode
    fn mode(&self) -> &Cell<Mode> {
        &self.mode
    }
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
        Window::new_flags(x, y, w, h, title, &[])
    }

    /// Create a new window with flags
    pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, flags: &[WindowFlag]) -> Option<Self> {
        let mut flag_str = String::new();

        let mut async = false;
        let mut resizable = false;
        for &flag in flags.iter() {
            match flag {
                WindowFlag::Async => {
                    async = true;
                    flag_str.push('a');
                },
                WindowFlag::Back => flag_str.push('b'),
                WindowFlag::Front => flag_str.push('f'),
                WindowFlag::Borderless => flag_str.push('l'),
                WindowFlag::Resizable => {
                    resizable = true;
                    flag_str.push('r');
                },
                WindowFlag::Unclosable => flag_str.push('u'),
            }
        }

        if let Ok(file) = File::open(&format!(
            "orbital:{}/{}/{}/{}/{}/{}",
            flag_str, x, y, w, h, title
        )) {
            if let Ok(address) = unsafe { syscall::fmap(file.as_raw_fd(), 0, (w * h * 4) as usize) } {
                Some(Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    async: async,
                    resizable: resizable,
                    mode: Cell::new(Mode::Blend),
                    file: file,
                    data: unsafe { slice::from_raw_parts_mut(address as *mut Color, (w * h) as usize) },
                })
            } else {
                None
            }
        } else {
            None
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        let mut buf: [u8; 4096] = [0; 4096];
        if let Ok(count) = syscall::fpath(self.file.as_raw_fd() as usize, &mut buf) {
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            // orbital:/x/y/w/h/t
            let mut parts = path.split('/').skip(1);
            if let Some(x) = parts.next() {
                self.x = x.parse::<i32>().unwrap_or(0);
            }
            if let Some(y) = parts.next() {
                self.y = y.parse::<i32>().unwrap_or(0);
            }
            if let Some(w) = parts.next() {
                self.w = w.parse::<u32>().unwrap_or(0);
            }
            if let Some(h) = parts.next() {
                self.h = h.parse::<u32>().unwrap_or(0);
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    // Set position
    pub fn set_pos(&mut self, x: i32, y: i32) {
        let _ = self.file.write(&format!("P,{},{}", x, y).as_bytes());
        self.sync_path();
    }

    // Set size
    pub fn set_size(&mut self, width: u32, height: u32) {
        //TODO: Improve safety and reliability
        unsafe {
            syscall::funmap(self.data.as_ptr() as usize).expect("orbclient: failed to unmap memory in resize");
        }
        let _ = self.file.write(&format!("S,{},{}", width, height).as_bytes());
        self.sync_path();
        unsafe {
            let address = syscall::fmap(self.file.as_raw_fd(), 0, (self.w * self.h * 4) as usize).expect("orbclient: failed to map memory in resize");
            self.data = slice::from_raw_parts_mut(address as *mut Color, (self.w * self.h) as usize);
        }
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        let _ = self.file.write(&format!("T,{}", title).as_bytes());
        self.sync_path();
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        let mut iter = EventIter {
            extra: None,
            events: [Event::new(); 16],
            i: 0,
            count: 0
        };

        'blocking: loop {
            if iter.events.len() - iter.count == 0 {
                if iter.extra.is_none() {
                    iter.extra = Some(Vec::with_capacity(32));
                }
                iter.extra.as_mut().unwrap().extend(&iter.events);
                iter.count = 0;
            }
            let bytes = unsafe { slice::from_raw_parts_mut(
                iter.events[iter.count..].as_mut_ptr() as *mut u8,
                iter.events[iter.count..].len() * mem::size_of::<Event>()
            ) };
            match self.file.read(bytes) {
                Ok(0) => if !self.async
                        && iter.extra.is_none()
                        && iter.count == 0 {
                    thread::yield_now();
                } else {
                    break 'blocking;
                },
                Ok(count) => {
                    let count = count / mem::size_of::<Event>();
                    let events = &iter.events[iter.count..][..count];
                    iter.count += count;

                    if self.resizable {
                        let mut resize = None;
                        for event in events {
                            let event = *event;
                            if event.code == EVENT_RESIZE {
                                resize = Some((event.a as u32, event.b as u32));
                            }
                        }
                        if let Some((w, h)) = resize {
                            self.set_size(w, h);
                        }
                    }
                },
                Err(_) => break 'blocking,
            }
        }

        iter
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        let _ = unsafe { syscall::funmap(self.data.as_ptr() as usize) };
    }
}

impl AsRawFd for Window {
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// Event iterator
pub struct EventIter {
    extra: Option<Vec<Event>>,
    events: [Event; 16],
    i: usize,
    count: usize
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        let mut i = self.i;
        if let Some(ref mut extra) = self.extra {
            if i < extra.len() {
                if let Some(event) = extra.get(i) {
                    self.i += 1;
                    return Some(*event);
                }
            }
            i -= extra.len();
        }
        if i < self.count {
            if let Some(event) = self.events.get(i) {
                self.i += 1;
                return Some(*event);
            }
        }
        None
    }
}
<commit_msg>Don't mess with synchronous windows<commit_after>extern crate syscall;

use std::{env, mem, slice, thread};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use std::cell::Cell;

use color::Color;
use event::{Event, EVENT_RESIZE};
use renderer::Renderer;
use WindowFlag;
use Mode;

pub fn get_display_size() -> Result<(u32, u32), String> {
    let display_path = try!(env::var("DISPLAY").or(Err("DISPLAY not set")));
    match File::open(&display_path) {
        Ok(display) => {
            let mut buf: [u8; 4096] = [0; 4096];
            let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf).map_err(|err| format!("{}", err))?;
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            let res = path.split(":").nth(1).unwrap_or("");
            let width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
            let height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
            Ok((width, height))
        },
        Err(err) => Err(format!("{}", err))
    }
}

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// True if the window should not wait for events
    async: bool,
    /// True if the window can be resized
    resizable: bool,
    /// Drawing mode
    mode: Cell<Mode>,
    /// The input scheme
    file: File,
    /// Window data
    data: &'static mut [Color],
}

impl Renderer for Window {
    /// Get width
    fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    fn height(&self) -> u32 {
        self.h
    }

    /// Access pixel buffer
    fn data(&self) -> &[Color] {
        &self.data
    }

    /// Access pixel buffer mutably
    fn data_mut(&mut self) -> &mut [Color] {
        &mut self.data
    }

    /// Flip the buffer
    fn sync(&mut self) -> bool {
        self.file.sync_data().is_ok()
    }

    /// Set/get mode
    fn mode(&self) -> &Cell<Mode> {
        &self.mode
    }
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
        Window::new_flags(x, y, w, h, title, &[])
    }

    /// Create a new window with flags
    pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, flags: &[WindowFlag]) -> Option<Self> {
        let mut flag_str = String::new();

        let mut async = false;
        let mut resizable = false;
        for &flag in flags.iter() {
            match flag {
                WindowFlag::Async => {
                    async = true;
                    flag_str.push('a');
                },
                WindowFlag::Back => flag_str.push('b'),
                WindowFlag::Front => flag_str.push('f'),
                WindowFlag::Borderless => flag_str.push('l'),
                WindowFlag::Resizable => {
                    resizable = true;
                    flag_str.push('r');
                },
                WindowFlag::Unclosable => flag_str.push('u'),
            }
        }

        if let Ok(file) = File::open(&format!(
            "orbital:{}/{}/{}/{}/{}/{}",
            flag_str, x, y, w, h, title
        )) {
            if let Ok(address) = unsafe { syscall::fmap(file.as_raw_fd(), 0, (w * h * 4) as usize) } {
                Some(Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    async: async,
                    resizable: resizable,
                    mode: Cell::new(Mode::Blend),
                    file: file,
                    data: unsafe { slice::from_raw_parts_mut(address as *mut Color, (w * h) as usize) },
                })
            } else {
                None
            }
        } else {
            None
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        let mut buf: [u8; 4096] = [0; 4096];
        if let Ok(count) = syscall::fpath(self.file.as_raw_fd() as usize, &mut buf) {
            let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
            // orbital:/x/y/w/h/t
            let mut parts = path.split('/').skip(1);
            if let Some(x) = parts.next() {
                self.x = x.parse::<i32>().unwrap_or(0);
            }
            if let Some(y) = parts.next() {
                self.y = y.parse::<i32>().unwrap_or(0);
            }
            if let Some(w) = parts.next() {
                self.w = w.parse::<u32>().unwrap_or(0);
            }
            if let Some(h) = parts.next() {
                self.h = h.parse::<u32>().unwrap_or(0);
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    // Set position
    pub fn set_pos(&mut self, x: i32, y: i32) {
        let _ = self.file.write(&format!("P,{},{}", x, y).as_bytes());
        self.sync_path();
    }

    // Set size
    pub fn set_size(&mut self, width: u32, height: u32) {
        //TODO: Improve safety and reliability
        unsafe {
            syscall::funmap(self.data.as_ptr() as usize).expect("orbclient: failed to unmap memory in resize");
        }
        let _ = self.file.write(&format!("S,{},{}", width, height).as_bytes());
        self.sync_path();
        unsafe {
            let address = syscall::fmap(self.file.as_raw_fd(), 0, (self.w * self.h * 4) as usize).expect("orbclient: failed to map memory in resize");
            self.data = slice::from_raw_parts_mut(address as *mut Color, (self.w * self.h) as usize);
        }
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        let _ = self.file.write(&format!("T,{}", title).as_bytes());
        self.sync_path();
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        let mut iter = EventIter {
            extra: None,
            events: [Event::new(); 16],
            i: 0,
            count: 0
        };

        'blocking: loop {
            if iter.events.len() - iter.count == 0 {
                if iter.extra.is_none() {
                    iter.extra = Some(Vec::with_capacity(32));
                }
                iter.extra.as_mut().unwrap().extend(&iter.events);
                iter.count = 0;
            }
            let bytes = unsafe { slice::from_raw_parts_mut(
                iter.events[iter.count..].as_mut_ptr() as *mut u8,
                iter.events[iter.count..].len() * mem::size_of::<Event>()
            ) };
            match self.file.read(bytes) {
                Ok(0) => if !self.async
                        && iter.extra.is_none()
                        && iter.count == 0 {
                    thread::yield_now();
                } else {
                    break 'blocking;
                },
                Ok(count) => {
                    let count = count / mem::size_of::<Event>();
                    let events = &iter.events[iter.count..][..count];
                    iter.count += count;

                    if self.resizable {
                        let mut resize = None;
                        for event in events {
                            let event = *event;
                            if event.code == EVENT_RESIZE {
                                resize = Some((event.a as u32, event.b as u32));
                            }
                        }
                        if let Some((w, h)) = resize {
                            self.set_size(w, h);
                        }
                    }
                    if !self.async {
                        // Synchronous windows are blocking, can't attempt another read
                        break 'blocking;
                    }
                },
                Err(_) => break 'blocking,
            }
        }

        iter
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        let _ = unsafe { syscall::funmap(self.data.as_ptr() as usize) };
    }
}

impl AsRawFd for Window {
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}

/// Event iterator
pub struct EventIter {
    extra: Option<Vec<Event>>,
    events: [Event; 16],
    i: usize,
    count: usize
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        let mut i = self.i;
        if let Some(ref mut extra) = self.extra {
            if i < extra.len() {
                if let Some(event) = extra.get(i) {
                    self.i += 1;
                    return Some(*event);
                }
            }
            i -= extra.len();
        }
        if i < self.count {
            if let Some(event) = self.events.get(i) {
                self.i += 1;
                return Some(*event);
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>use crate::audio::SoundSource;
use crate::tests;
use crate::*;

#[test]
fn audio_load_ogg() {
    let (c, _e) = &mut tests::make_context();

    // OGG format
    let filename = "/pew.ogg";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn audio_load_wav() {
    let (c, _e) = &mut tests::make_context();

    // WAV format
    let filename = "/pew.wav";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn audio_load_flac() {
    let (c, _e) = &mut tests::make_context();

    // FLAC format
    let filename = "/pew.flac";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn fail_when_loading_nonexistent_file() {
    let (c, _e) = &mut tests::make_context();

    // File does not exist
    let filename = "/does-not-exist.ogg";
    assert!(audio::Source::new(c, filename).is_err());
    assert!(audio::SpatialSource::new(c, filename).is_err());
}

#[test]
fn fail_when_loading_non_audio_file() {
    let (c, _e) = &mut tests::make_context();

    let filename = "/player.png";
    assert!(audio::Source::new(c, filename).is_err());
    assert!(audio::SpatialSource::new(c, filename).is_err());
}

#[test]
fn playing_returns_correct_value_based_on_state() {
    let (c, _e) = &mut tests::make_context();

    let mut sound = audio::Source::new(c, "/pew.ogg").unwrap();
    assert!(!sound.playing());

    sound.play().unwrap();
    assert!(sound.playing());

    sound.pause();
    assert!(!sound.playing());

    sound.resume();
    assert!(sound.playing());

    sound.stop();
    assert!(!sound.playing());
}

#[test]
fn paused_returns_correct_value_based_on_state() {
    let (c, _e) = &mut tests::make_context();

    let mut sound = audio::Source::new(c, "/pew.ogg").unwrap();
    assert!(!sound.paused());

    sound.play().unwrap();
    assert!(!sound.paused());

    sound.pause();
    assert!(sound.paused());

    sound.resume();
    assert!(!sound.paused());

    sound.pause();
    assert!(sound.paused());

    sound.stop();
    assert!(!sound.paused());
}

#[test]
fn volume_persists_after_stop() {
    let (c, _e) = &mut tests::make_context();
    let filename = "/pew.ogg";
    {
        let volume = 0.8;
        let mut sound = audio::Source::new(c, filename).unwrap();
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.stop();
        assert_eq!(sound.volume(), volume);
    }

    {
        let volume = 0.8;
        let mut sound = audio::SpatialSource::new(c, filename).unwrap();
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.stop();
        assert_eq!(sound.volume(), volume);
    }
}

#[test]
fn volume_persists_after_play() {
    let (c, _e) = &mut tests::make_context();
    let filename = "/pew.ogg";
    {
        let volume = 0.8;
        let mut sound = audio::Source::new(c, filename).unwrap();
        assert_eq!(sound.volume(), 1.0);
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.play().unwrap();
        assert_eq!(sound.volume(), volume);
    }

    {
        let volume = 0.8;
        let mut sound = audio::SpatialSource::new(c, filename).unwrap();
        assert_eq!(sound.volume(), 1.0);
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.play().unwrap();
        assert_eq!(sound.volume(), volume);
    }
}
<commit_msg>Reduced duplication in tests for Source vs SpatialSource<commit_after>use crate::audio::SoundSource;
use crate::tests;
use crate::*;

#[test]
fn audio_load_ogg() {
    let (c, _e) = &mut tests::make_context();

    // OGG format
    let filename = "/pew.ogg";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn audio_load_wav() {
    let (c, _e) = &mut tests::make_context();

    // WAV format
    let filename = "/pew.wav";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn audio_load_flac() {
    let (c, _e) = &mut tests::make_context();

    // FLAC format
    let filename = "/pew.flac";
    let _sound = audio::Source::new(c, filename).unwrap();
    let _sound = audio::SpatialSource::new(c, filename).unwrap();
}

#[test]
fn fail_when_loading_nonexistent_file() {
    let (c, _e) = &mut tests::make_context();

    // File does not exist
    let filename = "/does-not-exist.ogg";
    assert!(audio::Source::new(c, filename).is_err());
    assert!(audio::SpatialSource::new(c, filename).is_err());
}

#[test]
fn fail_when_loading_non_audio_file() {
    let (c, _e) = &mut tests::make_context();

    let filename = "/player.png";
    assert!(audio::Source::new(c, filename).is_err());
    assert!(audio::SpatialSource::new(c, filename).is_err());
}

#[test]
fn playing_returns_correct_value_based_on_state() {
    let (c, _e) = &mut tests::make_context();

    let mut sound = audio::Source::new(c, "/pew.ogg").unwrap();
    assert!(!sound.playing());

    sound.play().unwrap();
    assert!(sound.playing());

    sound.pause();
    assert!(!sound.playing());

    sound.resume();
    assert!(sound.playing());

    sound.stop();
    assert!(!sound.playing());
}

#[test]
fn paused_returns_correct_value_based_on_state() {
    let (c, _e) = &mut tests::make_context();

    let mut sound = audio::Source::new(c, "/pew.ogg").unwrap();
    assert!(!sound.paused());

    sound.play().unwrap();
    assert!(!sound.paused());

    sound.pause();
    assert!(sound.paused());

    sound.resume();
    assert!(!sound.paused());

    sound.pause();
    assert!(sound.paused());

    sound.stop();
    assert!(!sound.paused());
}

#[test]
fn volume_persists_after_stop() {
    let (c, _e) = &mut tests::make_context();
    let filename = "/pew.ogg";
    test_volume_after_stop(audio::Source::new(c, filename).unwrap());
    test_volume_after_stop(audio::SpatialSource::new(c, filename).unwrap());

    fn test_volume_after_stop(mut sound: impl SoundSource) {
        let volume = 0.8;
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.stop();
        assert_eq!(sound.volume(), volume);
    }
}

#[test]
fn volume_persists_after_play() {
    let (c, _e) = &mut tests::make_context();
    let filename = "/pew.ogg";
    test_volume(audio::Source::new(c, filename).unwrap());
    test_volume(audio::SpatialSource::new(c, filename).unwrap());

    fn test_volume(mut sound: impl SoundSource) {
        let volume = 0.8;
        assert_eq!(sound.volume(), 1.0);
        sound.set_volume(volume);
        assert_eq!(sound.volume(), volume);
        sound.play().unwrap();
        assert_eq!(sound.volume(), volume);
    }
}
<|endoftext|>


<commit_before>pub use self::{memory_rgba8_texture::MemoryRGBA8Texture, sub_texture::SubTexture};
use std::ops::{Deref, DerefMut};

pub mod image_texture;
pub mod memory_rgba8_texture;
pub mod sub_texture;

pub trait Texture {
    type Pixel: Pixel;

    fn width(&self) -> u32;
    fn height(&self) -> u32;
    // TODO: Chanage return value to &-ptr
    fn get(&self, x: u32, y: u32) -> Option<Self::Pixel>;
    fn set(&mut self, x: u32, y: u32, val: Self::Pixel);

    fn get_rotated(&self, x: u32, y: u32) -> Option<Self::Pixel> {
        let w = self.height();
        self.get(y, w - x - 1)
    }

    fn is_column_transparent(&self, col: u32) -> bool {
        for y in 0..self.height() {
            if let Some(p) = self.get(col, y) {
                if !p.is_transparent() {
                    return false;
                }
            }
        }
        true
    }

    fn is_row_transparent(&self, row: u32) -> bool {
        for x in 0..self.width() {
            if let Some(p) = self.get(x, row) {
                if !p.is_transparent() {
                    return false;
                }
            }
        }
        true
    }
}

pub trait Pixel: Sized {
    fn is_transparent(&self) -> bool;
    fn transparency() -> Option<Self>;
    fn outline() -> Self;
}

impl<P: Pixel> Texture for Box<dyn Texture<Pixel = P> + 'static> {
    type Pixel = P;

    fn width(&self) -> u32 {
        self.deref().width()
    }

    fn height(&self) -> u32 {
        self.deref().height()
    }

    fn get(&self, x: u32, y: u32) -> Option<P> {
        self.deref().get(x, y)
    }

    fn set(&mut self, x: u32, y: u32, val: P) {
        self.deref_mut().set(x, y, val);
    }
}
<commit_msg>docs: Document texture module contents<commit_after>//! Traits for a texture and its pixel contents.
pub use self::{memory_rgba8_texture::MemoryRGBA8Texture, sub_texture::SubTexture};
use std::ops::{Deref, DerefMut};

pub mod image_texture;
pub mod memory_rgba8_texture;
pub mod sub_texture;

/// Describes a texture type.
pub trait Texture {
    /// Pixel type of this texture.
    type Pixel: Pixel;

    /// Get the width of this texture.
    fn width(&self) -> u32;
    /// Get the height of this texture.
    fn height(&self) -> u32;
    // TODO: Chanage return value to &-ptr
    /// Get the pixel value at a specific coordinate.
    fn get(&self, x: u32, y: u32) -> Option<Self::Pixel>;
    /// Set the pixel value at a specific coordinate.
    fn set(&mut self, x: u32, y: u32, val: Self::Pixel);

    /// Get the pixel if it were transformed by a rotation.
    fn get_rotated(&self, x: u32, y: u32) -> Option<Self::Pixel> {
        let w = self.height();
        self.get(y, w - x - 1)
    }

    /// Check if a column of the texture is transparent.
    fn is_column_transparent(&self, col: u32) -> bool {
        for y in 0..self.height() {
            if let Some(p) = self.get(col, y) {
                if !p.is_transparent() {
                    return false;
                }
            }
        }
        true
    }

    /// Check if a row of the texture is transparent.
    fn is_row_transparent(&self, row: u32) -> bool {
        for x in 0..self.width() {
            if let Some(p) = self.get(x, row) {
                if !p.is_transparent() {
                    return false;
                }
            }
        }
        true
    }
}

/// Describes a pixel type.
pub trait Pixel: Sized {
    /// If the pixel is transparent.
    fn is_transparent(&self) -> bool;
    /// The transparent value for this pixel type.
    fn transparency() -> Option<Self>;
    /// Outline value for this pixel type.
    fn outline() -> Self;
}

impl<P: Pixel> Texture for Box<dyn Texture<Pixel = P> + 'static> {
    type Pixel = P;

    fn width(&self) -> u32 {
        self.deref().width()
    }

    fn height(&self) -> u32 {
        self.deref().height()
    }

    fn get(&self, x: u32, y: u32) -> Option<P> {
        self.deref().get(x, y)
    }

    fn set(&mut self, x: u32, y: u32, val: P) {
        self.deref_mut().set(x, y, val);
    }
}
<|endoftext|>