<commit_before>// Copyright 2016 Pierre Marijon.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! GFF3 format reading and writing.
//!
//! GFF2 definition : http://gmod.org/wiki/GFF2#The_GFF2_File_Format (not yet support)
//! GTF2 definition : http://mblab.wustl.edu/GTF2.html (not yet support)
//! GFF3 definition : http://gmod.org/wiki/GFF3#GFF3_Format
//!
//! # Example
//!
//! ```
//! use std::io;
//! use bio::io::gff;
//! let reader = gff::Reader::new(io::stdin());
//! ```

use std::io;
use std::fs;
use std::path::Path;
use std::convert::AsRef;

use csv;

use io::Strand;

/// A GFF reader.
pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
}

impl Reader<fs::File> {
    /// Read GFF from given file path.
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::new)
    }
}

impl<R: io::Read> Reader<R> {
    /// Create a new GFF reader given an instance of `io::Read`.
    pub fn new(reader: R) -> Self {
        Reader {
            inner: csv::Reader::from_reader(reader).delimiter(b'\t').has_headers(false)
        }
    }

    /// Iterate over all records.
    pub fn records(&mut self) -> Records<R> {
        Records { inner: self.inner.decode() }
    }
}

/// A GFF record.
pub struct Records<'a, R: 'a + io::Read> {
    inner: csv::DecodedRecords<'a, R, (String, String, String, u64, u64, String, String, String, String)>,
}

impl<'a, R: io::Read> Iterator for Records<'a, R> {
    type Item = csv::Result<Record>;

    fn next(&mut self) -> Option<csv::Result<Record>> {
        self.inner.next().map(|res| {
            res.map(|(seqname, source, feature_type, start, end, score, strand, frame, attributes)| {
                Record {
                    seqname: seqname,
                    source: source,
                    feature_type: feature_type,
                    start: start,
                    end: end,
                    score: score,
                    strand: strand,
                    frame: frame,
                    attributes: csv::Reader::from_string(attributes)
                        .delimiter(b'=')
                        .record_terminator(csv::RecordTerminator::Any(b';'))
                        .has_headers(false)
                        .decode().collect::<csv::Result<Vec<(String, String)>>>().unwrap(),
                }
            })
        })
    }
}

/// A GFF writer.
pub struct Writer<W: io::Write> {
    inner: csv::Writer<W>,
}

impl Writer<fs::File> {
    /// Write to a given file path.
    pub fn to_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::create(path).map(Writer::new)
    }
}

impl<W: io::Write> Writer<W> {
    /// Write to a given writer.
    pub fn new(writer: W) -> Self {
        Writer { inner: csv::Writer::from_writer(writer).delimiter(b'\t').flexible(true) }
    }

    /// Write a given GFF record.
    pub fn write(&mut self, record: Record) -> csv::Result<()> {
        if !record.attributes.is_empty() {
            self.inner.encode((
                record.seqname,
                record.source,
                record.feature_type,
                record.start,
                record.end,
                record.score,
                record.strand,
                record.frame,
                record.attributes.iter().map(|&(ref a, ref b)| format!("{}={}", a, b)).collect::<Vec<_>>().join(";"),
                ))

        } else {
            self.inner.encode((record.seqname, record.source, record.feature_type, record.start, record.end, record.score, record.strand, record.frame))
        }
    }
}

/// A GFF record
#[derive(RustcEncodable)]
pub struct Record {
    seqname: String,
    source: String,
    feature_type: String,
    start: u64,
    end: u64,
    score: String,
    strand: String,
    frame: String,
    attributes: Vec<(String, String)>,
}

impl Record {
    /// Create a new GFF record.
    pub fn new() -> Self {
        Record {
            seqname: "".to_owned(),
            source: "".to_owned(),
            feature_type: "".to_owned(),
            start: 0,
            end: 0,
            score: ".".to_owned(),
            strand: ".".to_owned(),
            frame: "".to_owned(),
            attributes: Vec::<(String, String)>::new(),
        }
    }

    /// Sequence name of the feature.
    pub fn seqname(&self) -> &str {
        &self.seqname
    }

    /// Source of the feature.
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Type of the feature.
    pub fn feature_type(&self) -> &str {
        &self.feature_type
    }

    /// Start position of feature (1-based).
    pub fn start(&self) -> u64 {
        self.start
    }

    /// End position of feature (1-based, not included).
    pub fn end(&self) -> u64 {
        self.end
    }

    /// Score of feature
    pub fn score(&self) -> Option<u64> {
        match self.score.as_ref() {
            "." => None,
            _ => self.score.parse::<u64>().ok(),
        }
    }

    /// Strand of the feature.
    pub fn strand(&self) -> Option<Strand> {
        match self.strand.as_ref() {
            "+" => Some(Strand::Forward),
            "-" => Some(Strand::Reverse),
            _ => None,
        }
    }

    /// Frame of the feature.
    pub fn frame(&self) -> &str {
        &self.frame
    }

    /// Attribute of feature
    pub fn attributes(&self) -> &Vec<(String, String)> {
        &self.attributes
    }

    /// Set seqname of feature.
    pub fn set_seqname(&mut self, seqname: &str) {
        self.seqname = seqname.to_owned();
    }

    /// Set source of feature.
    pub fn set_source(&mut self, source: &str) {
        self.source = source.to_owned();
    }

    /// Set type of feature.
    pub fn set_feature_type(&mut self, feature_type: &str) {
        self.feature_type = feature_type.to_owned();
    }

    /// Set start of feature.
    pub fn set_start(&mut self, start: u64) {
        self.start = start;
    }

    /// Set end of feature.
    pub fn set_end(&mut self, end: u64) {
        self.end = end;
    }

    /// Set score of feature.
    pub fn set_score(&mut self, score: &str) {
        self.score = score.to_owned();
    }

    /// Set strand of feature.
    pub fn set_strand(&mut self, strand: &str) {
        self.strand = strand.to_owned();
    }

    pub fn set_attributes(&mut self, attributes: &Vec<(String, String)>) {
        &self.attributes = attributes;
    }
}

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

    const GFF_FILE: &'static [u8] = b"P0A7B8\tUniProtKB\tInitiator methionine\t1\t1\t.\t.\t.\tID=test;Note=Removed
P0A7B8\tUniProtKB\tChain\t2\t176\t50\t+\t.\tID=PRO_0000148105;Note=ATP-dependent protease subunit HslV
";

    #[test]
    fn test_reader() {
        let seqname = ["P0A7B8", "P0A7B8"];
        let source = ["UniProtKB", "UniProtKB"];
        let feature_type = ["Initiator methionine", "Chain"];
        let starts = [1, 2];
        let ends = [1, 176];
        let scores = [None, Some(50)];
        let strand = [None, Some(Strand::Forward)];
        let frame = [".", "."];
        let attributes = [[("ID", "test"),("Note","Removed")], [("ID","PRO_0000148105"),("Note","ATP-dependent protease subunit HslV")]];

        let mut reader = Reader::new(GFF_FILE);
        for (i, r) in reader.records().enumerate() {
            let record = r.ok().expect("Error reading record");
            assert_eq!(record.seqname(), seqname[i]);
            assert_eq!(record.source(), source[i]);
            assert_eq!(record.feature_type(), feature_type[i]);
            assert_eq!(record.start(), starts[i]);
            assert_eq!(record.end(), ends[i]);
            assert_eq!(record.score(), scores[i]);
            assert_eq!(record.strand(), strand[i]);
            assert_eq!(record.frame(), frame[i]);
            for (j, tuple) in record.attributes().iter().enumerate() {
                assert_eq!(tuple.0, attributes[i][j].0);
                assert_eq!(tuple.1, attributes[i][j].1);
            }
        }
    }

    #[test]
    fn test_writer() {
        let mut reader = Reader::new(GFF_FILE);
        let mut writer = Writer::new(vec![]);
        for r in reader.records() {
            writer.write(r.ok().expect("Error reading record")).ok().expect("Error writing record");
        }
        assert_eq!(writer.inner.as_string(), String::from_utf8_lossy(GFF_FILE))
    }
}
<commit_msg>Key Value struct is more expressive than table of tuple<commit_after>// Copyright 2016 Pierre Marijon.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! GFF3 format reading and writing.
//!
//! GFF2 definition : http://gmod.org/wiki/GFF2#The_GFF2_File_Format (not yet support)
//! GTF2 definition : http://mblab.wustl.edu/GTF2.html (not yet support)
//! GFF3 definition : http://gmod.org/wiki/GFF3#GFF3_Format
//!
//! # Example
//!
//! ```
//! use std::io;
//! use bio::io::gff;
//! let reader = gff::Reader::new(io::stdin());
//! ```

use std::io;
use std::fs;
use std::path::Path;
use std::convert::AsRef;
use std::collections::HashMap;

use csv;

use io::Strand;

/// A GFF reader.
pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
}

impl Reader<fs::File> {
    /// Read GFF from given file path.
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::new)
    }
}

impl<R: io::Read> Reader<R> {
    /// Create a new GFF reader given an instance of `io::Read`.
    pub fn new(reader: R) -> Self {
        Reader {
            inner: csv::Reader::from_reader(reader).delimiter(b'\t').has_headers(false)
        }
    }

    /// Iterate over all records.
    pub fn records(&mut self) -> Records<R> {
        Records { inner: self.inner.decode() }
    }
}

/// A GFF record.
pub struct Records<'a, R: 'a + io::Read> {
    inner: csv::DecodedRecords<'a, R, (String, String, String, u64, u64, String, String, String, String)>,
}

impl<'a, R: io::Read> Iterator for Records<'a, R> {
    type Item = csv::Result<Record>;

    fn next(&mut self) -> Option<csv::Result<Record>> {
        self.inner.next().map(|res| {
            res.map(|(seqname, source, feature_type, start, end, score, strand, frame, attributes)| {
                Record {
                    seqname: seqname,
                    source: source,
                    feature_type: feature_type,
                    start: start,
                    end: end,
                    score: score,
                    strand: strand,
                    frame: frame,
                    attributes: csv::Reader::from_string(attributes)
                        .delimiter(b'=')
                        .record_terminator(csv::RecordTerminator::Any(b';'))
                        .has_headers(false)
                        .decode().collect::<csv::Result<HashMap<String, String>>>().unwrap(),
                }
            })
        })
    }
}

