<commit_before>use std::ops;

///A 2D Vector with x and y coordinates: Vector2
#[derive(PartialEq, Debug)]
pub struct Vector2 {
    x: f32,
    y: f32,
}

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

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

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

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

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

    ///Defines a 2D Vector with x=1 and y=1
    pub fn ONE() -> Vector2 {
        Vector2 {x: 1f32, y: 1f32}
    }

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

    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2))
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector2 {x: 3f32, y: 4f32};
        assert_eq!(vec.magnitude(), 5f32);
    }

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

    #[test]
    fn dot_product() {
        let vec1 = Vector2 {x: 2f32, y: 1f32};
        let vec2 = Vector2 {x: 1f32, y: 2f32};
        let actual = vec1 * vec2;
        let expected = 2f32 * f32::sqrt(2f32);
        assert_eq!(actual.magnitude(), expected);
    }
}
<commit_msg>corrects dot product<commit_after>use std::ops;

///A 2D Vector with x and y coordinates: Vector2
#[derive(PartialEq, Debug)]
pub struct Vector2 {
    x: f32,
    y: f32,
}

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

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

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

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

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

    ///Defines a 2D Vector with x=1 and y=1
    pub fn ONE() -> Vector2 {
        Vector2 {x: 1f32, y: 1f32}
    }

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

    pub fn magnitude(self) -> f32 {
        f32::sqrt(self.x.powi(2) + self.y.powi(2))
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[test]
    fn magnitude_of_vector() {
        let vec = Vector2 {x: 3f32, y: 4f32};
        assert_eq!(vec.magnitude(), 5f32);
    }

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

    #[test]
    fn dot_product() {
        let vec1 = Vector2 {x: 2f32, y: 1f32};
        let vec2 = Vector2 {x: 1f32, y: 2f32};
        let actual = vec1 * vec2;
        let expected = 4f32;
        assert_eq!(actual, expected);
    }
}
<|endoftext|>


<commit_before>//! Operations on ASCII strings and characters.
//!
//! Most string operations in Rust act on UTF-8 strings. However, at times it
//! makes more sense to only consider the ASCII character set for a specific
//! operation.
//!
//! The [`escape_default`] function provides an iterator over the bytes of an
//! escaped version of the character given.

#![stable(feature = "core_ascii", since = "1.26.0")]

use crate::fmt;
use crate::iter::FusedIterator;
use crate::ops::Range;
use crate::str::from_utf8_unchecked;

/// An iterator over the escaped version of a byte.
///
/// This `struct` is created by the [`escape_default`] function. See its
/// documentation for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EscapeDefault {
    range: Range<usize>,
    data: [u8; 4],
}

/// Returns an iterator that produces an escaped version of a `u8`.
///
/// The default is chosen with a bias toward producing literals that are
/// legal in a variety of languages, including C++11 and similar C-family
/// languages. The exact rules are:
///
/// * Tab is escaped as `\t`.
/// * Carriage return is escaped as `\r`.
/// * Line feed is escaped as `\n`.
/// * Single quote is escaped as `\'`.
/// * Double quote is escaped as `\"`.
/// * Backslash is escaped as `\\`.
/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
///   inclusive is not escaped.
/// * Any other chars are given hex escapes of the form '\xNN'.
/// * Unicode escapes are never generated by this function.
///
/// # Examples
///
/// ```
/// use std::ascii;
///
/// let escaped = ascii::escape_default(b'0').next().unwrap();
/// assert_eq!(b'0', escaped);
///
/// let mut escaped = ascii::escape_default(b'\t');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\r');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'r', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\n');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'n', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\'');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\'', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'"');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'"', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\\');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\\', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\x9d');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'x', escaped.next().unwrap());
/// assert_eq!(b'9', escaped.next().unwrap());
/// assert_eq!(b'd', escaped.next().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault {
    let (data, len) = match c {
        b'\t' => ([b'\\', b't', 0, 0], 2),
        b'\r' => ([b'\\', b'r', 0, 0], 2),
        b'\n' => ([b'\\', b'n', 0, 0], 2),
        b'\\' => ([b'\\', b'\\', 0, 0], 2),
        b'\'' => ([b'\\', b'\'', 0, 0], 2),
        b'"' => ([b'\\', b'"', 0, 0], 2),
        b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
    };

    return EscapeDefault { range: 0..len, data };

    fn hexify(b: u8) -> u8 {
        match b {
            0..=9 => b'0' + b,
            _ => b'a' + b - 10,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        self.range.next().map(|i| self.data[i])
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
    fn last(mut self) -> Option<u8> {
        self.next_back()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
    fn next_back(&mut self) -> Option<u8> {
        self.range.next_back().map(|i| self.data[i])
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}

#[stable(feature = "ascii_escape_display", since = "1.39.0")]
impl fmt::Display for EscapeDefault {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // SAFETY: ok because `escape_default` created only valid utf-8 data
        f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("EscapeDefault").finish_non_exhaustive()
    }
}
<commit_msg>EscapeDefault: change `range` field to `Range<u8>`, reducing struct size 24 -> 6 bytes<commit_after>//! Operations on ASCII strings and characters.
//!
//! Most string operations in Rust act on UTF-8 strings. However, at times it
//! makes more sense to only consider the ASCII character set for a specific
//! operation.
//!
//! The [`escape_default`] function provides an iterator over the bytes of an
//! escaped version of the character given.

#![stable(feature = "core_ascii", since = "1.26.0")]

use crate::fmt;
use crate::iter::FusedIterator;
use crate::ops::Range;
use crate::str::from_utf8_unchecked;

/// An iterator over the escaped version of a byte.
///
/// This `struct` is created by the [`escape_default`] function. See its
/// documentation for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EscapeDefault {
    range: Range<u8>,
    data: [u8; 4],
}

/// Returns an iterator that produces an escaped version of a `u8`.
///
/// The default is chosen with a bias toward producing literals that are
/// legal in a variety of languages, including C++11 and similar C-family
/// languages. The exact rules are:
///
/// * Tab is escaped as `\t`.
/// * Carriage return is escaped as `\r`.
/// * Line feed is escaped as `\n`.
/// * Single quote is escaped as `\'`.
/// * Double quote is escaped as `\"`.
/// * Backslash is escaped as `\\`.
/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
///   inclusive is not escaped.
/// * Any other chars are given hex escapes of the form '\xNN'.
/// * Unicode escapes are never generated by this function.
///
/// # Examples
///
/// ```
/// use std::ascii;
///
/// let escaped = ascii::escape_default(b'0').next().unwrap();
/// assert_eq!(b'0', escaped);
///
/// let mut escaped = ascii::escape_default(b'\t');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b't', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\r');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'r', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\n');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'n', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\'');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\'', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'"');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'"', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\\');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'\\', escaped.next().unwrap());
///
/// let mut escaped = ascii::escape_default(b'\x9d');
///
/// assert_eq!(b'\\', escaped.next().unwrap());
/// assert_eq!(b'x', escaped.next().unwrap());
/// assert_eq!(b'9', escaped.next().unwrap());
/// assert_eq!(b'd', escaped.next().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn escape_default(c: u8) -> EscapeDefault {
    let (data, len) = match c {
        b'\t' => ([b'\\', b't', 0, 0], 2),
        b'\r' => ([b'\\', b'r', 0, 0], 2),
        b'\n' => ([b'\\', b'n', 0, 0], 2),
        b'\\' => ([b'\\', b'\\', 0, 0], 2),
        b'\'' => ([b'\\', b'\'', 0, 0], 2),
        b'"' => ([b'\\', b'"', 0, 0], 2),
        b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
    };

    return EscapeDefault { range: 0..len, data };

    fn hexify(b: u8) -> u8 {
        match b {
            0..=9 => b'0' + b,
            _ => b'a' + b - 10,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault {
    type Item = u8;
    fn next(&mut self) -> Option<u8> {
        self.range.next().map(|i| self.data[i as usize])
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
    fn last(mut self) -> Option<u8> {
        self.next_back()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
    fn next_back(&mut self) -> Option<u8> {
        self.range.next_back().map(|i| self.data[i as usize])
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}

#[stable(feature = "ascii_escape_display", since = "1.39.0")]
impl fmt::Display for EscapeDefault {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // SAFETY: ok because `escape_default` created only valid utf-8 data
        f.write_str(unsafe {
            from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
        })
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("EscapeDefault").finish_non_exhaustive()
    }
}
<|endoftext|>


<commit_before>use diesel::prelude::*;
use std::path::{Path, PathBuf};

use super::*;
use crate::app::{config, user, vfs};
use crate::db::{self, directories, songs};
use crate::test_name;

fn get_context(test_name: &str) -> (db::DB, Index) {
	let db = db::get_test_db(test_name);
	let vfs_manager = vfs::Manager::new(db.clone());
	let user_manager = user::Manager::new(db.clone());
	let config_manager = config::Manager::new(db.clone(), user_manager);
	let index = Index::new(db.clone(), vfs_manager, config_manager);
	(db, index)
}

#[test]
fn test_populate() {
	let (db, index) = get_context(&test_name!());
	index.update().unwrap();
	index.update().unwrap(); // Validates that subsequent updates don't run into conflicts

	let connection = db.connect().unwrap();
	let all_directories: Vec<Directory> = directories::table.load(&connection).unwrap();
	let all_songs: Vec<Song> = songs::table.load(&connection).unwrap();
	assert_eq!(all_directories.len(), 6);
	assert_eq!(all_songs.len(), 13);
}

#[test]
fn test_metadata() {
	let target: PathBuf = ["test-data", "small-collection", "Tobokegao", "Picnic"]
		.iter()
		.collect();

	let mut song_path = target.clone();
	song_path.push("05 - シャーベット (Sherbet).mp3");

	let mut artwork_path = target.clone();
	artwork_path.push("Folder.png");

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("シャーベット (Sherbet)"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(song.path, song_path.to_string_lossy().as_ref());
	assert_eq!(song.track_number, Some(5));
	assert_eq!(song.disc_number, None);
	assert_eq!(song.title, Some("シャーベット (Sherbet)".to_owned()));
	assert_eq!(song.artist, Some("Tobokegao".to_owned()));
	assert_eq!(song.album_artist, None);
	assert_eq!(song.album, Some("Picnic".to_owned()));
	assert_eq!(song.year, Some(2016));
	assert_eq!(
		song.artwork,
		Some(artwork_path.to_string_lossy().into_owned())
	);
}

#[test]
fn test_artwork_pattern_case_insensitive() {
	let target: PathBuf = ["test-data", "small-collection", "Khemmis", "Hunted"]
		.iter()
		.collect();

	let mut song_path = target.clone();
	song_path.push("05 - Hunted.mp3");

	let mut artwork_path = target.clone();
	artwork_path.push("folder.jpg");

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("Hunted"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(
		song.artwork,
		Some(artwork_path.to_string_lossy().into_owned())
	);
}

#[test]
fn test_embedded_artwork() {
	let song_path: PathBuf = [
		"test-data",
		"small-collection",
		"Tobokegao",
		"Picnic",
		"07 - なぜ (Why).mp3",
	]
	.iter()
	.collect();

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("なぜ (Why?)"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(song.artwork, Some(song_path.to_string_lossy().into_owned()));
}

#[test]
fn test_browse_top_level() {
	let mut root_path = PathBuf::new();
	root_path.push("root");

	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.browse(Path::new("")).unwrap();

	assert_eq!(results.len(), 1);
	match results[0] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
}

#[test]
fn test_browse() {
	let khemmis_path: PathBuf = ["root", "Khemmis"].iter().collect();
	let tobokegao_path: PathBuf = ["root", "Tobokegao"].iter().collect();

	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.browse(Path::new("root")).unwrap();

	assert_eq!(results.len(), 2);
	match results[0] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
	match results[1] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
}

#[test]
fn test_flatten() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	// Flatten all
	let results = index.flatten(Path::new("root")).unwrap();
	assert_eq!(results.len(), 13);
	assert_eq!(results[0].title, Some("Above The Water".to_owned()));

	// Flatten a directory
	let path: PathBuf = ["root", "Tobokegao"].iter().collect();
	let results = index.flatten(&path).unwrap();
	assert_eq!(results.len(), 8);

	// Flatten a directory that is a prefix of another directory (Picnic Remixes)
	let path: PathBuf = ["root", "Tobokegao", "Picnic"].iter().collect();
	let results = index.flatten(&path).unwrap();
	assert_eq!(results.len(), 7);
}

#[test]
fn test_random() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.get_random_albums(1).unwrap();
	assert_eq!(results.len(), 1);
}

#[test]
fn test_recent() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.get_recent_albums(2).unwrap();
	assert_eq!(results.len(), 2);
	assert!(results[0].date_added >= results[1].date_added);
}

#[test]
fn test_get_song() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let song_path: PathBuf = ["root", "Khemmis", "Hunted", "02 - Candlelight.mp3"]
		.iter()
		.collect();

	let song = index.get_song(&song_path).unwrap();
	assert_eq!(song.title.unwrap(), "Candlelight");
}
<commit_msg>Fixed test on linux<commit_after>use diesel::prelude::*;
use std::path::{Path, PathBuf};

use super::*;
use crate::app::{config, user, vfs};
use crate::db::{self, directories, songs};
use crate::test_name;

fn get_context(test_name: &str) -> (db::DB, Index) {
	let db = db::get_test_db(test_name);
	let vfs_manager = vfs::Manager::new(db.clone());
	let user_manager = user::Manager::new(db.clone());
	let config_manager = config::Manager::new(db.clone(), user_manager);
	let index = Index::new(db.clone(), vfs_manager, config_manager);
	(db, index)
}

#[test]
fn test_populate() {
	let (db, index) = get_context(&test_name!());
	index.update().unwrap();
	index.update().unwrap(); // Validates that subsequent updates don't run into conflicts

	let connection = db.connect().unwrap();
	let all_directories: Vec<Directory> = directories::table.load(&connection).unwrap();
	let all_songs: Vec<Song> = songs::table.load(&connection).unwrap();
	assert_eq!(all_directories.len(), 6);
	assert_eq!(all_songs.len(), 13);
}

#[test]
fn test_metadata() {
	let target: PathBuf = ["test-data", "small-collection", "Tobokegao", "Picnic"]
		.iter()
		.collect();

	let mut song_path = target.clone();
	song_path.push("05 - シャーベット (Sherbet).mp3");

	let mut artwork_path = target.clone();
	artwork_path.push("Folder.png");

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("シャーベット (Sherbet)"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(song.path, song_path.to_string_lossy().as_ref());
	assert_eq!(song.track_number, Some(5));
	assert_eq!(song.disc_number, None);
	assert_eq!(song.title, Some("シャーベット (Sherbet)".to_owned()));
	assert_eq!(song.artist, Some("Tobokegao".to_owned()));
	assert_eq!(song.album_artist, None);
	assert_eq!(song.album, Some("Picnic".to_owned()));
	assert_eq!(song.year, Some(2016));
	assert_eq!(
		song.artwork,
		Some(artwork_path.to_string_lossy().into_owned())
	);
}

#[test]
fn test_artwork_pattern_case_insensitive() {
	let target: PathBuf = ["test-data", "small-collection", "Khemmis", "Hunted"]
		.iter()
		.collect();

	let mut song_path = target.clone();
	song_path.push("05 - Hunted.mp3");

	let mut artwork_path = target.clone();
	artwork_path.push("folder.jpg");

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("Hunted"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(
		song.artwork.as_ref().unwrap().to_lowercase(),
		artwork_path.to_string_lossy().to_lowercase()
	);
}

#[test]
fn test_embedded_artwork() {
	let song_path: PathBuf = [
		"test-data",
		"small-collection",
		"Tobokegao",
		"Picnic",
		"07 - なぜ (Why).mp3",
	]
	.iter()
	.collect();

	let (db, index) = get_context(&test_name!());
	index.update().unwrap();

	let connection = db.connect().unwrap();
	let songs: Vec<Song> = songs::table
		.filter(songs::title.eq("なぜ (Why?)"))
		.load(&connection)
		.unwrap();

	assert_eq!(songs.len(), 1);
	let song = &songs[0];
	assert_eq!(song.artwork, Some(song_path.to_string_lossy().into_owned()));
}

#[test]
fn test_browse_top_level() {
	let mut root_path = PathBuf::new();
	root_path.push("root");

	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.browse(Path::new("")).unwrap();

	assert_eq!(results.len(), 1);
	match results[0] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, root_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
}

#[test]
fn test_browse() {
	let khemmis_path: PathBuf = ["root", "Khemmis"].iter().collect();
	let tobokegao_path: PathBuf = ["root", "Tobokegao"].iter().collect();

	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.browse(Path::new("root")).unwrap();

	assert_eq!(results.len(), 2);
	match results[0] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, khemmis_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
	match results[1] {
		CollectionFile::Directory(ref d) => assert_eq!(d.path, tobokegao_path.to_str().unwrap()),
		_ => panic!("Expected directory"),
	}
}

#[test]
fn test_flatten() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	// Flatten all
	let results = index.flatten(Path::new("root")).unwrap();
	assert_eq!(results.len(), 13);
	assert_eq!(results[0].title, Some("Above The Water".to_owned()));

	// Flatten a directory
	let path: PathBuf = ["root", "Tobokegao"].iter().collect();
	let results = index.flatten(&path).unwrap();
	assert_eq!(results.len(), 8);

	// Flatten a directory that is a prefix of another directory (Picnic Remixes)
	let path: PathBuf = ["root", "Tobokegao", "Picnic"].iter().collect();
	let results = index.flatten(&path).unwrap();
	assert_eq!(results.len(), 7);
}

#[test]
fn test_random() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.get_random_albums(1).unwrap();
	assert_eq!(results.len(), 1);
}

#[test]
fn test_recent() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let results = index.get_recent_albums(2).unwrap();
	assert_eq!(results.len(), 2);
	assert!(results[0].date_added >= results[1].date_added);
}

#[test]
fn test_get_song() {
	let (_db, index) = get_context(&test_name!());
	index.update().unwrap();

	let song_path: PathBuf = ["root", "Khemmis", "Hunted", "02 - Candlelight.mp3"]
		.iter()
		.collect();

	let song = index.get_song(&song_path).unwrap();
	assert_eq!(song.title.unwrap(), "Candlelight");
}
<|endoftext|>


<commit_before>//! A system for creating and managing IRC server connections.
//!
//! This API provides the ability to create and manage multiple IRC servers that can run on the same
//! thread through the use of a shared event loop. It can also be used to encapsulate the dependency
//! on `tokio` and `futures` in the use of `IrcServer::new_future`. This means that knowledge of
//! those libraries should be unnecessary for the average user. Nevertheless, this API also provides
//! some escape hatches that let advanced users take further advantage of these dependencies.
//!
//! # Example
//! ```no_run
//! # extern crate irc;
//! # use std::default::Default;
//! use irc::client::prelude::*;
//! use irc::error;
//!
//! fn main() {
//!   let config = Config::default();
//!   let mut reactor = IrcReactor::new().unwrap();
//!   let server = reactor.prepare_server_and_connect(&config).unwrap();
//!   reactor.register_server_with_handler(server, process_msg);
//!   reactor.run().unwrap();
//! }
//! # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
//! ```

use futures::{Future, IntoFuture, Stream};
use futures::future;
use tokio_core::reactor::{Core, Handle};

use client::data::Config;
use client::server::{IrcServer, IrcServerFuture, PackedIrcServer, Server};
use error;
use proto::Message;

/// A thin wrapper over an event loop.
///
/// An IRC reactor is used to create new connections to IRC servers and to drive the management of
/// all connected servers as the application runs. It can be used to run multiple servers on the
/// same thread, as well as to get better control over error management in an IRC client.
///
/// For a full example usage, see [irc::client::reactor](./index.html).
pub struct IrcReactor {
    inner: Core,
    handlers: Vec<Box<Future<Item = (), Error = error::Error>>>,
}

impl IrcReactor {
    /// Creates a new reactor.
    pub fn new() -> error::Result<IrcReactor> {
        Ok(IrcReactor {
            inner: Core::new()?,
            handlers: Vec::new(),
        })
    }

    /// Creates a representation of an IRC server that has not yet attempted to connect. In
    /// particular, this representation is as a Future that when run will produce a connected
    /// [IrcServer](./server/struct.IrcServer.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let future_server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_server<'a>(&mut self, config: &'a Config) -> error::Result<IrcServerFuture<'a>> {
        IrcServer::new_future(self.inner_handle(), config)
    }

    /// Runs an [IrcServerFuture](./server/struct.IrcServerFuture.html), such as one from
    /// `prepare_server` to completion, yielding an [IrcServer](./server/struct.IrcServer.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server(&config).and_then(|future| {
    ///         reactor.connect_server(future)
    ///     })
    /// });
    /// # }
    /// ```
    pub fn connect_server(&mut self, future: IrcServerFuture) -> error::Result<IrcServer> {
        self.inner.run(future).map(|PackedIrcServer(server, future)| {
            self.register_future(future);
            server
        })
    }

    /// Creates a new IRC server from the specified configuration, connecting immediately. This is
    /// guaranteed to be the composition of prepare_server and connect_server.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server_and_connect(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_server_and_connect(&mut self, config: &Config) -> error::Result<IrcServer> {
        self.prepare_server(config).and_then(|future| self.connect_server(future))
    }

    /// Registers the given server with the specified message handler. The reactor will store this
    /// setup until the next call to run, where it will be used to process new messages over the
    /// connection indefinitely (or until failure). As registration is consumed by `run`, subsequent
    /// calls to run will require new registration.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let server = reactor.prepare_server_and_connect(&config).unwrap();
    /// reactor.register_server_with_handler(server, |server, msg| {
    ///   // Message processing happens here.
    ///   Ok(())
    /// })
    /// # }
    /// ```
    pub fn register_server_with_handler<F, U>(
        &mut self, server: IrcServer, handler: F
    ) where F: Fn(&IrcServer, Message) -> U + 'static,
            U: IntoFuture<Item = (), Error = error::Error> + 'static {
        self.handlers.push(Box::new(server.stream().for_each(move |message| {
            handler(&server, message)
        })));
    }

    /// Registers an arbitrary future with this reactor. This is a sort of escape hatch that allows
    /// you to take more control over what runs on the reactor without requiring you to bring in
    /// additional knowledge about `tokio`. It is suspected that `register_server_with_handler` will
    /// be sufficient for most use cases.
    pub fn register_future<F>(
        &mut self, future: F
    ) where F: IntoFuture<Item = (), Error = error::Error> + 'static {
        self.handlers.push(Box::new(future.into_future()))
    }

    /// Returns a handle to the internal event loop. This is a sort of escape hatch that allows you
    /// to take more control over what runs on the reactor using `tokio`. This can be used for
    /// sharing this reactor with some elements of other libraries.
    pub fn inner_handle(&self) -> Handle {
        self.inner.handle()
    }

    /// Consumes all registered handlers and futures, and runs them. When using
    /// `register_server_with_handler`, this will block indefinitely (until failure occurs) as it
    /// will simply continue to process new, incoming messages for each server that was registered.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # use irc::error;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let server = reactor.prepare_server_and_connect(&config).unwrap();
    /// reactor.register_server_with_handler(server, process_msg)
    /// # }
    /// # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
    /// ```
    pub fn run(&mut self) -> error::Result<()> {
        let mut handlers = Vec::new();
        while let Some(handler) = self.handlers.pop() {
            handlers.push(handler);
        }
        self.inner.run(future::join_all(handlers).map(|_| ()))
    }
}
<commit_msg>Removed some trailing whitespace in reactor docs.<commit_after>//! A system for creating and managing IRC server connections.
//!
//! This API provides the ability to create and manage multiple IRC servers that can run on the same
//! thread through the use of a shared event loop. It can also be used to encapsulate the dependency
//! on `tokio` and `futures` in the use of `IrcServer::new_future`. This means that knowledge of
//! those libraries should be unnecessary for the average user. Nevertheless, this API also provides
//! some escape hatches that let advanced users take further advantage of these dependencies.
//!
//! # Example
//! ```no_run
//! # extern crate irc;
//! # use std::default::Default;
//! use irc::client::prelude::*;
//! use irc::error;
//!
//! fn main() {
//!   let config = Config::default();
//!   let mut reactor = IrcReactor::new().unwrap();
//!   let server = reactor.prepare_server_and_connect(&config).unwrap();
//!   reactor.register_server_with_handler(server, process_msg);
//!   reactor.run().unwrap();
//! }
//! # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
//! ```