/// A GFF writer.
pub struct Writer<W: io::Write> {
    inner: csv::Writer<W>,
}

impl Writer<fs::File> {
    /// Write to a given file path.
    pub fn to_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::create(path).map(Writer::new)
    }
}

impl<W: io::Write> Writer<W> {
    /// Write to a given writer.
    pub fn new(writer: W) -> Self {
        Writer { inner: csv::Writer::from_writer(writer).delimiter(b'\t').flexible(true) }
    }

    /// Write a given GFF record.
    pub fn write(&mut self, record: Record) -> csv::Result<()> {
        if !record.attributes.is_empty() {
            self.inner.encode((
                record.seqname,
                record.source,
                record.feature_type,
                record.start,
                record.end,
                record.score,
                record.strand,
                record.frame,
                record.attributes.iter().map(|(a, b)| format!("{}={}", a, b)).collect::<Vec<_>>().join(";"),
                ))

        } else {
            self.inner.encode((record.seqname, record.source, record.feature_type, record.start, record.end, record.score, record.strand, record.frame, ""))
        }
    }
}

/// A GFF record
#[derive(RustcEncodable)]
pub struct Record {
    seqname: String,
    source: String,
    feature_type: String,
    start: u64,
    end: u64,
    score: String,
    strand: String,
    frame: String,
    attributes: HashMap<String, String>,
}

impl Record {
    /// Create a new GFF record.
    pub fn new() -> Self {
        Record {
            seqname: "".to_owned(),
            source: "".to_owned(),
            feature_type: "".to_owned(),
            start: 0,
            end: 0,
            score: ".".to_owned(),
            strand: ".".to_owned(),
            frame: "".to_owned(),
            attributes: HashMap::<String, String>::new(),
        }
    }

    /// Sequence name of the feature.
    pub fn seqname(&self) -> &str {
        &self.seqname
    }

    /// Source of the feature.
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Type of the feature.
    pub fn feature_type(&self) -> &str {
        &self.feature_type
    }

    /// Start position of feature (1-based).
    pub fn start(&self) -> u64 {
        self.start
    }

    /// End position of feature (1-based, not included).
    pub fn end(&self) -> u64 {
        self.end
    }

    /// Score of feature
    pub fn score(&self) -> Option<u64> {
        match self.score.as_ref() {
            "." => None,
            _ => self.score.parse::<u64>().ok(),
        }
    }

    /// Strand of the feature.
    pub fn strand(&self) -> Option<Strand> {
        match self.strand.as_ref() {
            "+" => Some(Strand::Forward),
            "-" => Some(Strand::Reverse),
            _ => None,
        }
    }

    /// Frame of the feature.
    pub fn frame(&self) -> &str {
        &self.frame
    }

    /// Attribute of feature
    pub fn attributes(&self) -> &HashMap<String, String> {
        &self.attributes
    }

    /// Set seqname of feature.
    pub fn set_seqname(&mut self, seqname: &str) {
        self.seqname = seqname.to_owned();
    }

    /// Set source of feature.
    pub fn set_source(&mut self, source: &str) {
        self.source = source.to_owned();
    }

    /// Set type of feature.
    pub fn set_feature_type(&mut self, feature_type: &str) {
        self.feature_type = feature_type.to_owned();
    }

    /// Set start of feature.
    pub fn set_start(&mut self, start: u64) {
        self.start = start;
    }

    /// Set end of feature.
    pub fn set_end(&mut self, end: u64) {
        self.end = end;
    }

    /// Set score of feature.
    pub fn set_score(&mut self, score: &str) {
        self.score = score.to_owned();
    }

    /// Set strand of feature.
    pub fn set_strand(&mut self, strand: &str) {
        self.strand = strand.to_owned();
    }

    // pub fn set_attributes(&mut self, attributes: &HashMap<String, String>) {
    //     self.attributes = attributes;
    // }
}

#[cfg(test)]
mod tests {
    use super::*;
    use io::Strand;
    use std::collections::HashMap;

    const GFF_FILE: &'static [u8] = b"P0A7B8\tUniProtKB\tInitiator methionine\t1\t1\t.\t.\t.\tNote=Removed;ID=test
P0A7B8\tUniProtKB\tChain\t2\t176\t50\t+\t.\tNote=ATP-dependent protease subunit HslV;ID=PRO_0000148105
";
    //required because HashMap iter on element randomly
    const GFF_FILE_NO_ATTRIB: &'static [u8] = b"P0A7B8\tUniProtKB\tInitiator methionine\t1\t1\t.\t.\t.\t
P0A7B8\tUniProtKB\tChain\t2\t176\t50\t+\t.\t
";

    #[test]
    fn test_reader() {
        let seqname = ["P0A7B8", "P0A7B8"];
        let source = ["UniProtKB", "UniProtKB"];
        let feature_type = ["Initiator methionine", "Chain"];
        let starts = [1, 2];
        let ends = [1, 176];
        let scores = [None, Some(50)];
        let strand = [None, Some(Strand::Forward)];
        let frame = [".", "."];
        let mut attributes = [HashMap::new(), HashMap::new()];
        attributes[0].insert("ID".to_owned(), "test".to_owned());
        attributes[0].insert("Note".to_owned(), "Removed".to_owned());
        attributes[1].insert("ID".to_owned(), "PRO_0000148105".to_owned());
        attributes[1].insert("Note".to_owned(), "ATP-dependent protease subunit HslV".to_owned());

        let mut reader = Reader::new(GFF_FILE);
        for (i, r) in reader.records().enumerate() {
            let record = r.ok().expect("Error reading record");
            assert_eq!(record.seqname(), seqname[i]);
            assert_eq!(record.source(), source[i]);
            assert_eq!(record.feature_type(), feature_type[i]);
            assert_eq!(record.start(), starts[i]);
            assert_eq!(record.end(), ends[i]);
            assert_eq!(record.score(), scores[i]);
            assert_eq!(record.strand(), strand[i]);
            assert_eq!(record.frame(), frame[i]);
            assert_eq!(record.attributes, attributes[i]);
        }
    }

    #[test]
    fn test_writer() {
        let mut reader = Reader::new(GFF_FILE_NO_ATTRIB);
        let mut writer = Writer::new(vec![]);
        for r in reader.records() {
            writer.write(r.ok().expect("Error reading record")).ok().expect("Error writing record");
        }
        assert_eq!(writer.inner.as_string(), String::from_utf8_lossy(GFF_FILE_NO_ATTRIB))
    }
}
<|endoftext|>


<commit_before>//! Endpoints that expose metadata about crate versions
//!
//! These endpoints provide data that could be obtained direclty from the
//! index or cached metadata which was extracted (client side) from the
//! `Cargo.toml` file.

use crate::controllers::frontend_prelude::*;

use crate::models::VersionOwnerAction;
use crate::schema::*;
use crate::views::{EncodableDependency, EncodablePublicUser, EncodableVersion};

use super::{extract_crate_name_and_semver, version_and_crate};

/// Handles the `GET /crates/:crate_id/:version/dependencies` route.
///
/// This information can be obtained direclty from the index.
///
/// In addition to returning cached data from the index, this returns
/// fields for `id`, `version_id`, and `downloads` (which appears to always
/// be 0)
pub fn dependencies(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;
    let conn = req.db_read_only()?;
    let (version, _) = version_and_crate(&conn, crate_name, semver)?;
    let deps = version.dependencies(&conn)?;
    let deps = deps
        .into_iter()
        .map(|(dep, crate_name)| EncodableDependency::from_dep(dep, &crate_name))
        .collect();

    #[derive(Serialize)]
    struct R {
        dependencies: Vec<EncodableDependency>,
    }
    Ok(req.json(&R { dependencies: deps }))
}

/// Handles the `GET /crates/:crate_id/:version/authors` route.
pub fn authors(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;
    let conn = req.db_read_only()?;
    let (version, _) = version_and_crate(&conn, crate_name, semver)?;
    let names = version_authors::table
        .filter(version_authors::version_id.eq(version.id))
        .select(version_authors::name)
        .order(version_authors::name)
        .load(&*conn)?;

    // It was imagined that we wold associate authors with users.
    // This was never implemented. This complicated return struct
    // is all that is left, hear for backwards compatibility.
    #[derive(Serialize)]
    struct R {
        users: Vec<EncodablePublicUser>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        names: Vec<String>,
    }
    Ok(req.json(&R {
        users: vec![],
        meta: Meta { names },
    }))
}

/// Handles the `GET /crates/:crate/:version` route.
///
/// The frontend doesn't appear to hit this endpoint, but our tests do, and it seems to be a useful
/// API route to have.
pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;
    let conn = req.db_read_only()?;
    let (version, krate) = version_and_crate(&conn, crate_name, semver)?;
    let published_by = version.published_by(&conn);
    let actions = VersionOwnerAction::by_version(&conn, &version)?;

    #[derive(Serialize)]
    struct R {
        version: EncodableVersion,
    }
    Ok(req.json(&R {
        version: EncodableVersion::from(version, &krate.name, published_by, actions),
    }))
}
<commit_msg>Return the empty list for authors API<commit_after>//! Endpoints that expose metadata about crate versions
//!
//! These endpoints provide data that could be obtained direclty from the
//! index or cached metadata which was extracted (client side) from the
//! `Cargo.toml` file.

use crate::controllers::frontend_prelude::*;

use crate::models::VersionOwnerAction;
use crate::views::{EncodableDependency, EncodablePublicUser, EncodableVersion};

use super::{extract_crate_name_and_semver, version_and_crate};