use futures::{Future, IntoFuture, Stream};
use futures::future;
use tokio_core::reactor::{Core, Handle};

use client::data::Config;
use client::server::{IrcServer, IrcServerFuture, PackedIrcServer, Server};
use error;
use proto::Message;

/// A thin wrapper over an event loop.
///
/// An IRC reactor is used to create new connections to IRC servers and to drive the management of
/// all connected servers as the application runs. It can be used to run multiple servers on the
/// same thread, as well as to get better control over error management in an IRC client.
///
/// For a full example usage, see [irc::client::reactor](./index.html).
pub struct IrcReactor {
    inner: Core,
    handlers: Vec<Box<Future<Item = (), Error = error::Error>>>,
}

impl IrcReactor {
    /// Creates a new reactor.
    pub fn new() -> error::Result<IrcReactor> {
        Ok(IrcReactor {
            inner: Core::new()?,
            handlers: Vec::new(),
        })
    }

    /// Creates a representation of an IRC server that has not yet attempted to connect. In
    /// particular, this representation is as a Future that when run will produce a connected
    /// [IrcServer](./server/struct.IrcServer.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let future_server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_server<'a>(&mut self, config: &'a Config) -> error::Result<IrcServerFuture<'a>> {
        IrcServer::new_future(self.inner_handle(), config)
    }

    /// Runs an [IrcServerFuture](./server/struct.IrcServerFuture.html), such as one from
    /// `prepare_server` to completion, yielding an [IrcServer](./server/struct.IrcServer.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server(&config).and_then(|future| {
    ///         reactor.connect_server(future)
    ///     })
    /// });
    /// # }
    /// ```
    pub fn connect_server(&mut self, future: IrcServerFuture) -> error::Result<IrcServer> {
        self.inner.run(future).map(|PackedIrcServer(server, future)| {
            self.register_future(future);
            server
        })
    }

    /// Creates a new IRC server from the specified configuration, connecting immediately. This is
    /// guaranteed to be the composition of prepare_server and connect_server.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let server = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_server_and_connect(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_server_and_connect(&mut self, config: &Config) -> error::Result<IrcServer> {
        self.prepare_server(config).and_then(|future| self.connect_server(future))
    }

    /// Registers the given server with the specified message handler. The reactor will store this
    /// setup until the next call to run, where it will be used to process new messages over the
    /// connection indefinitely (or until failure). As registration is consumed by `run`, subsequent
    /// calls to run will require new registration.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let server = reactor.prepare_server_and_connect(&config).unwrap();
    /// reactor.register_server_with_handler(server, |server, msg| {
    ///   // Message processing happens here.
    ///   Ok(())
    /// })
    /// # }
    /// ```
    pub fn register_server_with_handler<F, U>(
        &mut self, server: IrcServer, handler: F
    ) where F: Fn(&IrcServer, Message) -> U + 'static,
            U: IntoFuture<Item = (), Error = error::Error> + 'static {
        self.handlers.push(Box::new(server.stream().for_each(move |message| {
            handler(&server, message)
        })));
    }

    /// Registers an arbitrary future with this reactor. This is a sort of escape hatch that allows
    /// you to take more control over what runs on the reactor without requiring you to bring in
    /// additional knowledge about `tokio`. It is suspected that `register_server_with_handler` will
    /// be sufficient for most use cases.
    pub fn register_future<F>(
        &mut self, future: F
    ) where F: IntoFuture<Item = (), Error = error::Error> + 'static {
        self.handlers.push(Box::new(future.into_future()))
    }

    /// Returns a handle to the internal event loop. This is a sort of escape hatch that allows you
    /// to take more control over what runs on the reactor using `tokio`. This can be used for
    /// sharing this reactor with some elements of other libraries.
    pub fn inner_handle(&self) -> Handle {
        self.inner.handle()
    }

    /// Consumes all registered handlers and futures, and runs them. When using
    /// `register_server_with_handler`, this will block indefinitely (until failure occurs) as it
    /// will simply continue to process new, incoming messages for each server that was registered.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # use irc::error;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let server = reactor.prepare_server_and_connect(&config).unwrap();
    /// reactor.register_server_with_handler(server, process_msg)
    /// # }
    /// # fn process_msg(server: &IrcServer, message: Message) -> error::Result<()> { Ok(()) }
    /// ```
    pub fn run(&mut self) -> error::Result<()> {
        let mut handlers = Vec::new();
        while let Some(handler) = self.handlers.pop() {
            handlers.push(handler);
        }
        self.inner.run(future::join_all(handlers).map(|_| ()))
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

extern crate twox_hash;

pub fn hash_bytes(bytes: &[u8]) -> u64 {
    let mut hasher = twox_hash::XxHash::default();
    hasher.write(bytes);
    hasher.finish()
}

pub fn hash_str (text: &String) -> u64 { // the same as the one in utils hash
    let text_bytes = text.as_bytes();
    hash_bytes(text_bytes)
}

pub fn hash_bytes_secondary(bytes: &[u8]) -> u64 {
    let mut hasher = DefaultHasher::default();
    hasher.write(bytes);
    hasher.finish()
}<commit_msg>use str instead of String<commit_after>use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

extern crate twox_hash;

pub fn hash_bytes(bytes: &[u8]) -> u64 {
    let mut hasher = twox_hash::XxHash::default();
    hasher.write(bytes);
    hasher.finish()
}

pub fn hash_str<'a>(text: &'a str) -> u64 { // the same as the one in utils hash
    let text_bytes = text.as_bytes();
    hash_bytes(text_bytes)
}

pub fn hash_bytes_secondary(bytes: &[u8]) -> u64 {
    let mut hasher = DefaultHasher::default();
    hasher.write(bytes);
    hasher.finish()
}<|endoftext|>


<commit_before>//! File structs

use alloc::sync::Arc;
use event;
use spin::RwLock;
use scheme::{self, SchemeId};
use syscall::error::{Result, Error, EBADF};

/// A file description
#[derive(Debug)]
pub struct FileDescription {
    /// The scheme that this file refers to
    pub scheme: SchemeId,
    /// The number the scheme uses to refer to this file
    pub number: usize,
    /// The flags passed to open or fcntl(SETFL)
    pub flags: usize,
}

/// A file descriptor
#[derive(Clone, Debug)]
pub struct FileDescriptor {
    /// Corresponding file description
    pub description: Arc<RwLock<FileDescription>>,
    /// Cloexec flag
    pub cloexec: bool,
}

impl FileDescriptor {
    pub fn close(self) -> Result<usize> {
        if let Ok(file) = Arc::try_unwrap(self.description) {
            let file = file.into_inner();

            event::unregister_file(file.scheme, file.number);

            let scheme = {
                let schemes = scheme::schemes();
                let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
                scheme.clone()
            };
            scheme.close(file.number)
        } else {
            Ok(0)
        }
    }
}
<commit_msg>FileDescriptor is now must_use<commit_after>//! File structs

use alloc::sync::Arc;
use event;
use spin::RwLock;
use scheme::{self, SchemeId};
use syscall::error::{Result, Error, EBADF};

/// A file description
#[derive(Debug)]
pub struct FileDescription {
    /// The scheme that this file refers to
    pub scheme: SchemeId,
    /// The number the scheme uses to refer to this file
    pub number: usize,
    /// The flags passed to open or fcntl(SETFL)
    pub flags: usize,
}

/// A file descriptor
#[derive(Clone, Debug)]
#[must_use = "File descriptors must be closed"]
pub struct FileDescriptor {
    /// Corresponding file description
    pub description: Arc<RwLock<FileDescription>>,
    /// Cloexec flag
    pub cloexec: bool,
}

impl FileDescriptor {
    pub fn close(self) -> Result<usize> {
        if let Ok(file) = Arc::try_unwrap(self.description) {
            let file = file.into_inner();

            event::unregister_file(file.scheme, file.number);

            let scheme = {
                let schemes = scheme::schemes();
                let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
                scheme.clone()
            };
            scheme.close(file.number)
        } else {
            Ok(0)
        }
    }
}
<|endoftext|>


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

//! Enumerations provided by DXGI.
//!
//! # References
//! [DXGI Enumerations, MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471320(v=vs.85).aspx)

#![allow(non_snake_case, dead_code)]

#[repr(C)] pub enum DXGI_ADAPTER_FLAG {
	DXGI_ADAPTER_FLAG_NONE = 0,
	DXGI_ADAPTER_FLAG_REMOTE = 1,
	DXGI_ADAPTER_FLAG_SOFTWARE = 2,
	DXGI_ADAPTER_FLAG_FORCE_DWORD = 0xffffffff
}

#[repr(C)] pub enum DXGI_ALPHA_MODE {
	DXGI_ALPHA_MODE_UNSPECIFIED = 0,
	DXGI_ALPHA_MODE_PREMULTIPLIED = 1,
	DXGI_ALPHA_MODE_STRAIGHT = 2,
	DXGI_ALPHA_MODE_IGNORE = 3,
	DXGI_ALPHA_MODE_FORCE_DWORD = 0xffffffff
}

#[repr(C)] pub enum DXGI_COMPUTE_PREEMPTION_GRANULARITY {
	DXGI_COMPUTE_PREEMPTION_DMA_BUFFER_BOUNDARY = 0,
	DXGI_COMPUTE_PREEMPTION_DISPATCH_BOUNDARY = 1,
	DXGI_COMPUTE_PREEMPTION_THREAD_GROUP_BOUNDARY = 2,
	DXGI_COMPUTE_PREEMPTION_THREAD_BOUNDARY = 3,
	DXGI_COMPUTE_PREEMPTION_INSTRUCTION_BOUNDARY = 4
}

#[repr(C)] pub enum DXGI_DEBUG_RLO_FLAGS {
	DXGI_DEBUG_RLO_SUMMARY = 0x1,
	DXGI_DEBUG_RLO_DETAIL = 0x2,
	DXGI_DEBUG_RLO_ALL = 0x3
}

#[repr(C)] pub enum DXGI_FORMAT {
	DXGI_FORMAT_UNKNOWN = 0,
	DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
	DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
	DXGI_FORMAT_R32G32B32A32_UINT = 3,
	DXGI_FORMAT_R32G32B32A32_SINT = 4,
	DXGI_FORMAT_R32G32B32_TYPELESS = 5,
	DXGI_FORMAT_R32G32B32_FLOAT = 6,
	DXGI_FORMAT_R32G32B32_UINT = 7,
	DXGI_FORMAT_R32G32B32_SINT = 8,
	DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
	DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
	DXGI_FORMAT_R16G16B16A16_UNORM = 11,
	DXGI_FORMAT_R16G16B16A16_UINT = 12,
	DXGI_FORMAT_R16G16B16A16_SNORM = 13,
	DXGI_FORMAT_R16G16B16A16_SINT = 14,
	DXGI_FORMAT_R32G32_TYPELESS = 15,
	DXGI_FORMAT_R32G32_FLOAT = 16,
	DXGI_FORMAT_R32G32_UINT = 17,
	DXGI_FORMAT_R32G32_SINT = 18,
	DXGI_FORMAT_R32G8X24_TYPELESS = 19,
	DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
	DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
	DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
	DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
	DXGI_FORMAT_R10G10B10A2_UNORM = 24,
	DXGI_FORMAT_R10G10B10A2_UINT = 25,
	DXGI_FORMAT_R11G11B10_FLOAT = 26,
	DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
	DXGI_FORMAT_R8G8B8A8_UNORM = 28,
	DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
	DXGI_FORMAT_R8G8B8A8_UINT = 30,
	DXGI_FORMAT_R8G8B8A8_SNORM = 31,
	DXGI_FORMAT_R8G8B8A8_SINT = 32,
	DXGI_FORMAT_R16G16_TYPELESS = 33,
	DXGI_FORMAT_R16G16_FLOAT = 34,
	DXGI_FORMAT_R16G16_UNORM = 35,
	DXGI_FORMAT_R16G16_UINT = 36,
	DXGI_FORMAT_R16G16_SNORM = 37,
	DXGI_FORMAT_R16G16_SINT = 38,
	DXGI_FORMAT_R32_TYPELESS = 39,
	DXGI_FORMAT_D32_FLOAT = 40,
	DXGI_FORMAT_R32_FLOAT = 41,
	DXGI_FORMAT_R32_UINT = 42,
	DXGI_FORMAT_R32_SINT = 43,
	DXGI_FORMAT_R24G8_TYPELESS = 44,
	DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
	DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
	DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
	DXGI_FORMAT_R8G8_TYPELESS = 48,
	DXGI_FORMAT_R8G8_UNORM = 49,
	DXGI_FORMAT_R8G8_UINT = 50,
	DXGI_FORMAT_R8G8_SNORM = 51,
	DXGI_FORMAT_R8G8_SINT = 52,
	DXGI_FORMAT_R16_TYPELESS = 53,
	DXGI_FORMAT_R16_FLOAT = 54,
	DXGI_FORMAT_D16_UNORM = 55,
	DXGI_FORMAT_R16_UNORM = 56,
	DXGI_FORMAT_R16_UINT = 57,
	DXGI_FORMAT_R16_SNORM = 58,
	DXGI_FORMAT_R16_SINT = 59,
	DXGI_FORMAT_R8_TYPELESS = 60,
	DXGI_FORMAT_R8_UNORM = 61,
	DXGI_FORMAT_R8_UINT = 62,
	DXGI_FORMAT_R8_SNORM = 63,
	DXGI_FORMAT_R8_SINT = 64,
	DXGI_FORMAT_A8_UNORM = 65,
	DXGI_FORMAT_R1_UNORM = 66,
	DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
	DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
	DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
	DXGI_FORMAT_BC1_TYPELESS = 70,
	DXGI_FORMAT_BC1_UNORM = 71,
	DXGI_FORMAT_BC1_UNORM_SRGB = 72,
	DXGI_FORMAT_BC2_TYPELESS = 73,
	DXGI_FORMAT_BC2_UNORM = 74,
	DXGI_FORMAT_BC2_UNORM_SRGB = 75,
	DXGI_FORMAT_BC3_TYPELESS = 76,
	DXGI_FORMAT_BC3_UNORM = 77,
	DXGI_FORMAT_BC3_UNORM_SRGB = 78,
	DXGI_FORMAT_BC4_TYPELESS = 79,
	DXGI_FORMAT_BC4_UNORM = 80,
	DXGI_FORMAT_BC4_SNORM = 81,
	DXGI_FORMAT_BC5_TYPELESS = 82,
	DXGI_FORMAT_BC5_UNORM = 83,
	DXGI_FORMAT_BC5_SNORM = 84,
	DXGI_FORMAT_B5G6R5_UNORM = 85,
	DXGI_FORMAT_B5G5R5A1_UNORM = 86,
	DXGI_FORMAT_B8G8R8A8_UNORM = 87,
	DXGI_FORMAT_B8G8R8X8_UNORM = 88,
	DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
	DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
	DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
	DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
	DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
	DXGI_FORMAT_BC6H_TYPELESS = 94,
	DXGI_FORMAT_BC6H_UF16 = 95,
	DXGI_FORMAT_BC6H_SF16 = 96,
	DXGI_FORMAT_BC7_TYPELESS = 97,
	DXGI_FORMAT_BC7_UNORM = 98,
	DXGI_FORMAT_BC7_UNORM_SRGB = 99,
	DXGI_FORMAT_AYUV = 100,
	DXGI_FORMAT_Y410 = 101,
	DXGI_FORMAT_Y416 = 102,
	DXGI_FORMAT_NV12 = 103,
	DXGI_FORMAT_P010 = 104,
	DXGI_FORMAT_P016 = 105,
	DXGI_FORMAT_420_OPAQUE = 106,
	DXGI_FORMAT_YUY2 = 107,
	DXGI_FORMAT_Y210 = 108,
	DXGI_FORMAT_Y216 = 109,
	DXGI_FORMAT_NV11 = 110,
	DXGI_FORMAT_AI44 = 111,
	DXGI_FORMAT_IA44 = 112,
	DXGI_FORMAT_P8 = 113,
	DXGI_FORMAT_A8P8 = 114,
	DXGI_FORMAT_B4G4R4A4_UNORM = 115,
	DXGI_FORMAT_FORCE_UINT = 0xffffffff
}

#[repr(C)] pub enum DXGI_FRAME_PRESENTATION_MODE {
	DXGI_FRAME_PRESENTATION_MODE_COMPOSED = 0,
	DXGI_FRAME_PRESENTATION_MODE_OVERLAY = 1,
	DXGI_FRAME_PRESENTATION_MODE_NONE = 2
}

#[repr(C)] pub enum DXGI_GRAPHICS_PREEMPTION_GRANULARITY {
	DXGI_GRAPHICS_PREEMPTION_DMA_BUFFER_BOUNDARY = 0,
	DXGI_GRAPHICS_PREEMPTION_PRIMITIVE_BOUNDARY = 1,
	DXGI_GRAPHICS_PREEMPTION_TRIANGLE_BOUNDARY = 2,
	DXGI_GRAPHICS_PREEMPTION_PIXEL_BOUNDARY = 3,
	DXGI_GRAPHICS_PREEMPTION_INSTRUCTION_BOUNDARY = 4
}

#[repr(C)] pub enum DXGI_INFO_QUEUE_MESSAGE_CATEGORY {
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_UNKNOWN = 0,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_MISCELLANEOUS = 1,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_INITIALIZATION = 2,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_CLEANUP = 3,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_COMPILATION = 4,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_STATE_CREATION = 5,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_STATE_SETTING = 6,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_STATE_GETTING = 7,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_RESOURCE_MANIPULATION = 8,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_EXECUTION = 9,
	DXGI_INFO_QUEUE_MESSAGE_CATEGORY_SHADER = 10
}

#[repr(C)] pub enum DXGI_INFO_QUEUE_MESSAGE_SEVERITY {
	DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION = 0,
	DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR = 2,
	DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING = 3,
	DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO = 4,
	DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE = 5
}