/// Handles the `GET /crates/:crate_id/:version/dependencies` route.
///
/// This information can be obtained direclty from the index.
///
/// In addition to returning cached data from the index, this returns
/// fields for `id`, `version_id`, and `downloads` (which appears to always
/// be 0)
pub fn dependencies(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;
    let conn = req.db_read_only()?;
    let (version, _) = version_and_crate(&conn, crate_name, semver)?;
    let deps = version.dependencies(&conn)?;
    let deps = deps
        .into_iter()
        .map(|(dep, crate_name)| EncodableDependency::from_dep(dep, &crate_name))
        .collect();

    #[derive(Serialize)]
    struct R {
        dependencies: Vec<EncodableDependency>,
    }
    Ok(req.json(&R { dependencies: deps }))
}

/// Handles the `GET /crates/:crate_id/:version/authors` route.
pub fn authors(req: &mut dyn RequestExt) -> EndpointResult {
    // Currently we return the empty list.
    // Because the API is not used anymore after RFC https://github.com/rust-lang/rfcs/pull/3052.
    #[derive(Serialize)]
    struct R {
        users: Vec<EncodablePublicUser>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        names: Vec<String>,
    }
    Ok(req.json(&R {
        users: vec![],
        meta: Meta { names: vec![] },
    }))
}

/// Handles the `GET /crates/:crate/:version` route.
///
/// The frontend doesn't appear to hit this endpoint, but our tests do, and it seems to be a useful
/// API route to have.
pub fn show(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;
    let conn = req.db_read_only()?;
    let (version, krate) = version_and_crate(&conn, crate_name, semver)?;
    let published_by = version.published_by(&conn);
    let actions = VersionOwnerAction::by_version(&conn, &version)?;

    #[derive(Serialize)]
    struct R {
        version: EncodableVersion,
    }
    Ok(req.json(&R {
        version: EncodableVersion::from(version, &krate.name, published_by, actions),
    }))
}
<|endoftext|>


<commit_before>use std::str;
use std::time::{Duration,Instant};
use std::collections::VecDeque;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,LineWriter,Write,ErrorKind};
use std::collections::HashMap;
use super::writer::{MetricSocket, MetricsWriter};

use super::{Subscriber,MetricData,StoredMetricData};

const VERSION: &str = env!("CARGO_PKG_VERSION");

#[derive(Debug,Clone,PartialEq)]
pub struct MetricLine {
  label:      &'static str,
  app_id:     Option<String>,
  backend_id: Option<String>,
  /// in milliseconds
  duration:   usize,
}

pub struct NetworkDrain {
  queue:              VecDeque<MetricLine>,
  pub prefix:         String,
  pub remote:         MetricsWriter,
  is_writable:        bool,
  data:               HashMap<String, StoredMetricData>,
  /// (app_id, key) -> metric
  app_data:           HashMap<(String, String), StoredMetricData>,
  /// (app_id, backend_id, key) -> metric
  backend_data:       HashMap<(String, String, String), StoredMetricData>,
  pub use_tagged_metrics: bool,
  pub origin:         String,
  created:            Instant,
}

impl NetworkDrain {
  pub fn new(prefix: String, socket: UdpSocket, addr: SocketAddr) -> Self {
    socket.connect(addr).unwrap();

    NetworkDrain {
      queue:  VecDeque::new(),
      prefix,
      remote: MetricsWriter::new(MetricSocket {
        addr, socket
      }),
      is_writable: true,
      data: HashMap::new(),
      app_data: HashMap::new(),
      backend_data: HashMap::new(),
      use_tagged_metrics: false,
      origin: String::from("x"),
      created: Instant::now(),
    }
  }

  pub fn writable(&mut self) {
    self.is_writable = true;
  }

  pub fn send_data(&mut self) {
    let now  = Instant::now();
    let secs = Duration::new(2, 0);
    let mut send_count = 0;

    // remove metrics that were not touched in the last 10mn
    self.app_data.retain(|ref key, ref value| value.updated || now.duration_since(value.last_sent) < Duration::new(600, 00));
    self.backend_data.retain(|ref key, ref value| value.updated || now.duration_since(value.last_sent) < Duration::new(600, 00));

    if self.is_writable {

    for (ref key, ref mut stored_metric) in self.data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|g\n", self.prefix, key, self.origin, VERSION, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|g\n", self.prefix, self.origin, key, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|c\n", self.prefix, key, self.origin, VERSION, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|c\n", self.prefix, self.origin, key, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing global metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for (ref key, ref mut stored_metric) in self.app_data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {:?} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|g\n",
              self.prefix, key.1, self.origin, VERSION, key.0, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|g\n", self.prefix, self.origin, key.0, key.1, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|c\n",
              self.prefix, key.1, self.origin, VERSION, key.0, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|c\n", self.prefix, self.origin, key.0, key.1, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing app metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for (ref key, ref mut stored_metric) in self.backend_data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {:?} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|g\n",
              self.prefix, key.2, self.origin, VERSION, key.0, key.1, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|g\n", self.prefix, self.origin, key.0, key.1, key.2, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|c\n",
              self.prefix, key.2, self.origin, VERSION, key.0, key.1, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|c\n", self.prefix, self.origin, key.0, key.1, key.2, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) =self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing backend metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }
    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for metric in self.queue.drain(..) {
       let res = match (metric.app_id, metric.backend_id) {
        (Some(app_id), Some(backend_id)) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, app_id, backend_id, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|ms\n", self.prefix, self.origin, app_id, backend_id,
              metric.label, metric.duration))
          }
        },
        (Some(app_id), None) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, app_id, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|ms\n", self.prefix, self.origin, app_id,
              metric.label, metric.duration))
          }
        },
        (None, None) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|ms\n", self.prefix, self.origin,
              metric.label, metric.duration))
          }
        },
        _ => { Ok(()) }
      };

      match res {
        Ok(()) => {
          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing timing metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/
    }
  }
}

impl Subscriber for NetworkDrain {
  fn receive_metric(&mut self, key: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData) {
    if metric.is_time() {
      if let MetricData::Time(millis) = metric {
        self.queue.push_back(MetricLine {
          label: key,
          app_id: app_id.map(|s| s.to_string()),
          backend_id: backend_id.map(|s| s.to_string()),
          duration: millis,
        });
      }
    } else if let Some(id) = app_id {
      if let Some(bid) = backend_id {
        let k = (String::from(id), String::from(bid), String::from(key));
        if !self.backend_data.contains_key(&k) {
          self.backend_data.insert(
            k,
            StoredMetricData::new(self.created, metric)
            );
        } else {
          self.backend_data.get_mut(&k).map(|stored_metric| {
            stored_metric.update(key, metric);
          });
        }
      } else {
        let k = (String::from(id), String::from(key));
        if !self.app_data.contains_key(&k) {
          self.app_data.insert(
            k,
            StoredMetricData::new(self.created, metric)
            );
        } else {
          self.app_data.get_mut(&k).map(|stored_metric| {
            stored_metric.update(key, metric);
          });
        }
      }
    } else if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData::new(self.created, metric)
        );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        stored_metric.update(key, metric);
      });
    }
  }
}

<commit_msg>send metrics every second instead of 2 seconds<commit_after>use std::str;
use std::time::{Duration,Instant};
use std::collections::VecDeque;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,LineWriter,Write,ErrorKind};
use std::collections::HashMap;
use super::writer::{MetricSocket, MetricsWriter};

use super::{Subscriber,MetricData,StoredMetricData};

const VERSION: &str = env!("CARGO_PKG_VERSION");

#[derive(Debug,Clone,PartialEq)]
pub struct MetricLine {
  label:      &'static str,
  app_id:     Option<String>,
  backend_id: Option<String>,
  /// in milliseconds
  duration:   usize,
}

pub struct NetworkDrain {
  queue:              VecDeque<MetricLine>,
  pub prefix:         String,
  pub remote:         MetricsWriter,
  is_writable:        bool,
  data:               HashMap<String, StoredMetricData>,
  /// (app_id, key) -> metric
  app_data:           HashMap<(String, String), StoredMetricData>,
  /// (app_id, backend_id, key) -> metric
  backend_data:       HashMap<(String, String, String), StoredMetricData>,
  pub use_tagged_metrics: bool,
  pub origin:         String,
  created:            Instant,
}

impl NetworkDrain {
  pub fn new(prefix: String, socket: UdpSocket, addr: SocketAddr) -> Self {
    socket.connect(addr).unwrap();

    NetworkDrain {
      queue:  VecDeque::new(),
      prefix,
      remote: MetricsWriter::new(MetricSocket {
        addr, socket
      }),
      is_writable: true,
      data: HashMap::new(),
      app_data: HashMap::new(),
      backend_data: HashMap::new(),
      use_tagged_metrics: false,
      origin: String::from("x"),
      created: Instant::now(),
    }
  }

  pub fn writable(&mut self) {
    self.is_writable = true;
  }