#[repr(C)] pub enum DXGI_MODE_ROTATION {
	DXGI_MODE_ROTATION_UNSPECIFIED = 0,
	DXGI_MODE_ROTATION_IDENTITY = 1,
	DXGI_MODE_ROTATION_ROTATE90 = 2,
	DXGI_MODE_ROTATION_ROTATE180 = 3,
	DXGI_MODE_ROTATION_ROTATE270 = 4
}

#[repr(C)] pub enum DXGI_MODE_SCALING {
	DXGI_MODE_SCALING_UNSPECIFIED = 0,
	DXGI_MODE_SCALING_CENTERED = 1,
	DXGI_MODE_SCALING_STRETCHED = 2
}

#[repr(C)] pub enum DXGI_MODE_SCANLINE_ORDER {
	DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0,
	DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE = 1,
	DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST = 2,
	DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST = 3
}

#[repr(C)] pub enum DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS {
	DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_NOMINAL_RANGE = 0x1,
	DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_BT709 = 0x2,
	DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAG_xvYCC = 0x4
}

#[repr(C)] pub enum DXGI_OFFER_RESOURCE_PRIORITY {
	DXGI_OFFER_RESOURCE_PRIORITY_LOW = 1,
	DXGI_OFFER_RESOURCE_PRIORITY_NORMAL = 2,
	DXGI_OFFER_RESOURCE_PRIORITY_HIGH = 3
}

#[repr(C)] pub enum DXGI_OUTDUPL_POINTER_SHAPE_TYPE {
	DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME = 0x1,
	DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR = 0x2,
	DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR = 0x4
}

#[repr(C)] pub enum DXGI_RESIDENCY {
	DXGI_RESIDENCY_FULLY_RESIDENT = 1,
	DXGI_RESIDENCY_RESIDENT_IN_SHARED_MEMORY = 2,
	DXGI_RESIDENCY_EVICTED_TO_DISK = 3
}

#[repr(C)] pub enum DXGI_SCALING {
	DXGI_SCALING_STRETCH = 0,
	DXGI_SCALING_NONE = 1,
	DXGI_SCALING_ASPECT_RATIO_STRETCH = 2
}

#[repr(C)] pub enum DXGI_SWAP_CHAIN_FLAG {
	DXGI_SWAP_CHAIN_FLAG_NONPREROTATED = 1,
	DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH = 2,
	DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE = 4,
	DXGI_SWAP_CHAIN_FLAG_RESTRICTED_CONTENT = 8,
	DXGI_SWAP_CHAIN_FLAG_RESTRICT_SHARED_RESOURCE_DRIVER = 16,
	DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY = 32,
	DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT = 64,
	DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER = 128
}

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

//! Enumerations provided by DXGI.
//!
//! # References
//! [DXGI Enumerations, MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471320(v=vs.85).aspx)

#![allow(non_snake_case, dead_code)]

#[repr(C)] pub enum DXGI_ADAPTER_FLAG {
	NONE = 0,
	REMOTE = 1,
	SOFTWARE = 2,
	FORCE_DWORD = 0xffffffff
}

#[repr(C)] pub enum DXGI_ALPHA_MODE {
	UNSPECIFIED = 0,
	PREMULTIPLIED = 1,
	STRAIGHT = 2,
	IGNORE = 3,
	FORCE_DWORD = 0xffffffff
}

#[repr(C)] pub enum DXGI_COMPUTE_PREEMPTION_GRANULARITY {
	DMA_BUFFER_BOUNDARY = 0,
	DISPATCH_BOUNDARY = 1,
	THREAD_GROUP_BOUNDARY = 2,
	THREAD_BOUNDARY = 3,
	INSTRUCTION_BOUNDARY = 4
}

#[repr(C)] pub enum DXGI_DEBUG_RLO_FLAGS {
	SUMMARY = 0x1,
	DETAIL = 0x2,
	ALL = 0x3
}

#[repr(C)] pub enum DXGI_FORMAT {
	UNKNOWN = 0,
	R32G32B32A32_TYPELESS = 1,
	R32G32B32A32_FLOAT = 2,
	R32G32B32A32_UINT = 3,
	R32G32B32A32_SINT = 4,
	R32G32B32_TYPELESS = 5,
	R32G32B32_FLOAT = 6,
	R32G32B32_UINT = 7,
	R32G32B32_SINT = 8,
	R16G16B16A16_TYPELESS = 9,
	R16G16B16A16_FLOAT = 10,
	R16G16B16A16_UNORM = 11,
	R16G16B16A16_UINT = 12,
	R16G16B16A16_SNORM = 13,
	R16G16B16A16_SINT = 14,
	R32G32_TYPELESS = 15,
	R32G32_FLOAT = 16,
	R32G32_UINT = 17,
	R32G32_SINT = 18,
	R32G8X24_TYPELESS = 19,
	D32_FLOAT_S8X24_UINT = 20,
	R32_FLOAT_X8X24_TYPELESS = 21,
	X32_TYPELESS_G8X24_UINT = 22,
	R10G10B10A2_TYPELESS = 23,
	R10G10B10A2_UNORM = 24,
	R10G10B10A2_UINT = 25,
	R11G11B10_FLOAT = 26,
	R8G8B8A8_TYPELESS = 27,
	R8G8B8A8_UNORM = 28,
	R8G8B8A8_UNORM_SRGB = 29,
	R8G8B8A8_UINT = 30,
	R8G8B8A8_SNORM = 31,
	R8G8B8A8_SINT = 32,
	R16G16_TYPELESS = 33,
	R16G16_FLOAT = 34,
	R16G16_UNORM = 35,
	R16G16_UINT = 36,
	R16G16_SNORM = 37,
	R16G16_SINT = 38,
	R32_TYPELESS = 39,
	D32_FLOAT = 40,
	R32_FLOAT = 41,
	R32_UINT = 42,
	R32_SINT = 43,
	R24G8_TYPELESS = 44,
	D24_UNORM_S8_UINT = 45,
	R24_UNORM_X8_TYPELESS = 46,
	X24_TYPELESS_G8_UINT = 47,
	R8G8_TYPELESS = 48,
	R8G8_UNORM = 49,
	R8G8_UINT = 50,
	R8G8_SNORM = 51,
	R8G8_SINT = 52,
	R16_TYPELESS = 53,
	R16_FLOAT = 54,
	D16_UNORM = 55,
	R16_UNORM = 56,
	R16_UINT = 57,
	R16_SNORM = 58,
	R16_SINT = 59,
	R8_TYPELESS = 60,
	R8_UNORM = 61,
	R8_UINT = 62,
	R8_SNORM = 63,
	R8_SINT = 64,
	A8_UNORM = 65,
	R1_UNORM = 66,
	R9G9B9E5_SHAREDEXP = 67,
	R8G8_B8G8_UNORM = 68,
	G8R8_G8B8_UNORM = 69,
	BC1_TYPELESS = 70,
	BC1_UNORM = 71,
	BC1_UNORM_SRGB = 72,
	BC2_TYPELESS = 73,
	BC2_UNORM = 74,
	BC2_UNORM_SRGB = 75,
	BC3_TYPELESS = 76,
	BC3_UNORM = 77,
	BC3_UNORM_SRGB = 78,
	BC4_TYPELESS = 79,
	BC4_UNORM = 80,
	BC4_SNORM = 81,
	BC5_TYPELESS = 82,
	BC5_UNORM = 83,
	BC5_SNORM = 84,
	B5G6R5_UNORM = 85,
	B5G5R5A1_UNORM = 86,
	B8G8R8A8_UNORM = 87,
	B8G8R8X8_UNORM = 88,
	R10G10B10_XR_BIAS_A2_UNORM = 89,
	B8G8R8A8_TYPELESS = 90,
	B8G8R8A8_UNORM_SRGB = 91,
	B8G8R8X8_TYPELESS = 92,
	B8G8R8X8_UNORM_SRGB = 93,
	BC6H_TYPELESS = 94,
	BC6H_UF16 = 95,
	BC6H_SF16 = 96,
	BC7_TYPELESS = 97,
	BC7_UNORM = 98,
	BC7_UNORM_SRGB = 99,
	AYUV = 100,
	Y410 = 101,
	Y416 = 102,
	NV12 = 103,
	P010 = 104,
	P016 = 105,
	OPAQUE_420 = 106,
	YUY2 = 107,
	Y210 = 108,
	Y216 = 109,
	NV11 = 110,
	AI44 = 111,
	IA44 = 112,
	P8 = 113,
	A8P8 = 114,
	B4G4R4A4_UNORM = 115,
	FORCE_UINT = 0xffffffff
}

#[repr(C)] pub enum DXGI_FRAME_PRESENTATION_MODE {
	COMPOSED = 0,
	OVERLAY = 1,
	NONE = 2
}

#[repr(C)] pub enum DXGI_GRAPHICS_PREEMPTION_GRANULARITY {
	DMA_BUFFER_BOUNDARY = 0,
	PRIMITIVE_BOUNDARY = 1,
	TRIANGLE_BOUNDARY = 2,
	PIXEL_BOUNDARY = 3,
	INSTRUCTION_BOUNDARY = 4
}

#[repr(C)] pub enum DXGI_INFO_QUEUE_MESSAGE_CATEGORY {
	UNKNOWN = 0,
	MISCELLANEOUS = 1,
	INITIALIZATION = 2,
	CLEANUP = 3,
	COMPILATION = 4,
	STATE_CREATION = 5,
	STATE_SETTING = 6,
	STATE_GETTING = 7,
	RESOURCE_MANIPULATION = 8,
	EXECUTION = 9,
	SHADER = 10
}

#[repr(C)] pub enum DXGI_INFO_QUEUE_MESSAGE_SEVERITY {
	CORRUPTION = 0,
	ERROR = 2,
	WARNING = 3,
	INFO = 4,
	MESSAGE = 5
}

#[repr(C)] pub enum DXGI_MODE_ROTATION {
	UNSPECIFIED = 0,
	IDENTITY = 1,
	ROTATE90 = 2,
	ROTATE180 = 3,
	ROTATE270 = 4
}

#[repr(C)] pub enum DXGI_MODE_SCALING {
	UNSPECIFIED = 0,
	CENTERED = 1,
	STRETCHED = 2
}

#[repr(C)] pub enum DXGI_MODE_SCANLINE_ORDER {
	UNSPECIFIED = 0,
	PROGRESSIVE = 1,
	UPPER_FIELD_FIRST = 2,
	LOWER_FIELD_FIRST = 3
}

#[repr(C)] pub enum DXGI_MULTIPLANE_OVERLAY_YCbCr_FLAGS {
	NOMINAL_RANGE = 0x1,
	BT709 = 0x2,
	xvYCC = 0x4
}

#[repr(C)] pub enum DXGI_OFFER_RESOURCE_PRIORITY {
	LOW = 1,
	NORMAL = 2,
	HIGH = 3
}

#[repr(C)] pub enum DXGI_OUTDUPL_POINTER_SHAPE_TYPE {
	MONOCHROME = 0x1,
	COLOR = 0x2,
	MASKED_COLOR = 0x4
}

#[repr(C)] pub enum DXGI_RESIDENCY {
	FULLY_RESIDENT = 1,
	RESIDENT_IN_SHARED_MEMORY = 2,
	EVICTED_TO_DISK = 3
}

#[repr(C)] pub enum DXGI_SCALING {
	STRETCH = 0,
	NONE = 1,
	ASPECT_RATIO_STRETCH = 2
}

#[repr(C)] pub enum DXGI_SWAP_CHAIN_FLAG {
	NONPREROTATED = 1,
	ALLOW_MODE_SWITCH = 2,
	GDI_COMPATIBLE = 4,
	RESTRICTED_CONTENT = 8,
	RESTRICT_SHARED_RESOURCE_DRIVER = 16,
	DISPLAY_ONLY = 32,
	FRAME_LATENCY_WAITABLE_OBJECT = 64,
	FOREGROUND_LAYER = 128
}

#[repr(C)] pub enum DXGI_SWAP_EFFECT {
	DISCARD = 0,
	SEQUENTIAL = 1,
	FLIP_SEQUENTIAL = 3
}<|endoftext|>


<commit_before>//! RenderPass handling.

use crate::format::Format;
use crate::image;
use crate::pso::PipelineStage;
use crate::Backend;
use std::ops::Range;

/// Specifies the operation which will be applied at the beginning of a subpass.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AttachmentLoadOp {
    /// Preserve existing content in the attachment.
    Load,
    /// Clear the attachment.
    Clear,
    /// Attachment content will be undefined.
    DontCare,
}

///
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AttachmentStoreOp {
    /// Content written to the attachment will be preserved.
    Store,
    /// Attachment content will be undefined.
    DontCare,
}

/// Image layout of an attachment.
pub type AttachmentLayout = image::Layout;

/// Attachment operations.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AttachmentOps {
    /// Indicates how the data of the attachment will be loaded at first usage at
    /// the beginning of the subpass.
    pub load: AttachmentLoadOp,
    /// Whether or not data from the store operation will be preserved after the subpass.
    pub store: AttachmentStoreOp,
}

impl AttachmentOps {
    /// Specifies `DontCare` for both load and store op.
    pub const DONT_CARE: Self = AttachmentOps {
        load: AttachmentLoadOp::DontCare,
        store: AttachmentStoreOp::DontCare,
    };

    /// Specifies `Load` for load op and `Store` for store op.
    pub const PRESERVE: Self = AttachmentOps {
        load: AttachmentLoadOp::Load,
        store: AttachmentStoreOp::Store,
    };

    /// Convenience function to create a new `AttachmentOps`.
    pub fn new(load: AttachmentLoadOp, store: AttachmentStoreOp) -> Self {
        AttachmentOps { load, store }
    }

    /// A method to provide `AttachmentOps::DONT_CARE` to things that expect
    /// a default function rather than a value.
    #[cfg(feature = "serde")]
    fn whatever() -> Self {
        Self::DONT_CARE
    }
}

/// An `Attachment` is a description of a resource provided to a render subpass.
/// It includes things such as render targets, images that were produced from
/// previous subpasses, etc.
#[derive(Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Attachment {
    /// Attachment format
    ///
    /// In the most cases `format` is not `None`. It should be only used for
    /// creating dummy renderpasses, which are used as placeholder for compatible
    /// renderpasses.
    pub format: Option<Format>,
    /// Number of samples.
    pub samples: image::NumSamples,
    /// Load and store operations of the attachment
    pub ops: AttachmentOps,
    /// Load and store operations of the stencil aspect, if any
    #[cfg_attr(feature = "serde", serde(default = "AttachmentOps::whatever"))]
    pub stencil_ops: AttachmentOps,
    /// Initial and final image layouts of the renderpass.
    pub layouts: Range<AttachmentLayout>,
}

impl Attachment {
    /// Returns true if this attachment has some clear operations. This is useful
    /// when starting a render pass, since there has to be a clear value provided.
    pub fn has_clears(&self) -> bool {
        self.ops.load == AttachmentLoadOp::Clear || self.stencil_ops.load == AttachmentLoadOp::Clear
    }
}

/// Index of an attachment within a framebuffer/renderpass,
pub type AttachmentId = usize;
/// Reference to an attachment by index and expected image layout.
pub type AttachmentRef = (AttachmentId, AttachmentLayout);

/// Which other subpasses a particular subpass depends on.
#[derive(Copy, Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum SubpassRef {
    /// The subpass depends on something that was submitted to the
    /// queue before or after the render pass began.
    External,
    /// The subpass depends on another subpass with the given index,
    /// which must be less than or equal to the index of the current
    /// subpass. The index here refers to the corresponding
    /// `SubpassId` of a `Subpass`.
    Pass(usize),
}

/// Expresses a dependency between multiple subpasses. This is used
/// both to describe a source or destination subpass; data either
/// explicitly passes from this subpass to the next or from another
/// subpass into this one.
#[derive(Clone, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubpassDependency {
    /// Other subpasses this one depends on.
    pub passes: Range<SubpassRef>,
    /// Other pipeline stages this subpass depends on.
    pub stages: Range<PipelineStage>,
    /// Resource accesses this subpass depends on.
    pub accesses: Range<image::Access>,
}

/// Description of a subpass for renderpass creation.
#[derive(Debug)]
pub struct SubpassDesc<'a> {
    /// Which attachments will be used as color buffers.
    pub colors: &'a [AttachmentRef],
    /// Which attachments will be used as depth/stencil buffers.
    pub depth_stencil: Option<&'a AttachmentRef>,
    /// Which attachments will be used as input attachments.
    pub inputs: &'a [AttachmentRef],
    /// Which attachments will be used as resolve destinations.
    ///
    /// The number of resolve attachments may be zero or equal to the number of color attachments.
    /// At the end of a subpass the color attachment will be resolved to the corresponding
    /// resolve attachment. The resolve attachment must not be multisampled.
    pub resolves: &'a [AttachmentRef],
    /// Attachments that are not used by the subpass but must be preserved to be
    /// passed on to subsequent passes.
    pub preserves: &'a [AttachmentId],
}

/// Index of a subpass.
pub type SubpassId = usize;

/// A sub-pass borrow of a pass.
#[derive(Debug)]
pub struct Subpass<'a, B: Backend> {
    /// Index of the subpass
    pub index: SubpassId,
    /// Main pass borrow.
    pub main_pass: &'a B::RenderPass,
}

impl<'a, B: Backend> Clone for Subpass<'a, B> {
    fn clone(&self) -> Self {
        Subpass {
            index: self.index,
            main_pass: self.main_pass,
        }
    }
}

impl<'a, B: Backend> PartialEq for Subpass<'a, B> {
    fn eq(&self, other: &Self) -> bool {
        self.index == other.index && self.main_pass as *const _ == other.main_pass as *const _
    }
}

impl<'a, B: Backend> Copy for Subpass<'a, B> {}
impl<'a, B: Backend> Eq for Subpass<'a, B> {}
<commit_msg>hal: Merge use statements in pass module<commit_after>//! RenderPass handling.

use crate::{format::Format, image, pso::PipelineStage, Backend};
use std::ops::Range;

/// Specifies the operation which will be applied at the beginning of a subpass.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AttachmentLoadOp {
    /// Preserve existing content in the attachment.
    Load,
    /// Clear the attachment.
    Clear,
    /// Attachment content will be undefined.
    DontCare,
}

///
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AttachmentStoreOp {
    /// Content written to the attachment will be preserved.
    Store,
    /// Attachment content will be undefined.
    DontCare,
}

/// Image layout of an attachment.
pub type AttachmentLayout = image::Layout;

/// Attachment operations.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AttachmentOps {
    /// Indicates how the data of the attachment will be loaded at first usage at
    /// the beginning of the subpass.
    pub load: AttachmentLoadOp,
    /// Whether or not data from the store operation will be preserved after the subpass.
    pub store: AttachmentStoreOp,
}

impl AttachmentOps {
    /// Specifies `DontCare` for both load and store op.
    pub const DONT_CARE: Self = AttachmentOps {
        load: AttachmentLoadOp::DontCare,
        store: AttachmentStoreOp::DontCare,
    };

    /// Specifies `Load` for load op and `Store` for store op.
    pub const PRESERVE: Self = AttachmentOps {
        load: AttachmentLoadOp::Load,
        store: AttachmentStoreOp::Store,
    };

    /// Convenience function to create a new `AttachmentOps`.
    pub fn new(load: AttachmentLoadOp, store: AttachmentStoreOp) -> Self {
        AttachmentOps { load, store }
    }

    /// A method to provide `AttachmentOps::DONT_CARE` to things that expect
    /// a default function rather than a value.
    #[cfg(feature = "serde")]
    fn whatever() -> Self {
        Self::DONT_CARE
    }
}

/// An `Attachment` is a description of a resource provided to a render subpass.
/// It includes things such as render targets, images that were produced from
/// previous subpasses, etc.
#[derive(Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Attachment {
    /// Attachment format
    ///
    /// In the most cases `format` is not `None`. It should be only used for
    /// creating dummy renderpasses, which are used as placeholder for compatible
    /// renderpasses.
    pub format: Option<Format>,
    /// Number of samples.
    pub samples: image::NumSamples,
    /// Load and store operations of the attachment
    pub ops: AttachmentOps,
    /// Load and store operations of the stencil aspect, if any
    #[cfg_attr(feature = "serde", serde(default = "AttachmentOps::whatever"))]
    pub stencil_ops: AttachmentOps,
    /// Initial and final image layouts of the renderpass.
    pub layouts: Range<AttachmentLayout>,
}

impl Attachment {
    /// Returns true if this attachment has some clear operations. This is useful
    /// when starting a render pass, since there has to be a clear value provided.
    pub fn has_clears(&self) -> bool {
        self.ops.load == AttachmentLoadOp::Clear || self.stencil_ops.load == AttachmentLoadOp::Clear
    }
}

/// Index of an attachment within a framebuffer/renderpass,
pub type AttachmentId = usize;
/// Reference to an attachment by index and expected image layout.
pub type AttachmentRef = (AttachmentId, AttachmentLayout);

/// Which other subpasses a particular subpass depends on.
#[derive(Copy, Clone, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum SubpassRef {
    /// The subpass depends on something that was submitted to the
    /// queue before or after the render pass began.
    External,
    /// The subpass depends on another subpass with the given index,
    /// which must be less than or equal to the index of the current
    /// subpass. The index here refers to the corresponding
    /// `SubpassId` of a `Subpass`.
    Pass(usize),
}