  pub fn send_data(&mut self) {
    let now  = Instant::now();
    let secs = Duration::new(1, 0);
    let mut send_count = 0;

    // remove metrics that were not touched in the last 10mn
    self.app_data.retain(|ref key, ref value| value.updated || now.duration_since(value.last_sent) < Duration::new(600, 00));
    self.backend_data.retain(|ref key, ref value| value.updated || now.duration_since(value.last_sent) < Duration::new(600, 00));

    if self.is_writable {

    for (ref key, ref mut stored_metric) in self.data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|g\n", self.prefix, key, self.origin, VERSION, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|g\n", self.prefix, self.origin, key, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|c\n", self.prefix, key, self.origin, VERSION, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|c\n", self.prefix, self.origin, key, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing global metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for (ref key, ref mut stored_metric) in self.app_data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {:?} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|g\n",
              self.prefix, key.1, self.origin, VERSION, key.0, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|g\n", self.prefix, self.origin, key.0, key.1, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|c\n",
              self.prefix, key.1, self.origin, VERSION, key.0, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|c\n", self.prefix, self.origin, key.0, key.1, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing app metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for (ref key, ref mut stored_metric) in self.backend_data.iter_mut().filter(|&(_, ref value)| value.updated && now.duration_since(value.last_sent) > secs) {
      //info!("will write {:?} -> {:#?}", key, stored_metric);
      let res = match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|g\n",
              self.prefix, key.2, self.origin, VERSION, key.0, key.1, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|g\n", self.prefix, self.origin, key.0, key.1, key.2, value))
          }
        },
        MetricData::Count(value) => {
          if value == 0 {
            stored_metric.last_sent = now;
          }

          let res = if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|c\n",
              self.prefix, key.2, self.origin, VERSION, key.0, key.1, value))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|c\n", self.prefix, self.origin, key.0, key.1, key.2, value))
          };

          if res.is_ok() {
            stored_metric.data = MetricData::Count(0);
          }

          res
        },
        _ => {Ok(())}
      };

      match res {
        Ok(()) => {
          stored_metric.last_sent = now;
          stored_metric.updated = false;

          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) =self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing backend metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }
    }
    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/

    if self.is_writable {
    for metric in self.queue.drain(..) {
       let res = match (metric.app_id, metric.backend_id) {
        (Some(app_id), Some(backend_id)) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.backend.{},origin={},version={},app_id={},backend_id={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, app_id, backend_id, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.backend.{}.{}:{}|ms\n", self.prefix, self.origin, app_id, backend_id,
              metric.label, metric.duration))
          }
        },
        (Some(app_id), None) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.app.{},origin={},version={},app_id={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, app_id, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.app.{}.{}:{}|ms\n", self.prefix, self.origin, app_id,
              metric.label, metric.duration))
          }
        },
        (None, None) => {
          if self.use_tagged_metrics {
            self.remote.write_fmt(format_args!("{}.{},origin={},version={}:{}|ms\n",
              self.prefix, metric.label, self.origin, VERSION, metric.duration))
          } else {
            self.remote.write_fmt(format_args!("{}.{}.{}:{}|ms\n", self.prefix, self.origin,
              metric.label, metric.duration))
          }
        },
        _ => { Ok(()) }
      };

      match res {
        Ok(()) => {
          send_count += 1;
          if send_count >= 10 {
            /*if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }*/
            send_count = 0;
          }
        },
        Err(e) => match e.kind() {
          ErrorKind::WriteZero => {
            if let Err(e) = self.remote.flush() {
              error!("error flushing metrics socket: {:?}", e);
            }
          },
          ErrorKind::WouldBlock => {
            error!("WouldBlock while writing timing metrics to socket");
            self.is_writable = false;
            break;
          },
          e => {
            error!("metrics socket write error={:?}", e);
            break;
          },
        }
      }
    }

    /*if let Err(e) = self.remote.flush() {
      error!("error flushing metrics socket: {:?}", e);
    }*/
    }
  }
}

impl Subscriber for NetworkDrain {
  fn receive_metric(&mut self, key: &'static str, app_id: Option<&str>, backend_id: Option<&str>, metric: MetricData) {
    if metric.is_time() {
      if let MetricData::Time(millis) = metric {
        self.queue.push_back(MetricLine {
          label: key,
          app_id: app_id.map(|s| s.to_string()),
          backend_id: backend_id.map(|s| s.to_string()),
          duration: millis,
        });
      }
    } else if let Some(id) = app_id {
      if let Some(bid) = backend_id {
        let k = (String::from(id), String::from(bid), String::from(key));
        if !self.backend_data.contains_key(&k) {
          self.backend_data.insert(
            k,
            StoredMetricData::new(self.created, metric)
            );
        } else {
          self.backend_data.get_mut(&k).map(|stored_metric| {
            stored_metric.update(key, metric);
          });
        }
      } else {
        let k = (String::from(id), String::from(key));
        if !self.app_data.contains_key(&k) {
          self.app_data.insert(
            k,
            StoredMetricData::new(self.created, metric)
            );
        } else {
          self.app_data.get_mut(&k).map(|stored_metric| {
            stored_metric.update(key, metric);
          });
        }
      }
    } else if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData::new(self.created, metric)
        );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        stored_metric.update(key, metric);
      });
    }
  }
}

<|endoftext|>


<commit_before>use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::slice;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::os::unix::io::AsRawFd;
use nix::sys::event::{ev_set, kqueue, kevent, KEvent, EventFilter, EventFlag, FilterFlag};
use libc::{uintptr_t, intptr_t};
use std::io::Result;
use event::Event;
use notification::Notification;
use user_event::UserEvent;
use nix_err_to_io_err;

type UserData = intptr_t;

static KQUEUE_EVENT_SIZE: usize = 1024;

pub struct KernelPoller {
    kqueue: RawFd,
    registrar: KernelRegistrar,
    eventlist: Vec<KEvent>,
    notifications: HashMap<RawFd, Notification>
}

impl KernelPoller {
    pub fn new() -> Result<KernelPoller> {
        let kq = kqueue().map_err(nix_err_to_io_err)?;
        let registrations = Arc::new(AtomicUsize::new(1));
        Ok(KernelPoller {
            kqueue: kq,
            registrar: KernelRegistrar::new(kq, registrations),
            eventlist: Vec::with_capacity(KQUEUE_EVENT_SIZE),
            notifications: HashMap::with_capacity(KQUEUE_EVENT_SIZE)
        })
    }

    // This will always succeed. We implement it this way for api compatibility with epoll.
    pub fn get_registrar(&self) -> Result<KernelRegistrar> {
        Ok(self.registrar.clone())
    }

    // Wait for kevents and return a list of Notifications. Coalesce reads and writes for the same
    // socket into a single notification. If only a read or a write event for a given socket is
    // present in the eventlist, check the registration to see if there is another kevent registered
    //  and remove it if so. We do this removal to prevent aliasing a pointer to the same
    // registration structure.
    pub fn wait(&mut self, timeout_ms: usize) -> Result<Vec<Notification>> {

        // Create a buffer to read events into
        let dst = unsafe {
            slice::from_raw_parts_mut(self.eventlist.as_mut_ptr(), self.eventlist.capacity())
        };

        let count = kevent(self.kqueue, &[], dst, timeout_ms).map_err(nix_err_to_io_err)?;

        // Set the length of the vector to the number of events that was returned by kevent
        unsafe { self.eventlist.set_len(count); }

        self.coalesce_events();
        Ok(self.notifications.drain().map(|(_, v)| v).collect())
    }