/// Expresses a dependency between multiple subpasses. This is used
/// both to describe a source or destination subpass; data either
/// explicitly passes from this subpass to the next or from another
/// subpass into this one.
#[derive(Clone, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubpassDependency {
    /// Other subpasses this one depends on.
    pub passes: Range<SubpassRef>,
    /// Other pipeline stages this subpass depends on.
    pub stages: Range<PipelineStage>,
    /// Resource accesses this subpass depends on.
    pub accesses: Range<image::Access>,
}

/// Description of a subpass for renderpass creation.
#[derive(Debug)]
pub struct SubpassDesc<'a> {
    /// Which attachments will be used as color buffers.
    pub colors: &'a [AttachmentRef],
    /// Which attachments will be used as depth/stencil buffers.
    pub depth_stencil: Option<&'a AttachmentRef>,
    /// Which attachments will be used as input attachments.
    pub inputs: &'a [AttachmentRef],
    /// Which attachments will be used as resolve destinations.
    ///
    /// The number of resolve attachments may be zero or equal to the number of color attachments.
    /// At the end of a subpass the color attachment will be resolved to the corresponding
    /// resolve attachment. The resolve attachment must not be multisampled.
    pub resolves: &'a [AttachmentRef],
    /// Attachments that are not used by the subpass but must be preserved to be
    /// passed on to subsequent passes.
    pub preserves: &'a [AttachmentId],
}

/// Index of a subpass.
pub type SubpassId = usize;

/// A sub-pass borrow of a pass.
#[derive(Debug)]
pub struct Subpass<'a, B: Backend> {
    /// Index of the subpass
    pub index: SubpassId,
    /// Main pass borrow.
    pub main_pass: &'a B::RenderPass,
}

impl<'a, B: Backend> Clone for Subpass<'a, B> {
    fn clone(&self) -> Self {
        Subpass {
            index: self.index,
            main_pass: self.main_pass,
        }
    }
}

impl<'a, B: Backend> PartialEq for Subpass<'a, B> {
    fn eq(&self, other: &Self) -> bool {
        self.index == other.index && self.main_pass as *const _ == other.main_pass as *const _
    }
}

impl<'a, B: Backend> Copy for Subpass<'a, B> {}
impl<'a, B: Backend> Eq for Subpass<'a, B> {}
<|endoftext|>


<commit_before>use crate::exceptions::{CalculateError, IOError};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::fs;
use std::fs::DirEntry;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Measurement {
    pub command: String,
    pub mean: f64,
    pub stddev: f64,
    pub median: f64,
    pub user: f64,
    pub system: f64,
    pub min: f64,
    pub max: f64,
    pub times: Vec<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Measurements {
    pub results: Vec<Measurement>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Data {
    pub threshold: f64,
    pub difference: f64,
    pub baseline: f64,
    pub dev: f64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Calculation {
    pub metric: String,
    pub regression: bool,
    pub data: Data,
}

#[derive(Debug, Clone, PartialEq)]
pub struct MeasurementGroup {
    pub version: String,
    pub run: String,
    pub measurement: Measurement,
}

fn calculate(metric: &str, dev: &Measurement, baseline: &Measurement) -> Vec<Calculation> {
    let median_threshold = 1.05; // 5% regression threshold
    let median_difference = dev.median / baseline.median;

    let stddev_threshold = 1.05; // 5% regression threshold
    let stddev_difference = dev.stddev / baseline.stddev;

    vec![
        Calculation {
            metric: ["median", metric].join("_"),
            regression: median_difference > median_threshold,
            data: Data {
                threshold: median_threshold,
                difference: median_difference,
                baseline: baseline.median,
                dev: dev.median,
            }
        },
        Calculation {
            metric: ["stddev", metric].join("_"),
            regression: stddev_difference > stddev_threshold,
            data: Data {
                threshold: stddev_threshold,
                difference: stddev_difference,
                baseline: baseline.stddev,
                dev: dev.stddev,
            }
        },
    ]
}

// given a directory, read all files in the directory and return each
// filename with the deserialized json contents of that file
fn measurements_from_files(
    results_directory: &Path,
) -> Result<Vec<(PathBuf, Measurements)>, CalculateError> {
    let result_files = fs::read_dir(results_directory)
        .or_else(|e| Err(IOError::ReadErr(results_directory.to_path_buf(), Some(e))))
        .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

    result_files
        .into_iter()
        .map(|entry| {
            let ent: DirEntry = entry.or_else(|e| Err(IOError::ReadErr(results_directory.to_path_buf(), Some(e))))
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

            Ok(ent.path())
        })
        .collect::<Result<Vec<PathBuf>, CalculateError>>()?
        .into_iter()
        .filter(|path| {
            path
                .extension()
                .and_then(|ext| ext.to_str())
                .map_or(false, |ext| ext.ends_with("json"))
        })
        .map(|path| {
            fs::read_to_string(&path)
                .or_else(|e| Err(IOError::BadFileContentsErr(path.clone(), Some(e))))
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))
                .and_then(|contents| {
                    serde_json::from_str::<Measurements>(&contents)
                        .or_else(|e| Err(CalculateError::BadJSONErr(path.clone(), Some(e))))
                })
                .map(|m| (path, m))
        })
        .collect()
}

// given a list of filename-measurement pairs, detect any regressions by grouping
// measurements together by filename
fn calculate_regressions(
    measurements: &[(PathBuf, Measurement)],
) -> Result<Vec<Calculation>, CalculateError> {
    let mut measurement_groups: Vec<MeasurementGroup> = measurements
        .into_iter()
        .map(|(p, m)| {
            p.file_name()
                .ok_or_else(|| IOError::MissingFilenameErr(p.to_path_buf()))
                .and_then(|name| {
                    name.to_str()
                        .ok_or_else(|| IOError::FilenameNotUnicodeErr(p.to_path_buf()))
                })
                .map(|name| {
                    let parts: Vec<&str> = name.split("_").collect();
                    MeasurementGroup {
                        version: parts[0].to_owned(),
                        run: parts[1..].join("_"),
                        measurement: m.clone(),
                    }
                })
        })
        .collect::<Result<Vec<MeasurementGroup>, IOError>>()
        .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

    measurement_groups.sort_by(|x, y| (&x.run, &x.version).cmp(&(&y.run, &y.version)));

    // locking up mutation
    let sorted_measurement_groups = measurement_groups;

    let calculations: Vec<Calculation> = sorted_measurement_groups
        .into_iter()
        .group_by(|x| x.run.clone())
        .into_iter()
        .map(|(_, g)| {
            let mut groups: Vec<MeasurementGroup> = g.collect();
            groups.sort_by(|x, y| x.version.cmp(&y.version));

            match groups.len() {
                2 => {
                    let dev = &groups[1];
                    let baseline = &groups[0];

                    if dev.version == "dev" && baseline.version == "baseline" {
                        Ok(calculate(&dev.run, &dev.measurement, &baseline.measurement))
                    } else {
                        Err(CalculateError::BadBranchNameErr(baseline.version.clone(), dev.version.clone()))
                    }
                },
                i => Err(CalculateError::BadGroupSizeErr(i, groups)),
            }
        })
        .collect::<Result<Vec<Vec<Calculation>>, CalculateError>>()?
        .concat();

    Ok(calculations)
}

pub fn regressions(results_directory: &PathBuf) -> Result<Vec<Calculation>, CalculateError> {
    measurements_from_files(Path::new(&results_directory)).and_then(|v| {
        // exit early with an Err if there are no results to process
        match v.len() {
            0 => Err(CalculateError::NoResultsErr(results_directory.clone())),
            i if i % 2 == 1 => Err(CalculateError::OddResultsCountErr(i, results_directory.clone())),
            _ => Ok(()),
        }?;

        let v_next: Vec<(PathBuf, Measurement)> = v
            .into_iter()
            // the way we're running these, the files will each contain exactly one measurement, hence `results[0]`
            .map(|(p, ms)| (p, ms.results[0].clone()))
            .collect();

        calculate_regressions(&v_next)
    })
}
<commit_msg>minor refactor<commit_after>use crate::exceptions::{CalculateError, IOError};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::fs;
use std::fs::DirEntry;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Measurement {
    pub command: String,
    pub mean: f64,
    pub stddev: f64,
    pub median: f64,
    pub user: f64,
    pub system: f64,
    pub min: f64,
    pub max: f64,
    pub times: Vec<f64>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Measurements {
    pub results: Vec<Measurement>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Data {
    pub threshold: f64,
    pub difference: f64,
    pub baseline: f64,
    pub dev: f64,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Calculation {
    pub metric: String,
    pub regression: bool,
    pub data: Data,
}

#[derive(Debug, Clone, PartialEq)]
pub struct MeasurementGroup {
    pub version: String,
    pub run: String,
    pub measurement: Measurement,
}

fn calculate(metric: &str, dev: &Measurement, baseline: &Measurement) -> Vec<Calculation> {
    let median_threshold = 1.05; // 5% regression threshold
    let median_difference = dev.median / baseline.median;

    let stddev_threshold = 1.05; // 5% regression threshold
    let stddev_difference = dev.stddev / baseline.stddev;

    vec![
        Calculation {
            metric: ["median", metric].join("_"),
            regression: median_difference > median_threshold,
            data: Data {
                threshold: median_threshold,
                difference: median_difference,
                baseline: baseline.median,
                dev: dev.median,
            }
        },
        Calculation {
            metric: ["stddev", metric].join("_"),
            regression: stddev_difference > stddev_threshold,
            data: Data {
                threshold: stddev_threshold,
                difference: stddev_difference,
                baseline: baseline.stddev,
                dev: dev.stddev,
            }
        },
    ]
}

// given a directory, read all files in the directory and return each
// filename with the deserialized json contents of that file
fn measurements_from_files(
    results_directory: &Path,
) -> Result<Vec<(PathBuf, Measurements)>, CalculateError> {
    let result_files = fs::read_dir(results_directory)
        .or_else(|e| Err(IOError::ReadErr(results_directory.to_path_buf(), Some(e))))
        .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

    result_files
        .into_iter()
        .map(|entry| {
            let ent: DirEntry = entry.or_else(|e| Err(IOError::ReadErr(results_directory.to_path_buf(), Some(e))))
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

            Ok(ent.path())
        })
        .collect::<Result<Vec<PathBuf>, CalculateError>>()?
        .into_iter()
        .filter(|path| {
            path
                .extension()
                .and_then(|ext| ext.to_str())
                .map_or(false, |ext| ext.ends_with("json"))
        })
        .map(|path| {
            fs::read_to_string(&path)
                .or_else(|e| Err(IOError::BadFileContentsErr(path.clone(), Some(e))))
                .or_else(|e| Err(CalculateError::CalculateIOError(e)))
                .and_then(|contents| {
                    serde_json::from_str::<Measurements>(&contents)
                        .or_else(|e| Err(CalculateError::BadJSONErr(path.clone(), Some(e))))
                })
                .map(|m| (path, m))
        })
        .collect()
}

// given a list of filename-measurement pairs, detect any regressions by grouping
// measurements together by filename
fn calculate_regressions(
    measurements: &[(PathBuf, Measurement)],
) -> Result<Vec<Calculation>, CalculateError> {
    let mut measurement_groups: Vec<MeasurementGroup> = measurements
        .into_iter()
        .map(|(p, m)| {
            p.file_name()
                .ok_or_else(|| IOError::MissingFilenameErr(p.to_path_buf()))
                .and_then(|name| {
                    name.to_str()
                        .ok_or_else(|| IOError::FilenameNotUnicodeErr(p.to_path_buf()))
                })
                .map(|name| {
                    let parts: Vec<&str> = name.split("_").collect();
                    MeasurementGroup {
                        version: parts[0].to_owned(),
                        run: parts[1..].join("_"),
                        measurement: m.clone(),
                    }
                })
        })
        .collect::<Result<Vec<MeasurementGroup>, IOError>>()
        .or_else(|e| Err(CalculateError::CalculateIOError(e)))?;

    measurement_groups.sort_by(|x, y| (&x.run, &x.version).cmp(&(&y.run, &y.version)));

    // locking up mutation
    let sorted_measurement_groups = measurement_groups;

    let calculations: Vec<Calculation> = sorted_measurement_groups
        .into_iter()
        .group_by(|x| x.run.clone())
        .into_iter()
        .map(|(_, g)| {
            let mut groups: Vec<MeasurementGroup> = g.collect();
            groups.sort_by(|x, y| x.version.cmp(&y.version));

            match groups.len() {
                2 => {
                    let dev = &groups[1];
                    let baseline = &groups[0];

                    if dev.version == "dev" && baseline.version == "baseline" {
                        Ok(calculate(&dev.run, &dev.measurement, &baseline.measurement))
                    } else {
                        Err(CalculateError::BadBranchNameErr(baseline.version.clone(), dev.version.clone()))
                    }
                },
                i => Err(CalculateError::BadGroupSizeErr(i, groups)),
            }
        })
        .collect::<Result<Vec<Vec<Calculation>>, CalculateError>>()?
        .concat();

    Ok(calculations)
}

pub fn regressions(results_directory: &PathBuf) -> Result<Vec<Calculation>, CalculateError> {
    measurements_from_files(Path::new(&results_directory)).and_then(|v| match v[..] {
        // exit early with an Err if there are no results to process
        [] => {
            Err(CalculateError::NoResultsErr(results_directory.clone()))
        },

        _ => {
            // we expect two runs for each project-metric pairing: one for each branch, baseline
            // and dev. An odd result count is unexpected.
            if v.len() % 2 == 1 {
                Err(CalculateError::OddResultsCountErr(v.len(), results_directory.clone()))
            } else {
                // otherwise, we can do our comparisons
                let measurements = v
                    .into_iter()
                    // the way we're running these, the files will each contain exactly one measurement, hence `results[0]`
                    .map(|(p, ms)| (p, ms.results[0].clone()))
                    .collect::<Vec<(PathBuf, Measurement)>>();

                calculate_regressions(&measurements)
            }
        },
    })
}
<|endoftext|>


<commit_before>// These methods are described in:
// http://nadeausoftware.com/articles/2012/07/c_c_tip_how_get_process_resident_set_size_physical_memory_use

use libc;
use super::Result;

/// Get the current RSS memory of this process in KB
#[cfg(target_os = "linux")]
pub fn current_rss() -> Result<u64> {
    os::current_rss()
}

/// Get the current RSS memory of a process with given pid in KB
#[cfg(target_os = "linux")]
pub fn current_rss_of(pid: libc::pid_t) -> Result<u64> {
    os::current_rss_of(pid)
}

#[cfg(target_os = "linux")]
mod os {
    use libc;
    use std::path::Path;
    use super::super::Result;
    use super::super::ProbeError;
    use super::super::file_to_string;

    #[inline]
    pub fn current_rss() -> Result<u64> {
        read_and_get_current_rss(&Path::new("/proc/self/statm"))
    }

    #[inline]
    pub fn current_rss_of(pid: libc::pid_t) -> Result<u64> {
        read_and_get_current_rss(&Path::new(&format!("/proc/{}/statm", pid)))
    }

    #[inline]
    pub fn read_and_get_current_rss(path: &Path) -> Result<u64> {
        let raw_data = try!(file_to_string(path));
        let segments: Vec<&str> = raw_data.split_whitespace().collect();

        if segments.len() < 2 {
            return Err(ProbeError::UnexpectedContent("Incorrect number of segments".to_owned()))
        }

        let pages: u64 = try!(segments[1].parse().map_err(|_| {
            ProbeError::UnexpectedContent("Could not parse segment".to_owned())
        }));

        // Value is in pages, needs to be multiplied by the page size to get a value in KB. We ask the OS
        // for this information using sysconf.
        let pagesize = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u64;

        Ok(pages * pagesize)
    }
}

#[cfg(test)]
mod tests {
    use libc;
    use std::path::Path;
    use super::super::ProbeError;

    #[test]
    fn test_current_rss() {
        assert!(super::current_rss().is_ok());
        // See if it's a sort of sane value, between 1 and 10 mb
        assert!(super::current_rss().unwrap() > 1_000_000);
        assert!(super::current_rss().unwrap() < 10_000_000);
    }

    #[test]
    fn test_read_and_get_current_rss() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm");
        let value = super::os::read_and_get_current_rss(&path).unwrap();
        assert_eq!(4_661_248, value);
    }

    #[test]
    fn test_read_and_get_current_rss_wrong_path() {
        let path = Path::new("/nonsense");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::IO(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_read_and_get_current_rss_incomplete() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm_incomplete");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::UnexpectedContent(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_read_and_get_current_rss_garbage() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm_garbage");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::UnexpectedContent(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_current_rss_of() {
        let pid = unsafe { libc::getpid() };
        assert!(super::current_rss_of(pid).is_ok());
        // See if it's a sort of sane value, between 1 and 10 mb
        assert!(super::current_rss_of(pid).unwrap() > 1_000_000);
        assert!(super::current_rss_of(pid).unwrap() < 10_000_000);
    }

    #[test]
    fn test_current_rss_of_invalid_pid() {
        assert!(super::current_rss_of(0).is_err());
    }
}
<commit_msg>Add max rss to process memory<commit_after>// These methods are described in:
// http://nadeausoftware.com/articles/2012/07/c_c_tip_how_get_process_resident_set_size_physical_memory_use

use libc;
use super::Result;

/// Get the current RSS memory of this process in KB
#[cfg(target_os = "linux")]
pub fn current_rss() -> Result<u64> {
    os::current_rss()
}

/// Get the current RSS memory of a process with given pid in KB
#[cfg(target_os = "linux")]
pub fn current_rss_of(pid: libc::pid_t) -> Result<u64> {
    os::current_rss_of(pid)
}

/// Get the max RSS memory of this process in KB
#[cfg(target_os = "linux")]
pub fn max_rss() -> u64 {
    os::max_rss()
}

#[cfg(target_os = "linux")]
mod os {
    use std::mem;
    use libc;
    use std::path::Path;
    use super::super::Result;
    use super::super::ProbeError;
    use super::super::file_to_string;

    #[inline]
    pub fn current_rss() -> Result<u64> {
        read_and_get_current_rss(&Path::new("/proc/self/statm"))
    }

    #[inline]
    pub fn current_rss_of(pid: libc::pid_t) -> Result<u64> {
        read_and_get_current_rss(&Path::new(&format!("/proc/{}/statm", pid)))
    }

    #[inline]
    pub fn read_and_get_current_rss(path: &Path) -> Result<u64> {
        let raw_data = try!(file_to_string(path));
        let segments: Vec<&str> = raw_data.split_whitespace().collect();

        if segments.len() < 2 {
            return Err(ProbeError::UnexpectedContent("Incorrect number of segments".to_owned()))
        }

        let pages: u64 = try!(segments[1].parse().map_err(|_| {
            ProbeError::UnexpectedContent("Could not parse segment".to_owned())
        }));

        // Value is in pages, needs to be multiplied by the page size to get a value in KB. We ask the OS
        // for this information using sysconf.
        let pagesize = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u64;

        Ok(pages * pagesize)
    }

    #[inline]
    pub fn max_rss() -> u64 {
        let mut rusage: libc::rusage = unsafe { mem::uninitialized() };
        unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut rusage) };
        rusage.ru_maxrss as u64
    }
}

#[cfg(test)]
mod tests {
    use libc;
    use std::path::Path;
    use super::super::ProbeError;

    #[test]
    fn test_current_rss() {
        assert!(super::current_rss().is_ok());
        // See if it's a sort of sane value, between 1 and 10 mb
        assert!(super::current_rss().unwrap() > 1_000_000);
        assert!(super::current_rss().unwrap() < 10_000_000);
    }

    #[test]
    fn test_read_and_get_current_rss() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm");
        let value = super::os::read_and_get_current_rss(&path).unwrap();
        assert_eq!(4_661_248, value);
    }

    #[test]
    fn test_read_and_get_current_rss_wrong_path() {
        let path = Path::new("/nonsense");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::IO(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_read_and_get_current_rss_incomplete() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm_incomplete");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::UnexpectedContent(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_read_and_get_current_rss_garbage() {
        let path = Path::new("fixtures/linux/process_memory/proc_self_statm_garbage");
        match super::os::read_and_get_current_rss(&path) {
            Err(ProbeError::UnexpectedContent(_)) => (),
            r => panic!("Unexpected result: {:?}", r)
        }
    }

    #[test]
    fn test_current_rss_of() {
        let pid = unsafe { libc::getpid() };
        assert!(super::current_rss_of(pid).is_ok());
        // See if it's a sort of sane value, between 1 and 10 mb
        assert!(super::current_rss_of(pid).unwrap() > 1_000_000);
        assert!(super::current_rss_of(pid).unwrap() < 10_000_000);
    }

    #[test]
    fn test_current_rss_of_invalid_pid() {
        assert!(super::current_rss_of(0).is_err());
    }

    #[test]
    fn test_max_rss() {
        // See if it's a sort of sane value, between 1 and 10 mb
        assert!(super::current_rss().unwrap() > 1_000_000);
        assert!(super::current_rss().unwrap() < 10_000_000);
    }
}
<|endoftext|>