    // Combine read and write events for the same socket into a single notification.
    fn coalesce_events(&mut self) {
        for e in self.eventlist.drain(..) {
            let event = event_from_filter(e.filter());
            let new_notification = Notification {
                id: e.udata() as usize,
                event: event.clone()
            };

            let mut notification = self.notifications.entry(e.ident() as RawFd)
                                                     .or_insert(new_notification);
            if notification.event != event {
                notification.event = Event::Both
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct KernelRegistrar {
    kqueue: RawFd,
    total_registrations: Arc<AtomicUsize>
}

impl KernelRegistrar {
    // Explicitly not public. KernelRegistrar's are tied to KernelPollers and are retreived via
    // calls to poller.get_registrar().
    fn new(kq: RawFd, registrations: Arc<AtomicUsize>) -> KernelRegistrar {
        KernelRegistrar {
            kqueue: kq,
            total_registrations: registrations
        }
    }

    // This will always succeed. We implement this to provide api compatibility with epoll.
    pub fn try_clone(&self) -> Result<KernelRegistrar> {
        Ok(self.clone())
    }

    pub fn register<T: AsRawFd>(&self, sock: &T, event: Event) -> Result<usize> {
        let sock_fd = sock.as_raw_fd();
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = make_changelist(sock_fd, event, id as UserData);
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(id)
    }

    pub fn reregister<T: AsRawFd>(&self, id: usize, sock: &T, event: Event) -> Result<()> {
        let sock_fd = sock.as_raw_fd();
        let changes = make_changelist(sock_fd, event, id as UserData);
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn deregister<T: AsRawFd>(&self, sock: &T) -> Result<()> {
        let sock_fd = sock.as_raw_fd();
        let mut changes = make_changelist(sock_fd, Event::Both, 0);
        for e in changes.iter_mut() {
            set_flags(e, EventFlag::EV_DELETE);
        }
        // Just ignore errors because, one of the events may not be present, but the deregister
        // signature ignores that fact. At this point, ownership of the socket is taken so it's
        // irrelevant anyway.
        let _ = kevent(self.kqueue, &changes, &mut[], 0);
        Ok(())
    }

    pub fn register_user_event(&mut self) -> Result<UserEvent> {
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = vec![make_user_event(id)];
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(UserEvent {id: id, registrar: self.clone()})
    }

    pub fn trigger_user_event(&self, event: &UserEvent) -> Result<()> {
        let mut e = make_user_event(event.get_id());
        set_fflags(&mut e, FilterFlag::NOTE_TRIGGER);
        kevent(self.kqueue, &vec![e], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn clear_user_event(&self, event: &UserEvent) -> Result<()> {
        let mut user_event = make_user_event(event.get_id());
        set_flags(&mut user_event, EventFlag::EV_DISABLE);
        kevent(self.kqueue, &vec![user_event], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn deregister_user_event(&self, event_id: usize) -> Result<()> {
        let mut user_event = make_user_event(event_id);
        set_flags(&mut user_event, EventFlag::EV_DELETE);
        kevent(self.kqueue, &vec![user_event], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn set_timeout(&self, timeout: usize) -> Result<usize> {
        self.set_timer(timeout, false)
    }

    pub fn set_interval(&self, timeout: usize) -> Result<usize> {
        self.set_timer(timeout, true)
    }

    pub fn cancel_timeout(&self, timer_id: usize) -> Result<()> {
        let mut e = make_timer(timer_id, 0, false);
        set_flags(&mut e, EventFlag::EV_DELETE);
        kevent(self.kqueue, &vec![e], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    fn set_timer(&self, timeout: usize, recurring: bool) -> Result<usize> {
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = vec![make_timer(id, timeout, recurring)];
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(id)
    }
}

fn event_from_filter(filter: EventFilter) -> Event {
    // TODO: Change Event to allow returning TIMER events instead of marking them READ
    if filter == EventFilter::EVFILT_READ ||
       filter == EventFilter::EVFILT_TIMER ||
       filter == EventFilter::EVFILT_USER {
        Event::Read
    } else {
        Event::Write
    }
}

// Each event in kqueue must have its own filter. In other words, there are seperate events for
// reads and writes on the same socket. We create the proper number of KEvents based on the enum
// variant in the `event` paramter.
fn make_changelist(sock_fd: RawFd, event: Event, user_data: UserData) -> Vec<KEvent> {
    let ev = KEvent::new(
        sock_fd as uintptr_t,
        EventFilter::EVFILT_READ,
         EventFlag::EV_ADD,
        FilterFlag::empty(),
        0,
        user_data
    );

    match event {
        Event::Read => vec![ev],
        Event::Write => {
            vec![KEvent::new(ev.ident(), EventFilter::EVFILT_WRITE, ev.flags(), ev.fflags(), ev.data(), ev.udata())]
        },
        Event::Both => vec![ev, KEvent::new(ev.ident(), EventFilter::EVFILT_WRITE, ev.flags(), ev.fflags(), ev.data(), ev.udata())]
    }
}

fn make_user_event(id: usize) -> KEvent {
    KEvent::new(
        id as uintptr_t,
        EventFilter::EVFILT_USER,
        EventFlag::EV_ADD | EventFlag::EV_CLEAR | EventFlag::EV_ENABLE,
        FilterFlag::empty(),
        0,
        id as UserData
    )
}

fn set_flags(e: &mut KEvent, flags: EventFlag) {
    let ident = e.ident();
    let filter = e.filter();
    let fflags = e.fflags();
    let udata = e.udata();
    ev_set(e, ident, filter, flags, fflags, udata);
}

fn set_fflags(e: &mut KEvent, fflags: FilterFlag) {
    let ident = e.ident();
    let filter = e.filter();
    let flags = e.flags();
    let udata = e.udata();
    ev_set(e, ident, filter, flags, fflags, udata);
}

fn make_timer(id: usize, timeout: usize, recurring: bool) -> KEvent {
    let mut flags = EventFlag::EV_ADD;
    if !recurring {
        flags |= EventFlag::EV_ONESHOT;
    }
    let ev = KEvent::new(
        id as uintptr_t,
        EventFilter::EVFILT_TIMER,
        flags,
        FilterFlag::empty(), // timeouts are in ms by default
        timeout as intptr_t,
        id as UserData
    );
    ev
}
<commit_msg>Add filter setting to kqueue<commit_after>use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::slice;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::os::unix::io::AsRawFd;
use nix::sys::event::{ev_set, kqueue, kevent, KEvent, EventFilter, EventFlag, FilterFlag};
use libc::{uintptr_t, intptr_t};
use std::io::Result;
use event::Event;
use notification::Notification;
use user_event::UserEvent;
use nix_err_to_io_err;

type UserData = intptr_t;

static KQUEUE_EVENT_SIZE: usize = 1024;

pub struct KernelPoller {
    kqueue: RawFd,
    registrar: KernelRegistrar,
    eventlist: Vec<KEvent>,
    notifications: HashMap<RawFd, Notification>
}

impl KernelPoller {
    pub fn new() -> Result<KernelPoller> {
        let kq = kqueue().map_err(nix_err_to_io_err)?;
        let registrations = Arc::new(AtomicUsize::new(1));
        Ok(KernelPoller {
            kqueue: kq,
            registrar: KernelRegistrar::new(kq, registrations),
            eventlist: Vec::with_capacity(KQUEUE_EVENT_SIZE),
            notifications: HashMap::with_capacity(KQUEUE_EVENT_SIZE)
        })
    }

    // This will always succeed. We implement it this way for api compatibility with epoll.
    pub fn get_registrar(&self) -> Result<KernelRegistrar> {
        Ok(self.registrar.clone())
    }

    // Wait for kevents and return a list of Notifications. Coalesce reads and writes for the same
    // socket into a single notification. If only a read or a write event for a given socket is
    // present in the eventlist, check the registration to see if there is another kevent registered
    //  and remove it if so. We do this removal to prevent aliasing a pointer to the same
    // registration structure.
    pub fn wait(&mut self, timeout_ms: usize) -> Result<Vec<Notification>> {

        // Create a buffer to read events into
        let dst = unsafe {
            slice::from_raw_parts_mut(self.eventlist.as_mut_ptr(), self.eventlist.capacity())
        };

        let count = kevent(self.kqueue, &[], dst, timeout_ms).map_err(nix_err_to_io_err)?;

        // Set the length of the vector to the number of events that was returned by kevent
        unsafe { self.eventlist.set_len(count); }

        self.coalesce_events();
        Ok(self.notifications.drain().map(|(_, v)| v).collect())
    }

    // Combine read and write events for the same socket into a single notification.
    fn coalesce_events(&mut self) {
        for e in self.eventlist.drain(..) {
            let event = event_from_filter(e.filter());
            let new_notification = Notification {
                id: e.udata() as usize,
                event: event.clone()
            };

            let mut notification = self.notifications.entry(e.ident() as RawFd)
                                                     .or_insert(new_notification);
            if notification.event != event {
                notification.event = Event::Both
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct KernelRegistrar {
    kqueue: RawFd,
    total_registrations: Arc<AtomicUsize>
}

impl KernelRegistrar {
    // Explicitly not public. KernelRegistrar's are tied to KernelPollers and are retreived via
    // calls to poller.get_registrar().
    fn new(kq: RawFd, registrations: Arc<AtomicUsize>) -> KernelRegistrar {
        KernelRegistrar {
            kqueue: kq,
            total_registrations: registrations
        }
    }

    // This will always succeed. We implement this to provide api compatibility with epoll.
    pub fn try_clone(&self) -> Result<KernelRegistrar> {
        Ok(self.clone())
    }

    pub fn register<T: AsRawFd>(&self, sock: &T, event: Event) -> Result<usize> {
        let sock_fd = sock.as_raw_fd();
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = make_changelist(sock_fd, event, id as UserData);
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(id)
    }

    pub fn reregister<T: AsRawFd>(&self, id: usize, sock: &T, event: Event) -> Result<()> {
        let sock_fd = sock.as_raw_fd();
        let changes = make_changelist(sock_fd, event, id as UserData);
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn deregister<T: AsRawFd>(&self, sock: &T) -> Result<()> {
        let sock_fd = sock.as_raw_fd();
        let mut changes = make_changelist(sock_fd, Event::Both, 0);
        for e in changes.iter_mut() {
            set_flags(e, EventFlag::EV_DELETE);
        }
        // Just ignore errors because, one of the events may not be present, but the deregister
        // signature ignores that fact. At this point, ownership of the socket is taken so it's
        // irrelevant anyway.
        let _ = kevent(self.kqueue, &changes, &mut[], 0);
        Ok(())
    }

    pub fn register_user_event(&mut self) -> Result<UserEvent> {
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = vec![make_user_event(id)];
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(UserEvent {id: id, registrar: self.clone()})
    }

    pub fn trigger_user_event(&self, event: &UserEvent) -> Result<()> {
        let mut e = make_user_event(event.get_id());
        set_fflags(&mut e, FilterFlag::NOTE_TRIGGER);
        kevent(self.kqueue, &vec![e], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn clear_user_event(&self, event: &UserEvent) -> Result<()> {
        let mut user_event = make_user_event(event.get_id());
        set_flags(&mut user_event, EventFlag::EV_DISABLE);
        kevent(self.kqueue, &vec![user_event], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn deregister_user_event(&self, event_id: usize) -> Result<()> {
        let mut user_event = make_user_event(event_id);
        set_flags(&mut user_event, EventFlag::EV_DELETE);
        kevent(self.kqueue, &vec![user_event], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    pub fn set_timeout(&self, timeout: usize) -> Result<usize> {
        self.set_timer(timeout, false)
    }

    pub fn set_interval(&self, timeout: usize) -> Result<usize> {
        self.set_timer(timeout, true)
    }

    pub fn cancel_timeout(&self, timer_id: usize) -> Result<()> {
        let mut e = make_timer(timer_id, 0, false);
        set_flags(&mut e, EventFlag::EV_DELETE);
        kevent(self.kqueue, &vec![e], &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(())
    }

    fn set_timer(&self, timeout: usize, recurring: bool) -> Result<usize> {
        let id = self.total_registrations.fetch_add(1, Ordering::SeqCst);
        let changes = vec![make_timer(id, timeout, recurring)];
        kevent(self.kqueue, &changes, &mut[], 0).map_err(nix_err_to_io_err)?;
        Ok(id)
    }
}

fn event_from_filter(filter: EventFilter) -> Event {
    // TODO: Change Event to allow returning TIMER events instead of marking them READ
    if filter == EventFilter::EVFILT_READ ||
       filter == EventFilter::EVFILT_TIMER ||
       filter == EventFilter::EVFILT_USER {
        Event::Read
    } else {
        Event::Write
    }
}

// Each event in kqueue must have its own filter. In other words, there are seperate events for
// reads and writes on the same socket. We create the proper number of KEvents based on the enum
// variant in the `event` paramter.
fn make_changelist(sock_fd: RawFd, event: Event, user_data: UserData) -> Vec<KEvent> {
    let mut ev = KEvent::new(
        sock_fd as uintptr_t,
        EventFilter::EVFILT_READ,
        EventFlag::EV_ADD,
        FilterFlag::empty(),
        0,
        user_data
    );

    match event {
        Event::Read => vec![ev],
        Event::Write => {
            set_filter(&mut ev, EventFilter::EVFILT_WRITE);
            vec![KEvent::new(ev.ident(), EventFilter::EVFILT_WRITE, ev.flags(), ev.fflags(), ev.data(), ev.udata())]
        },
        Event::Both => vec![ev, KEvent::new(ev.ident(), EventFilter::EVFILT_WRITE, ev.flags(), ev.fflags(), ev.data(), ev.udata())]
    }
}

fn make_user_event(id: usize) -> KEvent {
    KEvent::new(
        id as uintptr_t,
        EventFilter::EVFILT_USER,
        EventFlag::EV_ADD | EventFlag::EV_CLEAR | EventFlag::EV_ENABLE,
        FilterFlag::empty(),
        0,
        id as UserData
    )
}

fn set_filter(e: &mut KEvent, filter: EventFilter) {
    let ident = e.ident();
    let flags = e.flags();
    let fflags = e.fflags();
    let udata = e.udata();
    ev_set(e, ident, filter, flags, fflags, udata);
}

fn set_flags(e: &mut KEvent, flags: EventFlag) {
    let ident = e.ident();
    let filter = e.filter();
    let fflags = e.fflags();
    let udata = e.udata();
    ev_set(e, ident, filter, flags, fflags, udata);
}

fn set_fflags(e: &mut KEvent, fflags: FilterFlag) {
    let ident = e.ident();
    let filter = e.filter();
    let flags = e.flags();
    let udata = e.udata();
    ev_set(e, ident, filter, flags, fflags, udata);
}

fn make_timer(id: usize, timeout: usize, recurring: bool) -> KEvent {
    let mut flags = EventFlag::EV_ADD;
    if !recurring {
        flags |= EventFlag::EV_ONESHOT;
    }
    let ev = KEvent::new(
        id as uintptr_t,
        EventFilter::EVFILT_TIMER,
        flags,
        FilterFlag::empty(), // timeouts are in ms by default
        timeout as intptr_t,
        id as UserData
    );
    ev
}
<|endoftext|>


<commit_before>use num::One;
use std::default::Default;
use std::ops::Mul;

pub use linear::{Matrix4, Vector3};
pub use nalgebra::*;

pub type Translation = Vector3<f32>;
pub type Axis = Vector3<f32>;
pub type Direction = Vector3<f32>;
pub type Position = Vector3<f32>;
pub type Orientation = UnitQuaternion<f32>;

pub const X_AXIS: Axis = Axis { x: 1., y: 0., z: 0. };
pub const Y_AXIS: Axis = Axis { x: 0., y: 1., z: 0. };
pub const Z_AXIS: Axis = Axis { x: 0., y: 0., z: 1. };

pub fn translation_matrix(v: Translation) -> Matrix4<f32> {
  Matrix4::new(
    1., 0., 0., v.x,
    0., 1., 0., v.y,
    0., 0., 1., v.z,
    0., 0., 0.,  1.,
  )
}

/// Arbritrary scale.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Scale {
  pub x: f32,
  pub y: f32,
  pub z: f32
}

impl Scale {
  pub fn new(x: f32, y: f32, z: f32) -> Self {
    Scale {
      x: x,
      y: y,
      z: z
    }
  }

  pub fn uni(x: f32) -> Self {
    Scale {
      x: x,
      y: x,
      z: x
    }
  }

  pub fn to_mat(&self) -> Matrix4<f32> {
    Matrix4::new(
      self.x,     0.,     0., 0.,
          0., self.y,     0., 0.,
          0.,     0., self.z, 0.,
          0.,     0.,     0., 1.
    )
  }
}

impl Default for Scale {
  fn default() -> Self { Scale::new(1., 1., 1.) }
}

impl<'a> From<&'a [f32; 3]> for Scale {
  fn from(slice: &[f32; 3]) -> Self {
    Scale {
      x: slice[0],
      y: slice[1],
      z: slice[2]
    }
  }
}

impl<'a> From<&'a Scale> for [f32; 3] {
  fn from(scale: &Scale) -> Self {
    [scale.x, scale.y, scale.z]
  }
}

impl Mul for Scale {
  type Output = Scale;

  fn mul(self, rhs: Self) -> Self::Output {
    Scale {
      x: self.x * rhs.x,
      y: self.y * rhs.y,
      z: self.z * rhs.z
    }
  }
}

impl One for Scale {
  fn one() -> Self {
    Scale::new(1., 1., 1.)
  }
}
<commit_msg>Export One and Zero from linear.rs.<commit_after>use std::default::Default;
use std::ops::Mul;

pub use num::{One, Zero};
pub use linear::{Matrix4, Vector3};
pub use nalgebra::*;

pub type Translation = Vector3<f32>;
pub type Axis = Vector3<f32>;
pub type Direction = Vector3<f32>;
pub type Position = Vector3<f32>;
pub type Orientation = UnitQuaternion<f32>;

pub const X_AXIS: Axis = Axis { x: 1., y: 0., z: 0. };
pub const Y_AXIS: Axis = Axis { x: 0., y: 1., z: 0. };
pub const Z_AXIS: Axis = Axis { x: 0., y: 0., z: 1. };

pub fn translation_matrix(v: Translation) -> Matrix4<f32> {
  Matrix4::new(
    1., 0., 0., v.x,
    0., 1., 0., v.y,
    0., 0., 1., v.z,
    0., 0., 0.,  1.,
  )
}

/// Arbritrary scale.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Scale {
  pub x: f32,
  pub y: f32,
  pub z: f32
}

impl Scale {
  pub fn new(x: f32, y: f32, z: f32) -> Self {
    Scale {
      x: x,
      y: y,
      z: z
    }
  }

  pub fn uni(x: f32) -> Self {
    Scale {
      x: x,
      y: x,
      z: x
    }
  }

  pub fn to_mat(&self) -> Matrix4<f32> {
    Matrix4::new(
      self.x,     0.,     0., 0.,
          0., self.y,     0., 0.,
          0.,     0., self.z, 0.,
          0.,     0.,     0., 1.
    )
  }
}

impl Default for Scale {
  fn default() -> Self { Scale::new(1., 1., 1.) }
}

impl<'a> From<&'a [f32; 3]> for Scale {
  fn from(slice: &[f32; 3]) -> Self {
    Scale {
      x: slice[0],
      y: slice[1],
      z: slice[2]
    }
  }
}

impl<'a> From<&'a Scale> for [f32; 3] {
  fn from(scale: &Scale) -> Self {
    [scale.x, scale.y, scale.z]
  }
}

impl Mul for Scale {
  type Output = Scale;

  fn mul(self, rhs: Self) -> Self::Output {
    Scale {
      x: self.x * rhs.x,
      y: self.y * rhs.y,
      z: self.z * rhs.z
    }
  }
}

impl One for Scale {
  fn one() -> Self {
    Scale::new(1., 1., 1.)
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use futures::{Future, IntoFuture};
use tokio::fs::File;
use tokio_io::AsyncRead;

use std::{
    collections::HashSet,
    path::PathBuf,
    str::from_utf8,
};

use crate::{local_infile_handler::LocalInfileHandler, BoxFuture};

/// Handles local infile requests from filesystem using explicit path white list.
///
/// Example usage:
///
/// ```rust
/// use mysql_async::{OptsBuilder, WhiteListFsLocalInfileHandler};
///
/// # let database_url = "mysql://root:password@127.0.0.1:3307/mysql";
/// let mut opts = OptsBuilder::from_opts(database_url);
/// opts.local_infile_handler(Some(WhiteListFsLocalInfileHandler::new(
///     &["path/to/local_infile.txt"][..],
/// )));
/// ```
#[derive(Clone, Debug)]
pub struct WhiteListFsLocalInfileHandler {
    white_list: HashSet<PathBuf>,
}

impl WhiteListFsLocalInfileHandler {
    pub fn new<A, B>(white_list: B) -> WhiteListFsLocalInfileHandler
    where
        A: Into<PathBuf>,
        B: IntoIterator<Item = A>,
    {
        let mut white_list_set = HashSet::new();
        for path in white_list.into_iter() {
            white_list_set.insert(Into::<PathBuf>::into(path));
        }
        WhiteListFsLocalInfileHandler {
            white_list: white_list_set,
        }
    }
}

impl LocalInfileHandler for WhiteListFsLocalInfileHandler {
    fn handle(&self, file_name: &[u8]) -> BoxFuture<Box<dyn AsyncRead + Send + 'static>> {
        let path: PathBuf = match from_utf8(file_name) {
            Ok(path_str) => path_str.into(),
            Err(_) => return Box::new(Err("Invalid file name".into()).into_future()),
        };

        if !self.white_list.contains(&path) {
            let err_msg = format!("Path `{}' is not in white list", path.display());
            return Box::new(Err(err_msg.into()).into_future());
        }

        let future = File::open(path.to_owned())
            .map(|file| Box::new(file) as Box<_>)
            .map_err(|e| e.into());

        Box::new(future)
    }
}
<commit_msg>Fix formatting since #61<commit_after>// Copyright (c) 2016 Anatoly Ikorsky
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use futures::{Future, IntoFuture};
use tokio::fs::File;
use tokio_io::AsyncRead;

use std::{collections::HashSet, path::PathBuf, str::from_utf8};

use crate::{local_infile_handler::LocalInfileHandler, BoxFuture};

/// Handles local infile requests from filesystem using explicit path white list.
///
/// Example usage:
///
/// ```rust
/// use mysql_async::{OptsBuilder, WhiteListFsLocalInfileHandler};
///
/// # let database_url = "mysql://root:password@127.0.0.1:3307/mysql";
/// let mut opts = OptsBuilder::from_opts(database_url);
/// opts.local_infile_handler(Some(WhiteListFsLocalInfileHandler::new(
///     &["path/to/local_infile.txt"][..],
/// )));
/// ```
#[derive(Clone, Debug)]
pub struct WhiteListFsLocalInfileHandler {
    white_list: HashSet<PathBuf>,
}

impl WhiteListFsLocalInfileHandler {
    pub fn new<A, B>(white_list: B) -> WhiteListFsLocalInfileHandler
    where
        A: Into<PathBuf>,
        B: IntoIterator<Item = A>,
    {
        let mut white_list_set = HashSet::new();
        for path in white_list.into_iter() {
            white_list_set.insert(Into::<PathBuf>::into(path));
        }
        WhiteListFsLocalInfileHandler {
            white_list: white_list_set,
        }
    }
}

impl LocalInfileHandler for WhiteListFsLocalInfileHandler {
    fn handle(&self, file_name: &[u8]) -> BoxFuture<Box<dyn AsyncRead + Send + 'static>> {
        let path: PathBuf = match from_utf8(file_name) {
            Ok(path_str) => path_str.into(),
            Err(_) => return Box::new(Err("Invalid file name".into()).into_future()),
        };

        if !self.white_list.contains(&path) {
            let err_msg = format!("Path `{}' is not in white list", path.display());
            return Box::new(Err(err_msg.into()).into_future());
        }

        let future = File::open(path.to_owned())
            .map(|file| Box::new(file) as Box<_>)
            .map_err(|e| e.into());

        Box::new(future)
    }
}
<|endoftext|>


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

/*!
* Minimal binding for OpenAL.
* Bind only functions which are needed by lib sailor
*/

#![allow(dead_code, non_snake_case)]
#[link(name = "libsndfile-1")]
#[link(name = "openal32")]
extern {}

pub mod ffi {

    use libc::{c_char, c_void, intptr_t };

    /// OpenAL types
    pub type ALCboolean = c_char;
    pub type ALCdevicePtr = intptr_t;
    pub type ALCcontextPtr = intptr_t;
    pub const ALC_TRUE:               ALCboolean  = 1;
    pub const ALC_FALSE:              ALCboolean  = 0;

    /// Sound modifier
    pub const AL_GAIN:                i32         = 0x100A;
    pub const AL_PITCH:               i32         = 0x1003;
    pub const AL_SOURCE_RELATIVE:     i32         = 0x202;
    pub const AL_POSITION:            i32         = 0x1004;
    pub const AL_ORIENTATION:         i32         = 0x100F;
    pub const AL_DIRECTION:           i32         = 0x1005;
    pub const AL_LOOPING:             i32         = 0x1007;
    pub const AL_MIN_GAIN:            i32         = 0x100D;
    pub const AL_MAX_GAIN:            i32         = 0x100E;
    pub const AL_MAX_DISTANCE:        i32         = 0x1023;
    pub const AL_REFERENCE_DISTANCE:  i32         = 0x1020;
    pub const AL_ROLLOFF_FACTOR:      i32         = 0x1021;

    /// Sound format
    pub const AL_FORMAT_MONO16:       i32         = 0x1101;
    pub const AL_FORMAT_STEREO16:     i32         = 0x1103;
    pub const AL_FORMAT_51CHN16:      i32         = 0x120B;
    pub const AL_FORMAT_61CHN16:      i32         = 0x120E;
    pub const AL_FORMAT_71CHN16:      i32         = 0x1211;
    pub const AL_FORMAT_QUAD16:       i32         = 0x1205;

    /// Source params
    pub const AL_BUFFER:              i32         = 0x1009;
    pub const AL_BUFFERS_PROCESSED:   i32         = 0x1016;
    pub const AL_BUFFERS_QUEUED:      i32         = 0x1015;

    /// Error identifiers
    pub const AL_NO_ERROR:            i32         = 0;
    pub const AL_INVALID_NAME:        i32         = 0xA001;
    pub const AL_INVALID_ENUM:        i32         = 0xA002;
    pub const AL_INVALID_VALUE:       i32         = 0xA003;
    pub const AL_INVALID_OPERATION:   i32         = 0xA004;
    pub const AL_OUT_OF_MEMORY :      i32         = 0xA005;

    /// Source states
    pub const AL_SOURCE_STATE:        i32         = 0x1010;
    pub const AL_INITIAL:             i32         = 0x1011;
    pub const AL_PLAYING:             i32         = 0x1012;
    pub const AL_PAUSED:              i32         = 0x1013;
    pub const AL_STOPPED:             i32         = 0x1014;

    /// ALC
    pub const ALC_CAPTURE_SAMPLES :    i32         = 0x312;

    extern "C" {
        /// Context functions
        pub fn alcCreateContext(device: ALCdevicePtr, attrlist: *mut i32) -> ALCcontextPtr;
        pub fn alcMakeContextCurrent(context: ALCcontextPtr) -> ALCboolean;
        pub fn alcDestroyContext(context: ALCcontextPtr);
        pub fn alcGetCurrentContext() -> ALCcontextPtr;

        /// Device functions
        pub fn alcOpenDevice(devicename: *mut c_char) -> ALCdevicePtr;
        pub fn alcCloseDevice(device: ALCdevicePtr) -> ALCboolean;

        /// Listener functions
        pub fn alListenerf(param: i32, value: f32) -> ();
        pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> ();
        pub fn alGetListenerf(param: i32, value: *mut f32) -> ();
        pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> ();
        pub fn alListenerfv(param: i32, values: *const f32) -> ();
        pub fn alGetListenerfv(param: i32, values: *mut f32) -> ();

        /// Sources functions
        pub fn alGenSources(n: i32, sources: *mut u32) -> ();
        pub fn alDeleteSources(n: i32, buffers: *mut u32) -> ();
        pub fn alSourcei(source: u32, param: i32, value: i32) -> ();
        pub fn alSourcef(source: u32, param: i32, value: f32) -> ();
        pub fn alSourcePlay(source: u32) -> ();
        pub fn alSourcePause(source: u32) -> ();
        pub fn alSourceStop(source: u32) -> ();
        pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> ();
        pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> ();
        pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> ();
        pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> ();

        /// Sound capture functions
        pub fn alcCaptureCloseDevice(device: ALCdevicePtr) -> ALCboolean;
        pub fn alcCaptureOpenDevice(device: *mut c_char, sample_rate: i32, format: i32, buffer_size: i32) -> ALCdevicePtr;
        pub fn alcCaptureStart(devide: ALCdevicePtr);
        pub fn alcCaptureStop(devide: ALCdevicePtr);
        pub fn alcGetIntegerv(devide: ALCdevicePtr, param: i32,  size: i32, values: *mut i32);
        pub fn alcCaptureSamples(devide: ALCdevicePtr, buffer: *mut c_void,sample: i32);

        /// extension check
        pub fn alcIsExtensionPresent(device: ALCdevicePtr, extension: *const c_char) -> ALCboolean;

        /// Buffers functions
        pub fn alGenBuffers(n: i32, buffers: *mut u32) -> ();
        pub fn alDeleteBuffers(n: i32, buffers: *mut u32);
        pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> ();

        /// Error
        pub fn alGetError() -> i32;
    }

    #[repr(C)]
    pub struct ALCdevice;
    #[repr(C)]
    pub struct ALCcontext;
}

pub mod al {

    use super::ffi;
    use libc::c_void;

    pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> () {
        unsafe { ffi::alBufferData(buffer, format, data, size, freq); }
    }

    pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> () {
        unsafe { ffi::alSourceQueueBuffers(source, nb, buffers); }
    }

    pub fn alSourcePlay(source: u32) -> () {
        unsafe { ffi::alSourcePlay(source); }
    }

    pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> () {
        unsafe { ffi::alGetSourcei(source, param, value); }
    }

    pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcef(source, param, value); }
    }

    pub fn alGetState(source: u32) -> i32 {
        let mut i = 0;
        unsafe { ffi::alGetSourcei(source, ffi::AL_SOURCE_STATE, &mut i); }
        i
    }

    pub fn alSourcei(source: u32, param: i32, value: i32) -> () {
        unsafe { ffi::alSourcei(source, param, value); }
    }

    pub fn alSourcef(source: u32, param: i32, value: f32) -> () {
        unsafe { ffi::alSourcef(source, param, value); }
    }

    pub fn alSourcePause(source: u32) -> () {
        unsafe { ffi::alSourcePause(source); }
    }

    pub fn alSourceStop(source: u32) -> () {
        unsafe { ffi::alSourceStop(source); }
    }

    pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alSourceUnqueueBuffers(source, nb, buffers); }
    }

    pub fn alGenSources(n: i32, sources: *mut u32) -> () {
        unsafe {ffi::alGenSources(n, sources); }
    }

    pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> () {
        unsafe { ffi::alSourcefv(source, param, value); }
    }

    pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcefv(source, param, value); }
    }

    pub fn alGenBuffers(n: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alGenBuffers(n, buffers); }
    }

    pub fn alListenerf(param: i32, value: f32) -> () {
        unsafe { ffi::alListenerf(param, value); }
    }

    pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> () {
        unsafe { ffi::alListener3f(param, value1, value2, value3); }
    }

    pub fn alGetListenerf(param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetListenerf(param, value); }
    }

    pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> () {
        unsafe { ffi::alGetListener3f(param, value1, value2, value3); }
    }

    pub fn alListenerfv(param: i32, values: *const f32) -> () {
        unsafe { ffi::alListenerfv(param, values); }
    }

    pub fn alGetListenerfv(param: i32, values: *mut f32) -> () {
        unsafe { ffi::alGetListenerfv(param, values); }
    }

    pub fn openal_has_error() -> Option<String> {
         match unsafe { ffi::alGetError() } {
            ffi::AL_NO_ERROR          => None,
            ffi::AL_INVALID_NAME      => Some("OpenAL error : Invalid name paramater passed to AL call.".to_string()),
            ffi::AL_INVALID_ENUM      => Some("OpenAL error : Invalid enum parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_VALUE     => Some("OpenAL error : Invalid value parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_OPERATION => Some("OpenAL error : Illegal AL call.".to_string()),
            ffi::AL_OUT_OF_MEMORY     => Some("OpenAL error : Not enough memory.".to_string()),
            _                         => Some("OpenAL internal error : Unknow error.".to_string())
        }
    }

    pub fn get_channels_format(channels : i32) -> Option<i32> {
        match channels {
            1 => Some(ffi::AL_FORMAT_MONO16),
            2 => Some(ffi::AL_FORMAT_STEREO16),
            4 => Some(ffi::AL_FORMAT_QUAD16),
            5 => Some(ffi::AL_FORMAT_51CHN16),
            6 => Some(ffi::AL_FORMAT_61CHN16),
            7 => Some(ffi::AL_FORMAT_71CHN16),
            _ => return None
        }
    }
}
<commit_msg>Link against openal instead of openal32 on Linux<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
* Minimal binding for OpenAL.
* Bind only functions which are needed by lib sailor
*/

#![allow(dead_code, non_snake_case)]

#[cfg(target_os = "linux")]
#[link(name = "openal")]
extern {}

#[cfg(not(target_os = "linux"))]
#[link(name = "openal32")]
extern {}

pub mod ffi {

    use libc::{c_char, c_void, intptr_t };

    /// OpenAL types
    pub type ALCboolean = c_char;
    pub type ALCdevicePtr = intptr_t;
    pub type ALCcontextPtr = intptr_t;
    pub const ALC_TRUE:               ALCboolean  = 1;
    pub const ALC_FALSE:              ALCboolean  = 0;

    /// Sound modifier
    pub const AL_GAIN:                i32         = 0x100A;
    pub const AL_PITCH:               i32         = 0x1003;
    pub const AL_SOURCE_RELATIVE:     i32         = 0x202;
    pub const AL_POSITION:            i32         = 0x1004;
    pub const AL_ORIENTATION:         i32         = 0x100F;
    pub const AL_DIRECTION:           i32         = 0x1005;
    pub const AL_LOOPING:             i32         = 0x1007;
    pub const AL_MIN_GAIN:            i32         = 0x100D;
    pub const AL_MAX_GAIN:            i32         = 0x100E;
    pub const AL_MAX_DISTANCE:        i32         = 0x1023;
    pub const AL_REFERENCE_DISTANCE:  i32         = 0x1020;
    pub const AL_ROLLOFF_FACTOR:      i32         = 0x1021;

    /// Sound format
    pub const AL_FORMAT_MONO16:       i32         = 0x1101;
    pub const AL_FORMAT_STEREO16:     i32         = 0x1103;
    pub const AL_FORMAT_51CHN16:      i32         = 0x120B;
    pub const AL_FORMAT_61CHN16:      i32         = 0x120E;
    pub const AL_FORMAT_71CHN16:      i32         = 0x1211;
    pub const AL_FORMAT_QUAD16:       i32         = 0x1205;

    /// Source params
    pub const AL_BUFFER:              i32         = 0x1009;
    pub const AL_BUFFERS_PROCESSED:   i32         = 0x1016;
    pub const AL_BUFFERS_QUEUED:      i32         = 0x1015;

    /// Error identifiers
    pub const AL_NO_ERROR:            i32         = 0;
    pub const AL_INVALID_NAME:        i32         = 0xA001;
    pub const AL_INVALID_ENUM:        i32         = 0xA002;
    pub const AL_INVALID_VALUE:       i32         = 0xA003;
    pub const AL_INVALID_OPERATION:   i32         = 0xA004;
    pub const AL_OUT_OF_MEMORY :      i32         = 0xA005;

    /// Source states
    pub const AL_SOURCE_STATE:        i32         = 0x1010;
    pub const AL_INITIAL:             i32         = 0x1011;
    pub const AL_PLAYING:             i32         = 0x1012;
    pub const AL_PAUSED:              i32         = 0x1013;
    pub const AL_STOPPED:             i32         = 0x1014;

    /// ALC
    pub const ALC_CAPTURE_SAMPLES :    i32         = 0x312;

    extern "C" {
        /// Context functions
        pub fn alcCreateContext(device: ALCdevicePtr, attrlist: *mut i32) -> ALCcontextPtr;
        pub fn alcMakeContextCurrent(context: ALCcontextPtr) -> ALCboolean;
        pub fn alcDestroyContext(context: ALCcontextPtr);
        pub fn alcGetCurrentContext() -> ALCcontextPtr;

        /// Device functions
        pub fn alcOpenDevice(devicename: *mut c_char) -> ALCdevicePtr;
        pub fn alcCloseDevice(device: ALCdevicePtr) -> ALCboolean;

        /// Listener functions
        pub fn alListenerf(param: i32, value: f32) -> ();
        pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> ();
        pub fn alGetListenerf(param: i32, value: *mut f32) -> ();
        pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> ();
        pub fn alListenerfv(param: i32, values: *const f32) -> ();
        pub fn alGetListenerfv(param: i32, values: *mut f32) -> ();

        /// Sources functions
        pub fn alGenSources(n: i32, sources: *mut u32) -> ();
        pub fn alDeleteSources(n: i32, buffers: *mut u32) -> ();
        pub fn alSourcei(source: u32, param: i32, value: i32) -> ();
        pub fn alSourcef(source: u32, param: i32, value: f32) -> ();
        pub fn alSourcePlay(source: u32) -> ();
        pub fn alSourcePause(source: u32) -> ();
        pub fn alSourceStop(source: u32) -> ();
        pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> ();
        pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> ();
        pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> ();
        pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> ();
        pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> ();

        /// Sound capture functions
        pub fn alcCaptureCloseDevice(device: ALCdevicePtr) -> ALCboolean;
        pub fn alcCaptureOpenDevice(device: *mut c_char, sample_rate: i32, format: i32, buffer_size: i32) -> ALCdevicePtr;
        pub fn alcCaptureStart(devide: ALCdevicePtr);
        pub fn alcCaptureStop(devide: ALCdevicePtr);
        pub fn alcGetIntegerv(devide: ALCdevicePtr, param: i32,  size: i32, values: *mut i32);
        pub fn alcCaptureSamples(devide: ALCdevicePtr, buffer: *mut c_void,sample: i32);

        /// extension check
        pub fn alcIsExtensionPresent(device: ALCdevicePtr, extension: *const c_char) -> ALCboolean;

        /// Buffers functions
        pub fn alGenBuffers(n: i32, buffers: *mut u32) -> ();
        pub fn alDeleteBuffers(n: i32, buffers: *mut u32);
        pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> ();

        /// Error
        pub fn alGetError() -> i32;
    }

    #[repr(C)]
    pub struct ALCdevice;
    #[repr(C)]
    pub struct ALCcontext;
}

pub mod al {

    use super::ffi;
    use libc::c_void;

    pub fn alBufferData(buffer: u32, format: i32, data: *mut c_void, size: i32, freq: i32) -> () {
        unsafe { ffi::alBufferData(buffer, format, data, size, freq); }
    }

    pub fn alSourceQueueBuffers(source: u32, nb: i32, buffers: *const u32) -> () {
        unsafe { ffi::alSourceQueueBuffers(source, nb, buffers); }
    }

    pub fn alSourcePlay(source: u32) -> () {
        unsafe { ffi::alSourcePlay(source); }
    }

    pub fn alGetSourcei(source: u32, param: i32, value: *mut i32) -> () {
        unsafe { ffi::alGetSourcei(source, param, value); }
    }

    pub fn alGetSourcef(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcef(source, param, value); }
    }

    pub fn alGetState(source: u32) -> i32 {
        let mut i = 0;
        unsafe { ffi::alGetSourcei(source, ffi::AL_SOURCE_STATE, &mut i); }
        i
    }

    pub fn alSourcei(source: u32, param: i32, value: i32) -> () {
        unsafe { ffi::alSourcei(source, param, value); }
    }

    pub fn alSourcef(source: u32, param: i32, value: f32) -> () {
        unsafe { ffi::alSourcef(source, param, value); }
    }

    pub fn alSourcePause(source: u32) -> () {
        unsafe { ffi::alSourcePause(source); }
    }

    pub fn alSourceStop(source: u32) -> () {
        unsafe { ffi::alSourceStop(source); }
    }

    pub fn alSourceUnqueueBuffers(source: u32, nb: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alSourceUnqueueBuffers(source, nb, buffers); }
    }

    pub fn alGenSources(n: i32, sources: *mut u32) -> () {
        unsafe {ffi::alGenSources(n, sources); }
    }

    pub fn alSourcefv(source: u32, param: i32, value: *const f32) -> () {
        unsafe { ffi::alSourcefv(source, param, value); }
    }

    pub fn alGetSourcefv(source: u32, param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetSourcefv(source, param, value); }
    }

    pub fn alGenBuffers(n: i32, buffers: *mut u32) -> () {
        unsafe { ffi::alGenBuffers(n, buffers); }
    }

    pub fn alListenerf(param: i32, value: f32) -> () {
        unsafe { ffi::alListenerf(param, value); }
    }

    pub fn alListener3f(param: i32, value1: f32, value2: f32, value3: f32) -> () {
        unsafe { ffi::alListener3f(param, value1, value2, value3); }
    }

    pub fn alGetListenerf(param: i32, value: *mut f32) -> () {
        unsafe { ffi::alGetListenerf(param, value); }
    }

    pub fn alGetListener3f(param: f32, value1: *mut f32, value2: *mut f32, value3: *mut f32) -> () {
        unsafe { ffi::alGetListener3f(param, value1, value2, value3); }
    }

    pub fn alListenerfv(param: i32, values: *const f32) -> () {
        unsafe { ffi::alListenerfv(param, values); }
    }

    pub fn alGetListenerfv(param: i32, values: *mut f32) -> () {
        unsafe { ffi::alGetListenerfv(param, values); }
    }

    pub fn openal_has_error() -> Option<String> {
         match unsafe { ffi::alGetError() } {
            ffi::AL_NO_ERROR          => None,
            ffi::AL_INVALID_NAME      => Some("OpenAL error : Invalid name paramater passed to AL call.".to_string()),
            ffi::AL_INVALID_ENUM      => Some("OpenAL error : Invalid enum parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_VALUE     => Some("OpenAL error : Invalid value parameter passed to AL call.".to_string()),
            ffi::AL_INVALID_OPERATION => Some("OpenAL error : Illegal AL call.".to_string()),
            ffi::AL_OUT_OF_MEMORY     => Some("OpenAL error : Not enough memory.".to_string()),
            _                         => Some("OpenAL internal error : Unknow error.".to_string())
        }
    }

    pub fn get_channels_format(channels : i32) -> Option<i32> {
        match channels {
            1 => Some(ffi::AL_FORMAT_MONO16),
            2 => Some(ffi::AL_FORMAT_STEREO16),
            4 => Some(ffi::AL_FORMAT_QUAD16),
            5 => Some(ffi::AL_FORMAT_51CHN16),
            6 => Some(ffi::AL_FORMAT_61CHN16),
            7 => Some(ffi::AL_FORMAT_71CHN16),
            _ => return None
        }
    }
}
<|endoftext|>