<commit_before>#![feature(test)]
#![allow(match_ref_pats)]
#![allow(too_many_arguments)]
#![allow(unknown_lints)]

#[macro_use] extern crate nom;
#[macro_use] extern crate lazy_static;

extern crate regex;
extern crate colored;

pub mod test;
pub mod types;
pub mod error;
pub mod cli_helpers;
pub mod gitignore;

pub mod prelude {

    use std::fs;
    use std::path::PathBuf;
    use regex::{Regex, RegexSet};
    use types::*;
    use colored::*;
    use gitignore::*;
    use std::io::prelude::*;
    use std::process::exit;
    use std::fs::{Metadata, File};

    #[cfg(not(target_os = "windows"))]
    use std::os::unix::fs::PermissionsExt;

    pub use cli_helpers::*;
    pub use error::*;

    /// Helper function to determine whether a path points
    ///
    /// Rules:
    /// - if the file extension of that is that of an artifact, return true
    /// - if the file is executable and included in the .gitignore, return true
    /// - if the file looks like a configuration file and is in the .gitignore, return true
    /// (\.cache.*, \.conf
    /// - return false otherwise
    ///
    /// # Examples
    ///
    /// ```
    /// use libsniff::prelude::*;
    /// use std::path::PathBuf;
    ///
    /// let path_buf: PathBuf = PathBuf::from("lib.so");
    /// assert_eq!(is_artifact(&path_buf, None), true);
    /// ```
    #[cfg(not(target_os = "windows"))]
    pub fn is_artifact(p: &PathBuf, re: Option<&Regex>, metadata: &Metadata, gitignore: &Option<RegexSet>) -> bool {

        // get path as a string so we can match against it
        let path_str = p.clone().into_os_string().into_string().expect("OS string invalid.");

        // match on the user's expression if it exists
        if let Some(r) = re {
            r.is_match(&path_str)
        }

        // otherwise, use builtin expressions
        else {
            lazy_static! {
                static ref REGEX: Regex =
                    Regex::new(r".*?\.(a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc)$")
                    .unwrap();
            }
            lazy_static! {
                static ref REGEX_GITIGNORE: Regex =
                    Regex::new(r".*?\.(stats|conf|h|cache.*|dat|pc|info)$")
                    .unwrap();
            }
            if REGEX.is_match(&path_str) { true }
            else if let &Some(ref x) = gitignore {
                if metadata.permissions().mode() == 0o755 || REGEX_GITIGNORE.is_match(&path_str)
                    { x.is_match(&path_str) }
                else { false }
            }
            else { false }
        }
    }

    #[cfg(target_os = "windows")]
    pub fn is_artifact(p: &PathBuf, re: Option<&Regex>, _: &Metadata, gitignore:&Option<RegexSet>) -> bool {
        let path_str = p.clone().into_os_string().into_string().expect("OS String invalid.");
        if let Some(r) = re {
            r.is_match(&path_str)
        }
        else {
            lazy_static! {
                static ref REGEX: Regex =
                    Regex::new(r".*?\.(exe|a|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|js_o|so.*|dump-.*|vmb|crx)$")
                    .unwrap();
            }
            lazy_static! {
                static ref REGEX_GITIGNORE: Regex =
                    Regex::new(r".*?\.(stats|conf|h|cache.*)$")
                    .unwrap();
            }
            if REGEX.is_match(&path_str) { true }

            else if let &Some(ref x) = gitignore {
                if REGEX_GITIGNORE.is_match(&path_str) {
                    if x.is_match(&path_str) { true } else { false }
                } else { false }
            }
            else { false }
        }
    }

    // how depth/recursion SHOULD work for artifacts: if e.g. .stack-work/ has *multiple* subdirs
    // with artifacts, then list it in place of all of them. Basically find "root nodes" of these
    // places - hard but potentially very nice? look in .gitignore?
    /// Function to process directory contents and return a `FileTree` struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use libsniff::prelude::*;
    /// use std::path::PathBuf;
    ///
    /// let path = PathBuf::from("src");
    /// let file_tree = read_all(&path, 2, None, None, None, false, true);
    /// ```
    pub fn read_all(in_paths: &PathBuf,
                          depth: u8,
                          min_bytes: Option<u64>,
                          artifact_regex: Option<&Regex>,
                          excludes: Option<&Regex>,
                          silent: bool,
                          maybe_gitignore: &Option<RegexSet>,
                          artifacts_only: bool) -> FileTree {

        // attempt to read the .gitignore
        let mut tree = FileTree::new();
        let min_size = min_bytes.map(FileSize::new);
        let gitignore = if let &Some(ref gitignore) = maybe_gitignore { Some(gitignore.to_owned()) }
            else {
                let mut gitignore_path = in_paths.clone();
                gitignore_path.push(".gitignore");
                if let Ok(mut file) = File::open(gitignore_path) {
                    let mut contents = String::new();
                    file.read_to_string(&mut contents)
                        .expect("File read failed. Is your system configured to use unix?");
                    Some(file_contents_to_regex(&contents))
                } else { None }
            };

        // try to read directory contents
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let path = p.unwrap().path(); // TODO no unwraps; idk what this error would be though.
                let path_string = path.clone().into_os_string().into_string().expect("OS String invalid."); // TODO nicer error message, mention windows/utf-8?
                let bool_loop = match excludes {
                    Some(ex) => !ex.is_match(&path_string),
                    _ => true,
                };

                // only consider path if we're not using regex excludes or if they don't match the
                // exclusion regex
                if bool_loop {

                    // if this fails, it's probably because `path` is a broken symlink
                    if let Ok(metadata) = fs::metadata(&path) {

                        // append file size/name for a file
                        if metadata.is_file() {
                            if !artifacts_only || is_artifact(&path, artifact_regex, &metadata, &gitignore) {
                                let file_size = FileSize::new(metadata.len());
                                if let Some(b) = min_bytes {
                                    if file_size >= FileSize::new(b) {
                                            tree.push(path_string, file_size, None, depth + 1, min_size);
                                        }
                                    }
                                else {
                                    tree.push(path_string, file_size, None, depth + 1, min_size);
                                }
                            }
                        }

                        // otherwise, go deeper

                        else if metadata.is_dir() {
                            let mut subtree = read_all(&path, depth + 1, min_bytes, artifact_regex, excludes, silent, &gitignore, artifacts_only);
                            let dir_size = subtree.file_size;
                            if let Some(b) = min_bytes {
                                if dir_size >= FileSize::new(b) {
                                    tree.push(path_string, dir_size, Some(&mut subtree), depth + 1, min_size);
                                }
                            }
                            else { tree.push(path_string, dir_size, Some(&mut subtree), depth + 1, min_size); }
                        }
                    }
                    else if !silent { eprintln!("{}: ignoring symlink at {}", "Warning".yellow(), path.display()); }
                }
            }
        }

        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!("{}: path '{}' does not exist.", "Error".red(), &in_paths.display()); // FIXME check it is a directory too
            exit(0x0001);
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            eprintln!("{}: {} is not a directory.", "Error".red(), &in_paths.display());
            exit(0x0001);
        }
        // 3: otherwise, give a warning about permissions
        else if !silent {
            eprintln!("{}: permission denied for directory: {}", "Warning".yellow(), &in_paths.display());
        }

        tree
    }
}
<commit_msg>removed clone<commit_after>#![feature(test)]
#![allow(match_ref_pats)]
#![allow(too_many_arguments)]
#![allow(unknown_lints)]

#[macro_use] extern crate nom;
#[macro_use] extern crate lazy_static;

extern crate regex;
extern crate colored;

pub mod test;
pub mod types;
pub mod error;
pub mod cli_helpers;
pub mod gitignore;

pub mod prelude {

    use std::fs;
    use std::path::PathBuf;
    use regex::{Regex, RegexSet};
    use types::*;
    use colored::*;
    use gitignore::*;
    use std::io::prelude::*;
    use std::process::exit;
    use std::fs::{Metadata, File};

    #[cfg(not(target_os = "windows"))]
    use std::os::unix::fs::PermissionsExt;

    pub use cli_helpers::*;
    pub use error::*;

    /// Helper function to determine whether a path points
    ///
    /// Rules:
    /// - if the file extension of that is that of an artifact, return true
    /// - if the file is executable and included in the .gitignore, return true
    /// - if the file looks like a configuration file and is in the .gitignore, return true
    /// (\.cache.*, \.conf
    /// - return false otherwise
    ///
    /// # Examples
    ///
    /// ```
    /// use libsniff::prelude::*;
    /// use std::path::PathBuf;
    ///
    /// let path_buf: PathBuf = PathBuf::from("lib.so");
    /// assert_eq!(is_artifact(&path_buf, None), true);
    /// ```
    #[cfg(not(target_os = "windows"))]
    pub fn is_artifact(path_str: &str, re: Option<&Regex>, metadata: &Metadata, gitignore: &Option<RegexSet>) -> bool {

        // match on the user's expression if it exists
        if let Some(r) = re {
            r.is_match(&path_str)
        }

        // otherwise, use builtin expressions
        else {
            lazy_static! {
                static ref REGEX: Regex =
                    Regex::new(r".*?\.(a|la|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc)$")
                    .unwrap();
            }
            lazy_static! {
                static ref REGEX_GITIGNORE: Regex =
                    Regex::new(r".*?\.(stats|conf|h|cache.*|dat|pc|info)$")
                    .unwrap();
            }
            if REGEX.is_match(&path_str) { true }
            else if let &Some(ref x) = gitignore {
                if metadata.permissions().mode() == 0o755 || REGEX_GITIGNORE.is_match(&path_str)
                    { x.is_match(&path_str) }
                else { false }
            }
            else { false }
        }
    }

    #[cfg(target_os = "windows")]
    pub fn is_artifact(path_str: &str, re: Option<&Regex>, _: &Metadata, gitignore:&Option<RegexSet>) -> bool {
        if let Some(r) = re {
            r.is_match(&path_str)
        }
        else {
            lazy_static! {
                static ref REGEX: Regex =
                    Regex::new(r".*?\.(exe|a|o|ll|keter|bc|dyn_o|out|d|rlib|crate|min\.js|hi|dyn_hi|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|js_o|so.*|dump-.*|vmb|crx)$")
                    .unwrap();
            }
            lazy_static! {
                static ref REGEX_GITIGNORE: Regex =
                    Regex::new(r".*?\.(stats|conf|h|cache.*)$")
                    .unwrap();
            }
            if REGEX.is_match(&path_str) { true }

            else if let &Some(ref x) = gitignore {
                if REGEX_GITIGNORE.is_match(&path_str) {
                    if x.is_match(&path_str) { true } else { false }
                } else { false }
            }
            else { false }
        }
    }

    // how depth/recursion SHOULD work for artifacts: if e.g. .stack-work/ has *multiple* subdirs
    // with artifacts, then list it in place of all of them. Basically find "root nodes" of these
    // places - hard but potentially very nice? look in .gitignore?
    /// Function to process directory contents and return a `FileTree` struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use libsniff::prelude::*;
    /// use std::path::PathBuf;
    ///
    /// let path = PathBuf::from("src");
    /// let file_tree = read_all(&path, 2, None, None, None, false, true);
    /// ```
    pub fn read_all(in_paths: &PathBuf,
                          depth: u8,
                          min_bytes: Option<u64>,
                          artifact_regex: Option<&Regex>,
                          excludes: Option<&Regex>,
                          silent: bool,
                          maybe_gitignore: &Option<RegexSet>,
                          artifacts_only: bool) -> FileTree {

        // attempt to read the .gitignore
        let mut tree = FileTree::new();
        let min_size = min_bytes.map(FileSize::new);
        let gitignore = if let &Some(ref gitignore) = maybe_gitignore { Some(gitignore.to_owned()) }
            else {
                let mut gitignore_path = in_paths.clone();
                gitignore_path.push(".gitignore");
                if let Ok(mut file) = File::open(gitignore_path) {
                    let mut contents = String::new();
                    file.read_to_string(&mut contents)
                        .expect("File read failed. Is your system configured to use unix?");
                    Some(file_contents_to_regex(&contents))
                } else { None }
            };

        // try to read directory contents
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let path = p.unwrap().path(); // TODO no unwraps; idk what this error would be though.
                let path_string = path.clone().into_os_string().into_string() // why does it do a clone here??
                    .expect("OS String invalid."); // TODO nicer error message, mention windows/utf-8?
                let bool_loop = match excludes {
                    Some(ex) => !ex.is_match(&path_string),
                    _ => true,
                };

                // only consider path if we're not using regex excludes or if they don't match the
                // exclusion regex
                if bool_loop {

                    // if this fails, it's probably because `path` is a broken symlink
                    if let Ok(metadata) = fs::metadata(&path) {

                        // append file size/name for a file
                        if metadata.is_file() {
                            if !artifacts_only || is_artifact(&path_string, artifact_regex, &metadata, &gitignore) {
                                let file_size = FileSize::new(metadata.len());
                                if let Some(b) = min_bytes {
                                    if file_size >= FileSize::new(b) {
                                            tree.push(path_string, file_size, None, depth + 1, min_size);
                                        }
                                    }
                                else {
                                    tree.push(path_string, file_size, None, depth + 1, min_size);
                                }
                            }
                        }

                        // otherwise, go deeper

                        else if metadata.is_dir() {
                            let mut subtree = read_all(&path, depth + 1, min_bytes, artifact_regex, excludes, silent, &gitignore, artifacts_only);
                            let dir_size = subtree.file_size;
                            if let Some(b) = min_bytes {
                                if dir_size >= FileSize::new(b) {
                                    tree.push(path_string, dir_size, Some(&mut subtree), depth + 1, min_size);
                                }
                            }
                            else { tree.push(path_string, dir_size, Some(&mut subtree), depth + 1, min_size); }
                        }
                    }
                    else if !silent { eprintln!("{}: ignoring symlink at {}", "Warning".yellow(), path.display()); }
                }
            }
        }

        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!("{}: path '{}' does not exist.", "Error".red(), &in_paths.display()); // FIXME check it is a directory too
            exit(0x0001);
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            eprintln!("{}: {} is not a directory.", "Error".red(), &in_paths.display());
            exit(0x0001);
        }
        // 3: otherwise, give a warning about permissions
        else if !silent {
            eprintln!("{}: permission denied for directory: {}", "Warning".yellow(), &in_paths.display());
        }

        tree
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
extern crate libc;

use std::ffi::CStr;
use std::{ptr, mem};

pub type ChromaprintContext = *mut ::libc::c_void;
pub type ChromaprintAlgorithm = ::libc::c_int;
pub const CHROMAPRINT_ALGORITHM_TEST1: ChromaprintAlgorithm = 0;
pub const CHROMAPRINT_ALGORITHM_TEST2: ChromaprintAlgorithm = 1;
pub const CHROMAPRINT_ALGORITHM_TEST3: ChromaprintAlgorithm = 2;
pub const CHROMAPRINT_ALGORITHM_TEST4: ChromaprintAlgorithm = 3;
pub const CHROMAPRINT_ALGORITHM_DEFAULT: ChromaprintAlgorithm  = CHROMAPRINT_ALGORITHM_TEST2;
#[link(name = "chromaprint")]
extern "C" {
    pub fn chromaprint_get_version() -> *const ::libc::c_char;
    pub fn chromaprint_new(algorithm: ChromaprintAlgorithm)
     -> *mut ChromaprintContext;
    pub fn chromaprint_free(ctx: *mut ChromaprintContext) -> ();
    pub fn chromaprint_get_algorithm(ctx: *mut ChromaprintContext)
     -> ChromaprintAlgorithm;
    pub fn chromaprint_set_option(ctx: *mut ChromaprintContext,
                                  name: *const ::libc::c_char,
                                  value: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_start(ctx: *mut ChromaprintContext,
                             sample_rate: ::libc::c_int,
                             num_channels: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_feed(ctx: *mut ChromaprintContext,
                            data: *const ::libc::c_void, size: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_finish(ctx: *mut ChromaprintContext) -> ::libc::c_int;
    pub fn chromaprint_get_fingerprint(ctx: *mut ChromaprintContext,
                                       fingerprint: *mut *mut ::libc::c_char)
     -> ::libc::c_int;
    pub fn chromaprint_get_raw_fingerprint(ctx: *mut ChromaprintContext,
                                           fingerprint:
                                               *mut *mut ::libc::c_void,
                                           size: *mut ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_encode_fingerprint(fp: *const ::libc::c_void,
                                          size: ::libc::c_int,
                                          algorithm: ::libc::c_int,
                                          encoded_fp:
                                              *mut *mut ::libc::c_void,
                                          encoded_size: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_decode_fingerprint(encoded_fp: *const ::libc::c_void,
                                          encoded_size: ::libc::c_int,
                                          fp: *mut *mut ::libc::c_void,
                                          size: *mut ::libc::c_int,
                                          algorithm: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_dealloc(ptr: *mut ::libc::c_void) -> ();
}

pub struct Chromaprint {
    ctx: *mut ChromaprintContext,
}

impl Chromaprint {
    pub fn new() -> Chromaprint {
        unsafe {
            Chromaprint {
                ctx:  chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT),
            }
        }
    }

    pub fn version() -> String {
        String::from_utf8(unsafe { CStr::from_ptr(chromaprint_get_version()).to_bytes().to_vec() }).unwrap()
    }

    pub fn algorithm(&self) -> ChromaprintAlgorithm {
        unsafe { chromaprint_get_algorithm(self.ctx) }
    }

    pub fn start(&mut self, sample_rate: ::libc::c_int, num_channels: ::libc::c_int) -> bool {
        unsafe { chromaprint_start(self.ctx, sample_rate, num_channels) == 1 }
    }

    pub fn feed(&mut self, data: &[u8]) -> bool {
        unsafe { chromaprint_feed(self.ctx, data.as_ptr() as *const ::libc::c_void, data.len() as ::libc::c_int) == 1 }
    }

    pub fn finish(&mut self) -> bool {
        unsafe { chromaprint_finish(self.ctx) == 1 }
    }

    pub fn fingerprint(&mut self) -> Option<String> {
        let mut fingerprint: *mut ::libc::c_char = ptr::null_mut();
        if unsafe { chromaprint_get_fingerprint(self.ctx, &mut fingerprint) } == 1 {
            let ret = String::from_utf8(unsafe { CStr::from_ptr(fingerprint) }.to_bytes().to_vec()).ok();
            unsafe { chromaprint_dealloc(fingerprint as *mut ::libc::c_void) }
            return ret;
        }
        None
    }

    pub fn raw_fingerprint(&mut self) -> Option<Vec<::libc::c_int>> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        if unsafe { chromaprint_get_raw_fingerprint(self.ctx, mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array), &mut size) } == 1 {
            let fingerprint = unsafe { Vec::from_raw_buf(array, size as usize) };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(fingerprint);
        }
        None
    }

    pub fn encode(raw_fingerprint: &[::libc::c_int], algorithm: ChromaprintAlgorithm, base64: bool) -> Option<Vec<u8>> {
        let mut array: *mut u8 = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let result = unsafe {
            chromaprint_encode_fingerprint(raw_fingerprint.as_ptr() as *const ::libc::c_void,
                                           raw_fingerprint.len() as ::libc::c_int, algorithm,
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array),
                                           &mut size, base64 as ::libc::c_int)
        };
        if result == 1 {
            let encoded = unsafe { Vec::from_raw_buf(array, size as usize) };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(encoded);
        }
        None
    }

    pub fn decode(encoded_fingerprint: &[u8], base64: bool) -> Option<(Vec<::libc::c_int>, ChromaprintAlgorithm)> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let mut algorithm: ChromaprintAlgorithm = -1;
        let result = unsafe {
            chromaprint_decode_fingerprint(encoded_fingerprint.as_ptr() as *const ::libc::c_void,
                                           encoded_fingerprint.len() as ::libc::c_int,
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array),
                                           &mut size, &mut algorithm, base64 as ::libc::c_int)
        };
        if result == 1 {
            let decoded = unsafe { Vec::from_raw_buf(array, size as usize) };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some((decoded, algorithm));
        }
        None
    }
}

impl Drop for Chromaprint {
    fn drop(&mut self) {
        unsafe { chromaprint_free(self.ctx); }
    }
}
<commit_msg>Changed Vec::from_raw_buf to slice::from_raw_parts<commit_after>extern crate libc;

use std::ffi::CStr;
use std::{ptr, mem, slice};

pub type ChromaprintContext = *mut ::libc::c_void;
pub type ChromaprintAlgorithm = ::libc::c_int;
pub const CHROMAPRINT_ALGORITHM_TEST1: ChromaprintAlgorithm = 0;
pub const CHROMAPRINT_ALGORITHM_TEST2: ChromaprintAlgorithm = 1;
pub const CHROMAPRINT_ALGORITHM_TEST3: ChromaprintAlgorithm = 2;
pub const CHROMAPRINT_ALGORITHM_TEST4: ChromaprintAlgorithm = 3;
pub const CHROMAPRINT_ALGORITHM_DEFAULT: ChromaprintAlgorithm  = CHROMAPRINT_ALGORITHM_TEST2;
#[link(name = "chromaprint")]
extern "C" {
    pub fn chromaprint_get_version() -> *const ::libc::c_char;
    pub fn chromaprint_new(algorithm: ChromaprintAlgorithm)
     -> *mut ChromaprintContext;
    pub fn chromaprint_free(ctx: *mut ChromaprintContext) -> ();
    pub fn chromaprint_get_algorithm(ctx: *mut ChromaprintContext)
     -> ChromaprintAlgorithm;
    pub fn chromaprint_set_option(ctx: *mut ChromaprintContext,
                                  name: *const ::libc::c_char,
                                  value: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_start(ctx: *mut ChromaprintContext,
                             sample_rate: ::libc::c_int,
                             num_channels: ::libc::c_int) -> ::libc::c_int;
    pub fn chromaprint_feed(ctx: *mut ChromaprintContext,
                            data: *const ::libc::c_void, size: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_finish(ctx: *mut ChromaprintContext) -> ::libc::c_int;
    pub fn chromaprint_get_fingerprint(ctx: *mut ChromaprintContext,
                                       fingerprint: *mut *mut ::libc::c_char)
     -> ::libc::c_int;
    pub fn chromaprint_get_raw_fingerprint(ctx: *mut ChromaprintContext,
                                           fingerprint:
                                               *mut *mut ::libc::c_void,
                                           size: *mut ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_encode_fingerprint(fp: *const ::libc::c_void,
                                          size: ::libc::c_int,
                                          algorithm: ::libc::c_int,
                                          encoded_fp:
                                              *mut *mut ::libc::c_void,
                                          encoded_size: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_decode_fingerprint(encoded_fp: *const ::libc::c_void,
                                          encoded_size: ::libc::c_int,
                                          fp: *mut *mut ::libc::c_void,
                                          size: *mut ::libc::c_int,
                                          algorithm: *mut ::libc::c_int,
                                          base64: ::libc::c_int)
     -> ::libc::c_int;
    pub fn chromaprint_dealloc(ptr: *mut ::libc::c_void) -> ();
}

pub struct Chromaprint {
    ctx: *mut ChromaprintContext,
}

impl Chromaprint {
    pub fn new() -> Chromaprint {
        unsafe {
            Chromaprint {
                ctx:  chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT),
            }
        }
    }

    pub fn version() -> String {
        String::from_utf8(unsafe { CStr::from_ptr(chromaprint_get_version()).to_bytes().to_vec() }).unwrap()
    }

    pub fn algorithm(&self) -> ChromaprintAlgorithm {
        unsafe { chromaprint_get_algorithm(self.ctx) }
    }

    pub fn start(&mut self, sample_rate: ::libc::c_int, num_channels: ::libc::c_int) -> bool {
        unsafe { chromaprint_start(self.ctx, sample_rate, num_channels) == 1 }
    }

    pub fn feed(&mut self, data: &[u8]) -> bool {
        unsafe { chromaprint_feed(self.ctx, data.as_ptr() as *const ::libc::c_void, data.len() as ::libc::c_int) == 1 }
    }

    pub fn finish(&mut self) -> bool {
        unsafe { chromaprint_finish(self.ctx) == 1 }
    }

    pub fn fingerprint(&mut self) -> Option<String> {
        let mut fingerprint: *mut ::libc::c_char = ptr::null_mut();
        if unsafe { chromaprint_get_fingerprint(self.ctx, &mut fingerprint) } == 1 {
            let ret = String::from_utf8(unsafe { CStr::from_ptr(fingerprint) }.to_bytes().to_vec()).ok();
            unsafe { chromaprint_dealloc(fingerprint as *mut ::libc::c_void) }
            return ret;
        }
        None
    }

    pub fn raw_fingerprint(&mut self) -> Option<Vec<::libc::c_int>> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        if unsafe { chromaprint_get_raw_fingerprint(self.ctx, mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array), &mut size) } == 1 {
            let fingerprint = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(fingerprint);
        }
        None
    }

    pub fn encode(raw_fingerprint: &[::libc::c_int], algorithm: ChromaprintAlgorithm, base64: bool) -> Option<Vec<u8>> {
        let mut array: *mut u8 = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let result = unsafe {
            chromaprint_encode_fingerprint(raw_fingerprint.as_ptr() as *const ::libc::c_void,
                                           raw_fingerprint.len() as ::libc::c_int, algorithm,
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array),
                                           &mut size, base64 as ::libc::c_int)
        };
        if result == 1 {
            let encoded = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some(encoded);
        }
        None
    }

    pub fn decode(encoded_fingerprint: &[u8], base64: bool) -> Option<(Vec<::libc::c_int>, ChromaprintAlgorithm)> {
        let mut array: *mut ::libc::c_int = ptr::null_mut();
        let mut size: ::libc::c_int = 0;
        let mut algorithm: ChromaprintAlgorithm = -1;
        let result = unsafe {
            chromaprint_decode_fingerprint(encoded_fingerprint.as_ptr() as *const ::libc::c_void,
                                           encoded_fingerprint.len() as ::libc::c_int,
                                           mem::transmute::<_, *mut *mut ::libc::c_void>(&mut array),
                                           &mut size, &mut algorithm, base64 as ::libc::c_int)
        };
        if result == 1 {
            let decoded = unsafe { slice::from_raw_parts(array, size as usize).to_vec() };
            unsafe { chromaprint_dealloc(array as *mut ::libc::c_void) }
            return Some((decoded, algorithm));
        }
        None
    }
}

impl Drop for Chromaprint {
    fn drop(&mut self) {
        unsafe { chromaprint_free(self.ctx); }
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use chrono::NaiveDate;

use error::Result;
use habit::HabitTemplate;

/// An instance of a habit is created for each time a habit is done.
///
/// # Note
///
/// A habit is a daily thing, so we only provide "date" as granularity for its time data.
///
pub trait HabitInstance {
    /// Check whether the instance is a habit instance by checking its headers for the habit
    /// data
    fn is_habit_instance(&self) -> Result<bool>;

    fn get_date(&self) -> Result<NaiveDate>;
    fn set_date(&self, n: NaiveDate) -> Result<()>;
    fn get_comment(&self) -> Result<String>;
    fn set_comment(&self, c: String) -> Result<()>;
    fn get_template_name(&self) -> Result<String>;
}

<commit_msg>Implement HabitInstance for Entry<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use chrono::NaiveDate;
use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::set::TomlValueSetExt;

use error::HabitError as HE;
use error::HabitErrorKind as HEK;
use error::*;
use habit::HabitTemplate;
use util::*;

use libimagstore::store::Entry;

/// An instance of a habit is created for each time a habit is done.
///
/// # Note
///
/// A habit is a daily thing, so we only provide "date" as granularity for its time data.
///
pub trait HabitInstance {
    /// Check whether the instance is a habit instance by checking its headers for the habit
    /// data
    fn is_habit_instance(&self) -> Result<bool>;

    fn get_date(&self) -> Result<NaiveDate>;
    fn set_date(&mut self, n: &NaiveDate) -> Result<()>;
    fn get_comment(&self) -> Result<String>;
    fn set_comment(&mut self, c: String) -> Result<()>;
    fn get_template_name(&self) -> Result<String>;
}

impl HabitInstance for Entry {
    fn is_habit_instance(&self) -> Result<bool> {
        [
            "habit.instance.name",
            "habit.instance.date",
            "habit.instance.comment",
        ].iter().fold(Ok(true), |acc, path| acc.and_then(|b| {
            self.get_header()
                .read(path)
                .map(|o| is_match!(o, Some(&Value::String(_))))
                .map_err(From::from)
        }))
    }

    fn get_date(&self) -> Result<NaiveDate> {
        match self.get_header().read("habit.instance.date")? {
            Some(&Value::String(ref s)) => date_from_string(s),
            Some(_) => Err(HEK::HeaderTypeError("habit.instance.date", "String").into()),
            None    => Err(HEK::HeaderFieldMissing("habit.instance.date").into()),
        }
    }

    fn set_date(&mut self, n: &NaiveDate) -> Result<()> {
        // Using `set` here because when creating the entry, these headers should be made present.
        self.get_header_mut()
            .set("habit.instance.date", Value::String(date_to_string(n)))
            .map_err(From::from)
            .map(|_| ())
    }

    fn get_comment(&self) -> Result<String> {
        match self.get_header().read("habit.instance.comment")? {
            Some(&Value::String(ref s)) => Ok(s.clone()),
            Some(_) => Err(HEK::HeaderTypeError("habit.instance.comment", "String").into()),
            None    => Err(HEK::HeaderFieldMissing("habit.instance.comment").into()),
        }
    }

    fn set_comment(&mut self, c: String) -> Result<()> {
        // Using `set` here because when creating the entry, these headers should be made present.
        self.get_header_mut()
            .set("habit.instance.comment", Value::String(c))
            .map_err(From::from)
            .map(|_| ())
    }

    fn get_template_name(&self) -> Result<String> {
        match self.get_header().read("habit.instance.name")? {
            Some(&Value::String(ref s)) => Ok(s.clone()),
            Some(_) => Err(HEK::HeaderTypeError("habit.instance.name", "String").into()),
            None    => Err(HEK::HeaderFieldMissing("habit.instance.name").into()),
        }
    }

}
<|endoftext|>


<commit_before>//! Collections for use with GC references.

use traits::{IntoHeap, IntoHeapAllocation};
use gcref::GCRef;
use heap::HeapId;
use std::marker::PhantomData;
use std::mem;
use std::cmp::Ordering;

/// An implementation detail.
pub struct VecStorage<'a, T: IntoHeap<'a>>(Vec<T::In>, HeapId<'a>);

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for Vec<T> {
    type In = VecStorage<'a, T>;

    fn into_heap(self) -> VecStorage<'a, T> {
        VecStorage(self.into_iter().map(|x| x.into_heap()).collect(), PhantomData)
    }

    unsafe fn from_heap(storage: &VecStorage<'a, T>) -> Vec<T> {
        storage.0.iter().map(|x| T::from_heap(x)).collect()
    }

    unsafe fn mark(storage: &VecStorage<'a, T>) {
        for r in &storage.0 {
            T::mark(r);
        }
    }
}

impl<'a, T: IntoHeap<'a>> IntoHeapAllocation<'a> for Vec<T> {
    type Ref = VecRef<'a, T>;

    fn wrap_gcref(gcref: GCRef<'a, Vec<T>>) -> VecRef<'a, T> {
        VecRef(gcref)
    }
}

/// A reference to a GC-heap-allocated `Vec`.
///
/// To allocate a vector in the heap, simply call `heap.alloc` on a plain old `Vec`.
/// It will return a `VecRef` object which has many of the familiar `Vec` methods,
/// as well as element accessors `get_at` and `set_at`.
///
/// ```rust
/// use cell_gc::collections::VecRef;
///
/// cell_gc::with_heap(|heap| {
///     let r: VecRef<i32> = heap.alloc(vec![20, 10, 40, 30]);
///     assert_eq!(r.len(), 4);
///     assert_eq!(r.get(0), 20);
///     r.push(100);
///     r.sort();
///     assert_eq!(r.get_all(), vec![10, 20, 30, 40, 100]);
/// });
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VecRef<'a, T: IntoHeap<'a>>(GCRef<'a, Vec<T>>);

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for VecRef<'a, T> {
    type In = *mut VecStorage<'a, T>;

    fn into_heap(self) -> *mut VecStorage<'a, T> {
        self.0.as_mut_ptr()
    }

    unsafe fn from_heap(storage: &*mut VecStorage<'a, T>) -> VecRef<'a, T> {
        VecRef(GCRef::new(*storage))
    }

    unsafe fn mark(storage: &*mut VecStorage<'a, T>) {
        // BUG - should call a method mark_ref that checks the mark bit before
        // doing anything
        for r in &(**storage).0 {
            T::mark(r);
        }
    }
}

impl<'a, T: IntoHeap<'a>> VecRef<'a, T> {
    // BUG: this should not let the borrow escape the closure.
    /// Unsafe to call: During the lifetime of the reference passed to the
    /// callback, the caller must ensure that the vector is not modified.
    /// Destructors and `from_heap` methods are presumed safe. Avoid
    /// `to_heap`.
    fn unsafe_deref<'b, R, F>(&'b self, f: F) -> R
        where F: FnOnce(&'b Vec<T::In>) -> R
    {
        // NOTE: the signature above is overly restrictive.
        // I should be able to figure out a better one when I have a little time.
        // TODO: in debug builds at least there should be a RefCell-like "lock" here,
        // asserting that no direct Rust references exist to anything in the GC heap.
        f(unsafe { &(*self.0.as_ptr()).0 })
    }

    /// Unsafe to call: During the lifetime of the reference passed to the
    /// callback, the caller must ensure that no other references exist to the
    /// vector.  Destructors and `from_heap` methods are presumed safe. Avoid
    /// `to_heap`.
    fn unsafe_deref_mut<'b, R, F>(&'b self, f: F) -> R
        where F: FnOnce(&'b mut Vec<T::In>) -> R
    {
        // TODO should assert here, like unsafe_deref
        f(unsafe { &mut (*self.0.as_mut_ptr()).0 })
    }

    /// Get the element `index` from the vector.
    ///
    /// This clones the element, so `VecRef<LargeStruct>::get()` would be slow.
    /// `VecRef<LargeStructRef>::get()` only clones a reference, so it is
    /// relatively quick.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn get(&self, index: usize) -> T {
        self.unsafe_deref(|v| unsafe { IntoHeap::from_heap(&v[index]) })
    }

    /// Copy the vector out of the GC-managed heap. This returns an ordinary,
    /// non-GC-managed Rust `Vec`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cell_gc::collections::VecRef;
    /// # cell_gc::with_heap(|heap| {
    /// let gc_vec: VecRef<i32> = heap.alloc(vec![]);
    /// for i in 0 .. 4 {
    ///     gc_vec.push(i);
    /// }
    /// let plain_vec = gc_vec.get_all();
    /// assert_eq!(plain_vec, vec![0, 1, 2, 3]);
    /// # });
    /// ```
    pub fn get_all(&self) -> Vec<T> {
        unsafe { IntoHeap::from_heap(&*self.0.as_ptr()) }
    }

    /// Set element `index` of the vector to `value`.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn set(&self, index: usize, value: T) {
        let u = value.into_heap();
        self.unsafe_deref_mut(|v| v[index] = u);
    }

    pub fn capacity(&self) -> usize {
        self.unsafe_deref(|v| v.capacity())
    }

    pub fn reserve(&self, additional: usize) {
        self.unsafe_deref_mut(|v| v.reserve(additional));
    }

    pub fn reserve_exact(&self, additional: usize) {
        self.unsafe_deref_mut(|v| v.reserve_exact(additional));
    }

    pub fn shrink_to_fit(&self) {
        self.unsafe_deref_mut(|v| v.shrink_to_fit());
    }

    pub fn truncate(&self, len: usize) {
        self.unsafe_deref_mut(|v| v.truncate(len));
    }

    pub fn swap_remove(&self, index: usize) -> T {
        let u = self.unsafe_deref_mut(|v| v.swap_remove(index));
        unsafe { IntoHeap::from_heap(&u) }
    }

    pub fn insert(&self, index: usize, element: T) {
        let u = element.into_heap();
        self.unsafe_deref_mut(|v| v.insert(index, u));
    }

    pub fn remove(&self, index: usize) -> T {
        let u = self.unsafe_deref_mut(|v| v.remove(index));
        unsafe { IntoHeap::from_heap(&u) }
    }

    pub fn push(&self, value: T) {
        let u = value.into_heap();
        self.unsafe_deref_mut(|v| v.push(u));
    }

    pub fn pop(&self) -> Option<T> {
        self.unsafe_deref_mut(|v| v.pop().map(|u| unsafe { IntoHeap::from_heap(&u) }))
    }

    pub fn append(&self, other: &VecRef<'a, T>) {
        let mut tmp: Vec<T::In> = vec![];
        other.unsafe_deref_mut(|src| mem::swap(src, &mut tmp));
        self.unsafe_deref_mut(|dest| dest.append(&mut tmp));
    }

    pub fn clear(&self) {
        self.unsafe_deref_mut(|v| v.clear());
    }

    pub fn len(&self) -> usize {
        self.unsafe_deref(|v| v.len())
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get the first element of the vector, or `None` if the vector is empty.
    ///
    /// The standard `Vec<T>::first` returns an `&T` reference into the vector,
    /// but cell-gc never hands out Rust references to heap values. Instead
    /// this returns a clone of the value.
    pub fn first(&self) -> Option<T> {
        self.unsafe_deref(|v| v.first().map(|u| unsafe { IntoHeap::from_heap(u) }))
    }

    /// Get the last element of the vector, or `None` if the vector is empty.
    ///
    /// Like `first()`, this clones the value.
    pub fn last(&self) -> Option<T> {
        self.unsafe_deref(|v| v.last().map(|u| unsafe { IntoHeap::from_heap(u) }))
    }

    /// Sort the vector in place.
    pub fn sort(&self) where T: Ord {
        self.sort_by(Ord::cmp);
    }

    pub fn sort_by<F>(&self, mut compare: F) where F: FnMut(&T, &T) -> Ordering {
        // Make the heap vector empty while we're sorting it.  This way, the
        // user can do whatever malicious nonsense they like to the heap in
        // `compare`, and our copy of the vector is unaffected.
        let mut tmp = vec![];
        self.unsafe_deref_mut(|v| mem::swap(&mut tmp, v));
        tmp.sort_by(|ru1, ru2| {
            let t1 = unsafe { IntoHeap::from_heap(ru1) };
            let t2 = unsafe { IntoHeap::from_heap(ru2) };
            compare(&t1, &t2)
        });
        self.unsafe_deref_mut(|v| mem::swap(&mut tmp, v));
    }
}
<commit_msg>Don't let a borrow survive the end of a call to `VecRef::unsafe_deref`.<commit_after>//! Collections for use with GC references.

use traits::{IntoHeap, IntoHeapAllocation};
use gcref::GCRef;
use heap::HeapId;
use std::marker::PhantomData;
use std::mem;
use std::cmp::Ordering;

/// An implementation detail.
pub struct VecStorage<'a, T: IntoHeap<'a>>(Vec<T::In>, HeapId<'a>);

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for Vec<T> {
    type In = VecStorage<'a, T>;

    fn into_heap(self) -> VecStorage<'a, T> {
        VecStorage(self.into_iter().map(|x| x.into_heap()).collect(), PhantomData)
    }

    unsafe fn from_heap(storage: &VecStorage<'a, T>) -> Vec<T> {
        storage.0.iter().map(|x| T::from_heap(x)).collect()
    }

    unsafe fn mark(storage: &VecStorage<'a, T>) {
        for r in &storage.0 {
            T::mark(r);
        }
    }
}

impl<'a, T: IntoHeap<'a>> IntoHeapAllocation<'a> for Vec<T> {
    type Ref = VecRef<'a, T>;

    fn wrap_gcref(gcref: GCRef<'a, Vec<T>>) -> VecRef<'a, T> {
        VecRef(gcref)
    }
}

/// A reference to a GC-heap-allocated `Vec`.
///
/// To allocate a vector in the heap, simply call `heap.alloc` on a plain old `Vec`.
/// It will return a `VecRef` object which has many of the familiar `Vec` methods,
/// as well as element accessors `get_at` and `set_at`.
///
/// ```rust
/// use cell_gc::collections::VecRef;
///
/// cell_gc::with_heap(|heap| {
///     let r: VecRef<i32> = heap.alloc(vec![20, 10, 40, 30]);
///     assert_eq!(r.len(), 4);
///     assert_eq!(r.get(0), 20);
///     r.push(100);
///     r.sort();
///     assert_eq!(r.get_all(), vec![10, 20, 30, 40, 100]);
/// });
/// ```
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VecRef<'a, T: IntoHeap<'a>>(GCRef<'a, Vec<T>>);

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for VecRef<'a, T> {
    type In = *mut VecStorage<'a, T>;

    fn into_heap(self) -> *mut VecStorage<'a, T> {
        self.0.as_mut_ptr()
    }

    unsafe fn from_heap(storage: &*mut VecStorage<'a, T>) -> VecRef<'a, T> {
        VecRef(GCRef::new(*storage))
    }

    unsafe fn mark(storage: &*mut VecStorage<'a, T>) {
        // BUG - should call a method mark_ref that checks the mark bit before
        // doing anything
        for r in &(**storage).0 {
            T::mark(r);
        }
    }
}

impl<'a, T: IntoHeap<'a>> VecRef<'a, T> {
    /// Unsafe to call: During the lifetime of the reference passed to the
    /// callback, the caller must ensure that the vector is not modified.
    /// Destructors and `from_heap` methods are presumed safe. Avoid
    /// `to_heap`.
    fn unsafe_deref<R, F>(&self, f: F) -> R
        where F: for <'b> FnOnce(&'b Vec<T::In>) -> R
    {
        // NOTE: the signature above is overly restrictive.
        // I should be able to figure out a better one when I have a little time.
        // TODO: in debug builds at least there should be a RefCell-like "lock" here,
        // asserting that no direct Rust references exist to anything in the GC heap.
        f(unsafe { &(*self.0.as_ptr()).0 })
    }

    /// Unsafe to call: During the lifetime of the reference passed to the
    /// callback, the caller must ensure that no other references exist to the
    /// vector.  Destructors and `from_heap` methods are presumed safe. Avoid
    /// `to_heap`.
    fn unsafe_deref_mut<R, F>(&self, f: F) -> R
        where F: for <'b> FnOnce(&'b mut Vec<T::In>) -> R
    {
        // TODO should assert here, like unsafe_deref
        f(unsafe { &mut (*self.0.as_mut_ptr()).0 })
    }

    /// Get the element `index` from the vector.
    ///
    /// This clones the element, so `VecRef<LargeStruct>::get()` would be slow.
    /// `VecRef<LargeStructRef>::get()` only clones a reference, so it is
    /// relatively quick.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn get(&self, index: usize) -> T {
        self.unsafe_deref(|v| unsafe { IntoHeap::from_heap(&v[index]) })
    }

    /// Copy the vector out of the GC-managed heap. This returns an ordinary,
    /// non-GC-managed Rust `Vec`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cell_gc::collections::VecRef;
    /// # cell_gc::with_heap(|heap| {
    /// let gc_vec: VecRef<i32> = heap.alloc(vec![]);
    /// for i in 0 .. 4 {
    ///     gc_vec.push(i);
    /// }
    /// let plain_vec = gc_vec.get_all();
    /// assert_eq!(plain_vec, vec![0, 1, 2, 3]);
    /// # });
    /// ```
    pub fn get_all(&self) -> Vec<T> {
        unsafe { IntoHeap::from_heap(&*self.0.as_ptr()) }
    }

    /// Set element `index` of the vector to `value`.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn set(&self, index: usize, value: T) {
        let u = value.into_heap();
        self.unsafe_deref_mut(|v| v[index] = u);
    }

    pub fn capacity(&self) -> usize {
        self.unsafe_deref(|v| v.capacity())
    }

    pub fn reserve(&self, additional: usize) {
        self.unsafe_deref_mut(|v| v.reserve(additional));
    }

    pub fn reserve_exact(&self, additional: usize) {
        self.unsafe_deref_mut(|v| v.reserve_exact(additional));
    }

    pub fn shrink_to_fit(&self) {
        self.unsafe_deref_mut(|v| v.shrink_to_fit());
    }

    pub fn truncate(&self, len: usize) {
        self.unsafe_deref_mut(|v| v.truncate(len));
    }

    pub fn swap_remove(&self, index: usize) -> T {
        let u = self.unsafe_deref_mut(|v| v.swap_remove(index));
        unsafe { IntoHeap::from_heap(&u) }
    }

    pub fn insert(&self, index: usize, element: T) {
        let u = element.into_heap();
        self.unsafe_deref_mut(|v| v.insert(index, u));
    }

    pub fn remove(&self, index: usize) -> T {
        let u = self.unsafe_deref_mut(|v| v.remove(index));
        unsafe { IntoHeap::from_heap(&u) }
    }

    pub fn push(&self, value: T) {
        let u = value.into_heap();
        self.unsafe_deref_mut(|v| v.push(u));
    }

    pub fn pop(&self) -> Option<T> {
        self.unsafe_deref_mut(|v| v.pop().map(|u| unsafe { IntoHeap::from_heap(&u) }))
    }

    pub fn append(&self, other: &VecRef<'a, T>) {
        let mut tmp: Vec<T::In> = vec![];
        other.unsafe_deref_mut(|src| mem::swap(src, &mut tmp));
        self.unsafe_deref_mut(|dest| dest.append(&mut tmp));
    }

    pub fn clear(&self) {
        self.unsafe_deref_mut(|v| v.clear());
    }

    pub fn len(&self) -> usize {
        self.unsafe_deref(|v| v.len())
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get the first element of the vector, or `None` if the vector is empty.
    ///
    /// The standard `Vec<T>::first` returns an `&T` reference into the vector,
    /// but cell-gc never hands out Rust references to heap values. Instead
    /// this returns a clone of the value.
    pub fn first(&self) -> Option<T> {
        self.unsafe_deref(|v| v.first().map(|u| unsafe { IntoHeap::from_heap(u) }))
    }

    /// Get the last element of the vector, or `None` if the vector is empty.
    ///
    /// Like `first()`, this clones the value.
    pub fn last(&self) -> Option<T> {
        self.unsafe_deref(|v| v.last().map(|u| unsafe { IntoHeap::from_heap(u) }))
    }

    /// Sort the vector in place.
    pub fn sort(&self) where T: Ord {
        self.sort_by(Ord::cmp);
    }

    pub fn sort_by<F>(&self, mut compare: F) where F: FnMut(&T, &T) -> Ordering {
        // Make the heap vector empty while we're sorting it.  This way, the
        // user can do whatever malicious nonsense they like to the heap in
        // `compare`, and our copy of the vector is unaffected.
        let mut tmp = vec![];
        self.unsafe_deref_mut(|v| mem::swap(&mut tmp, v));
        tmp.sort_by(|ru1, ru2| {
            let t1 = unsafe { IntoHeap::from_heap(ru1) };
            let t2 = unsafe { IntoHeap::from_heap(ru2) };
            compare(&t1, &t2)
        });
        self.unsafe_deref_mut(|v| mem::swap(&mut tmp, v));
    }
}
<|endoftext|>


<commit_before>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promises".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(futures_api)]

#![no_std]

#![deny(missing_docs, missing_debug_implementations)]
#![deny(bare_trait_objects)]

#![doc(html_root_url = "https://docs.rs/futures-preview/0.3.0-alpha")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(feature = "nightly", feature(use_extern_macros))]

#[doc(hidden)] pub use futures_core::core_reexport;

#[macro_use]
mod macros;

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! # #![feature(pin, arbitrary_self_types, futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //!   [`spawn`](crate::executor::spawn) function or [pulling the executor
    //!   from the task context](crate::task::Context::executor).
    //! - Spawn onto a specific executor by calling its
    //!   [`spawn_obj`](crate::executor::Executor::spawn_obj) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalExecutor::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalExecutor, LocalPool,
        Spawn, SpawnWithHandle,
        ThreadPool, ThreadPoolBuilder, JoinHandle,
        block_on, block_on_stream, enter, spawn, spawn_with_handle
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`result`](crate::future::result), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        FutureOption, Future, TryFuture, ReadyFuture, ready,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };
    pub use futures_util::future::{
        Empty, Flatten, FlattenStream, Fuse, Inspect, IntoStream, Lazy,
        Then, PollFn, Map, FutureExt, empty, lazy, poll_fn,
        // AndThen, ErrInto, Join, Join3, Join4, Join5, LoopFn,
        // MapErr, OrElse, Select, Loop, loop_fn, Either
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind
        // JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        // join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::future::{Future, CoreFutureExt, TryFuture};
    pub use futures_core::stream::{Stream, TryStream};
    pub use futures_core::task::{self, Poll};

    pub use futures_sink::Sink;

    #[cfg(feature = "std")]
    pub use futures_io::{
        AsyncRead,
        AsyncWrite,
    };

    pub use futures_util::{
        FutureExt,
        TryFutureExt,
        StreamExt,
        TryStreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{Stream, TryStream};

    pub use futures_util::stream::{
        Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold, ForEach, Fuse,
        Inspect, Map, Once, Peekable, PollFn, Repeat, Select, Skip, SkipWhile,
        StreamFuture, Take, TakeWhile, Then, Unfold, Zip, StreamExt, empty,
        once, poll_fn, repeat, unfold, iter,
        Forward,
    };

    pub use futures_util::try_stream::{
        TryCollect,
        // AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        CatchUnwind, Chunks, Collect,
        BufferUnordered, Buffered,
        FuturesUnordered, FuturesOrdered,
        futures_unordered, futures_ordered,
        // , select_all,
        // ReuniteError, SelectAll, SplitSink,
        // SplitStream,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](crate::task::Context), which provides contextual data
    //!   present for every task, including a handle for waking up the task.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](crate::executor). However, you can manually construct a task
    //! by creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Context, Executor, Waker, LocalWaker, UnsafeWake,
        SpawnErrorKind, SpawnObjError, SpawnLocalObjError,
    };

    #[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
    pub use futures_core::task::AtomicWaker;

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        local_waker, local_waker_from_nonlocal,
        Wake,
    };
}
<commit_msg>`result()` is now called `ready()`<commit_after>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promises".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(futures_api)]

#![no_std]

#![deny(missing_docs, missing_debug_implementations)]
#![deny(bare_trait_objects)]

#![doc(html_root_url = "https://docs.rs/futures-preview/0.3.0-alpha")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
#![cfg_attr(feature = "nightly", feature(use_extern_macros))]

#[doc(hidden)] pub use futures_core::core_reexport;

#[macro_use]
mod macros;

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! # #![feature(pin, arbitrary_self_types, futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assumping `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! There are two ways to spawn a task:
    //!
    //! - Spawn onto a "default" execuctor by calling the top-level
    //!   [`spawn`](crate::executor::spawn) function or [pulling the executor
    //!   from the task context](crate::task::Context::executor).
    //! - Spawn onto a specific executor by calling its
    //!   [`spawn_obj`](crate::executor::Executor::spawn_obj) method directly.
    //!
    //! Every task always has an associated default executor, which is usually
    //! the executor on which the task is running.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! execute non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalExecutor::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalExecutor, LocalPool,
        Spawn, SpawnWithHandle,
        ThreadPool, ThreadPoolBuilder, JoinHandle,
        block_on, block_on_stream, enter, spawn, spawn_with_handle
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`ready`](crate::future::ready), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        FutureOption, Future, TryFuture, ReadyFuture, ready,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };
    pub use futures_util::future::{
        Empty, Flatten, FlattenStream, Fuse, Inspect, IntoStream, Lazy,
        Then, PollFn, Map, FutureExt, empty, lazy, poll_fn,
        // AndThen, ErrInto, Join, Join3, Join4, Join5, LoopFn,
        // MapErr, OrElse, Select, Loop, loop_fn, Either
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        CatchUnwind
        // JoinAll, SelectAll, SelectOk, Shared, SharedError, SharedItem,
        // join_all, select_all, select_ok
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use futures_core::future::{Future, CoreFutureExt, TryFuture};
    pub use futures_core::stream::{Stream, TryStream};
    pub use futures_core::task::{self, Poll};

    pub use futures_sink::Sink;

    #[cfg(feature = "std")]
    pub use futures_io::{
        AsyncRead,
        AsyncWrite,
    };

    pub use futures_util::{
        FutureExt,
        TryFutureExt,
        StreamExt,
        TryStreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{Stream, TryStream};

    pub use futures_util::stream::{
        Chain, Concat, Empty, Filter, FilterMap, Flatten, Fold, ForEach, Fuse,
        Inspect, Map, Once, Peekable, PollFn, Repeat, Select, Skip, SkipWhile,
        StreamFuture, Take, TakeWhile, Then, Unfold, Zip, StreamExt, empty,
        once, poll_fn, repeat, unfold, iter,
        Forward,
    };

    pub use futures_util::try_stream::{
        TryCollect,
        // AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        CatchUnwind, Chunks, Collect,
        BufferUnordered, Buffered,
        FuturesUnordered, FuturesOrdered,
        futures_unordered, futures_ordered,
        // , select_all,
        // ReuniteError, SelectAll, SplitSink,
        // SplitStream,
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Context`](crate::task::Context), which provides contextual data
    //!   present for every task, including a handle for waking up the task.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! Tasks themselves are generally created by spawning a future onto [an
    //! executor](crate::executor). However, you can manually construct a task
    //! by creating your own `Context` instance, and polling a future with it.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Context, Executor, Waker, LocalWaker, UnsafeWake,
        SpawnErrorKind, SpawnObjError, SpawnLocalObjError,
    };

    #[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
    pub use futures_core::task::AtomicWaker;

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        local_waker, local_waker_from_nonlocal,
        Wake,
    };
}
<|endoftext|>


<commit_before>//! Zero-cost Futures in Rust
//!
//! This library is an implementation of futures in Rust which aims to provide
//! a robust implementation of handling asynchronous computations, ergonomic
//! composition and usage, and zero-cost abstractions over what would otherwise
//! be written by hand.
//!
//! Futures are a concept for an object which is a proxy for another value that
//! may not be ready yet. For example issuing an HTTP request may return a
//! future for the HTTP response, as it probably hasn't arrived yet. With an
//! object representing a value that will eventually be available, futures allow
//! for powerful composition of tasks through basic combinators that can perform
//! operations like chaining computations, changing the types of futures, or
//! waiting for two futures to complete at the same time.
//!
//! You can find extensive tutorials and documentations at [https://tokio.rs]
//! for both this crate (asynchronous programming in general) as well as the
//! Tokio stack to perform async I/O with.
//!
//! [https://tokio.rs]: https://tokio.rs
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! futures = "0.1"
//! ```
//!
//! ## Examples
//!
//! Let's take a look at a few examples of how futures might be used:
//!
//! ```
//! extern crate futures;
//!
//! use std::io;
//! use std::time::Duration;
//! use futures::prelude::*;
//! use futures::future::Map;
//!
//! // A future is actually a trait implementation, so we can generically take a
//! // future of any integer and return back a future that will resolve to that
//! // value plus 10 more.
//! //
//! // Note here that like iterators, we're returning the `Map` combinator in
//! // the futures crate, not a boxed abstraction. This is a zero-cost
//! // construction of a future.
//! fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
//!     where F: Future<Item=i32>,
//! {
//!     fn add(a: i32) -> i32 { a + 10 }
//!     future.map(add)
//! }
//!
//! // Not only can we modify one future, but we can even compose them together!
//! // Here we have a function which takes two futures as input, and returns a
//! // future that will calculate the sum of their two values.
//! //
//! // Above we saw a direct return value of the `Map` combinator, but
//! // performance isn't always critical and sometimes it's more ergonomic to
//! // return a trait object like we do here. Note though that there's only one
//! // allocation here, not any for the intermediate futures.
//! fn add<'a, A, B>(a: A, b: B) -> Box<Future<Item=i32, Error=A::Error> + 'a>
//!     where A: Future<Item=i32> + 'a,
//!           B: Future<Item=i32, Error=A::Error> + 'a,
//! {
//!     Box::new(a.join(b).map(|(a, b)| a + b))
//! }
//!
//! // Futures also allow chaining computations together, starting another after
//! // the previous finishes. Here we wait for the first computation to finish,
//! // and then decide what to do depending on the result.
//! fn download_timeout(url: &str,
//!                     timeout_dur: Duration)
//!                     -> Box<Future<Item=Vec<u8>, Error=io::Error>> {
//!     use std::io;
//!     use std::net::{SocketAddr, TcpStream};
//!
//!     type IoFuture<T> = Box<Future<Item=T, Error=io::Error>>;
//!
//!     // First thing to do is we need to resolve our URL to an address. This
//!     // will likely perform a DNS lookup which may take some time.
//!     let addr = resolve(url);
//!
//!     // After we acquire the address, we next want to open up a TCP
//!     // connection.
//!     let tcp = addr.and_then(|addr| connect(&addr));
//!
//!     // After the TCP connection is established and ready to go, we're off to
//!     // the races!
//!     let data = tcp.and_then(|conn| download(conn));
//!
//!     // That all might take awhile, though, so let's not wait too long for it
//!     // to all come back. The `select` combinator here returns a future which
//!     // resolves to the first value that's ready plus the next future.
//!     //
//!     // Note we can also use the `then` combinator which is similar to
//!     // `and_then` above except that it receives the result of the
//!     // computation, not just the successful value.
//!     //
//!     // Again note that all the above calls to `and_then` and the below calls
//!     // to `map` and such require no allocations. We only ever allocate once
//!     // we hit the `Box::new()` call at the end here, which means we've built
//!     // up a relatively involved computation with only one box, and even that
//!     // was optional!
//!
//!     let data = data.map(Ok);
//!     let timeout = timeout(timeout_dur).map(Err);
//!
//!     let ret = data.select(timeout).then(|result| {
//!         match result {
//!             Ok(result) => {
//!                 let (data, _other_future) = result.split();
//!                 match data {
//!                     // One future succeeded, and it was the one which was
//!                     // downloading data from the connection.
//!                     Ok(data) => Ok(data),
//!
//!                     // The timeout fired, and otherwise no error was found, so
//!                     // we translate this to an error.
//!                     Err(_timeout) => {
//!                         Err(io::Error::new(io::ErrorKind::Other, "timeout"))
//!                     }
//!                 }
//!             }
//!
//!             // A normal I/O error happened, so we pass that on through.
//!             Err(err) => Err(err.split().0),
//!         }
//!     });
//!     return Box::new(ret);
//!
//!     fn resolve(url: &str) -> IoFuture<SocketAddr> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn connect(hostname: &SocketAddr) -> IoFuture<TcpStream> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn download(stream: TcpStream) -> IoFuture<Vec<u8>> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn timeout(stream: Duration) -> IoFuture<()> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//! }
//! # fn main() {}
//! ```
//!
//! Some more information can also be found in the [README] for now, but
//! otherwise feel free to jump in to the docs below!
//!
//! [README]: https://github.com/alexcrichton/futures-rs#futures-rs

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2")]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

// TODO: task_local macro

pub use futures_core::{Async, Poll};

#[cfg(feature = "std")]
pub mod channel {
    //! Channels
    //!
    //! This module contains channels for asynchronous
    //! communication.
    pub use futures_channel::*;
}

pub mod executor {
    //! Executors
    //!
    //! This module contains the `Executor` trait, which allows futures to be
    //! spawned and executed asynchronously.

    pub use futures_executor::*;
    pub use futures_core::executor::*;
}

pub mod future {
    //! Futures
    //!
    //! This module contains the `Future` trait and adapters for this trait.

    pub use futures_core::future::*;
    pub use futures_util::future::*;
}

#[cfg(feature = "std")]
pub mod io {
    //! IO
    //!
    //! This module contains the `AsyncRead` and `AsyncWrite` traits, as well
    //! as a number of combinators and extensions for using them.
    pub use futures_io::*;
    pub use futures_util::io::*;
}

pub mod prelude {
	//! A "prelude" for crates using the `futures` crate.
	//!
	//! This prelude is similar to the standard library's prelude in that you'll
	//! almost always want to import its entire contents, but unlike the standard
	//! library's prelude you'll have to do so manually. An example of using this is:
	//!
	//! ```
	//! use futures::prelude::*;
	//! ```
	//!
	//! We may add items to this over time as they become ubiquitous as well, but
	//! otherwise this should help cut down on futures-related imports when you're
	//! working with the `futures` crate!

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        task,
    };

    pub use futures_sink::Sink;

    pub use futures_util::{
		FutureExt,
		StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncRead,
        AsyncWrite,
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
	//! Asynchronous sinks
	//!
	//! This module contains the `Sink` trait, along with a number of adapter types
	//! for it. An overview is available in the documentation for the trait itself.
	//!
	//! You can find more information/tutorials about streams [online at
	//! https://tokio.rs][online]
	//!
	//! [online]: https://tokio.rs/docs/getting-started/streams-and-sinks/

    pub use futures_sink::*;
    pub use futures_util::sink::*;
}

pub mod stream {
	//! Asynchronous streams
	//!
	//! This module contains the `Stream` trait and a number of adaptors for this
	//! trait. This trait is very similar to the `Iterator` trait in the standard
	//! library except that it expresses the concept of blocking as well. A stream
	//! here is a sequential sequence of values which may take some amount of time
	//! in between to produce.
	//!
	//! A stream may request that it is blocked between values while the next value
	//! is calculated, and provides a way to get notified once the next value is
	//! ready as well.
	//!
	//! You can find more information/tutorials about streams [online at
	//! https://tokio.rs][online]
	//!
	//! [online]: https://tokio.rs/docs/getting-started/streams-and-sinks/

    pub use futures_core::stream::*;
    pub use futures_util::stream::*;
}

pub mod task {
    //! Task executon
    pub use futures_core::task::*;
}
<commit_msg>Reexport "never" module from futures<commit_after>//! Zero-cost Futures in Rust
//!
//! This library is an implementation of futures in Rust which aims to provide
//! a robust implementation of handling asynchronous computations, ergonomic
//! composition and usage, and zero-cost abstractions over what would otherwise
//! be written by hand.
//!
//! Futures are a concept for an object which is a proxy for another value that
//! may not be ready yet. For example issuing an HTTP request may return a
//! future for the HTTP response, as it probably hasn't arrived yet. With an
//! object representing a value that will eventually be available, futures allow
//! for powerful composition of tasks through basic combinators that can perform
//! operations like chaining computations, changing the types of futures, or
//! waiting for two futures to complete at the same time.
//!
//! You can find extensive tutorials and documentations at [https://tokio.rs]
//! for both this crate (asynchronous programming in general) as well as the
//! Tokio stack to perform async I/O with.
//!
//! [https://tokio.rs]: https://tokio.rs
//!
//! ## Installation
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! futures = "0.1"
//! ```
//!
//! ## Examples
//!
//! Let's take a look at a few examples of how futures might be used:
//!
//! ```
//! extern crate futures;
//!
//! use std::io;
//! use std::time::Duration;
//! use futures::prelude::*;
//! use futures::future::Map;
//!
//! // A future is actually a trait implementation, so we can generically take a
//! // future of any integer and return back a future that will resolve to that
//! // value plus 10 more.
//! //
//! // Note here that like iterators, we're returning the `Map` combinator in
//! // the futures crate, not a boxed abstraction. This is a zero-cost
//! // construction of a future.
//! fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
//!     where F: Future<Item=i32>,
//! {
//!     fn add(a: i32) -> i32 { a + 10 }
//!     future.map(add)
//! }
//!
//! // Not only can we modify one future, but we can even compose them together!
//! // Here we have a function which takes two futures as input, and returns a
//! // future that will calculate the sum of their two values.
//! //
//! // Above we saw a direct return value of the `Map` combinator, but
//! // performance isn't always critical and sometimes it's more ergonomic to
//! // return a trait object like we do here. Note though that there's only one
//! // allocation here, not any for the intermediate futures.
//! fn add<'a, A, B>(a: A, b: B) -> Box<Future<Item=i32, Error=A::Error> + 'a>
//!     where A: Future<Item=i32> + 'a,
//!           B: Future<Item=i32, Error=A::Error> + 'a,
//! {
//!     Box::new(a.join(b).map(|(a, b)| a + b))
//! }
//!
//! // Futures also allow chaining computations together, starting another after
//! // the previous finishes. Here we wait for the first computation to finish,
//! // and then decide what to do depending on the result.
//! fn download_timeout(url: &str,
//!                     timeout_dur: Duration)
//!                     -> Box<Future<Item=Vec<u8>, Error=io::Error>> {
//!     use std::io;
//!     use std::net::{SocketAddr, TcpStream};
//!
//!     type IoFuture<T> = Box<Future<Item=T, Error=io::Error>>;
//!
//!     // First thing to do is we need to resolve our URL to an address. This
//!     // will likely perform a DNS lookup which may take some time.
//!     let addr = resolve(url);
//!
//!     // After we acquire the address, we next want to open up a TCP
//!     // connection.
//!     let tcp = addr.and_then(|addr| connect(&addr));
//!
//!     // After the TCP connection is established and ready to go, we're off to
//!     // the races!
//!     let data = tcp.and_then(|conn| download(conn));
//!
//!     // That all might take awhile, though, so let's not wait too long for it
//!     // to all come back. The `select` combinator here returns a future which
//!     // resolves to the first value that's ready plus the next future.
//!     //
//!     // Note we can also use the `then` combinator which is similar to
//!     // `and_then` above except that it receives the result of the
//!     // computation, not just the successful value.
//!     //
//!     // Again note that all the above calls to `and_then` and the below calls
//!     // to `map` and such require no allocations. We only ever allocate once
//!     // we hit the `Box::new()` call at the end here, which means we've built
//!     // up a relatively involved computation with only one box, and even that
//!     // was optional!
//!
//!     let data = data.map(Ok);
//!     let timeout = timeout(timeout_dur).map(Err);
//!
//!     let ret = data.select(timeout).then(|result| {
//!         match result {
//!             Ok(result) => {
//!                 let (data, _other_future) = result.split();
//!                 match data {
//!                     // One future succeeded, and it was the one which was
//!                     // downloading data from the connection.
//!                     Ok(data) => Ok(data),
//!
//!                     // The timeout fired, and otherwise no error was found, so
//!                     // we translate this to an error.
//!                     Err(_timeout) => {
//!                         Err(io::Error::new(io::ErrorKind::Other, "timeout"))
//!                     }
//!                 }
//!             }
//!
//!             // A normal I/O error happened, so we pass that on through.
//!             Err(err) => Err(err.split().0),
//!         }
//!     });
//!     return Box::new(ret);
//!
//!     fn resolve(url: &str) -> IoFuture<SocketAddr> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn connect(hostname: &SocketAddr) -> IoFuture<TcpStream> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn download(stream: TcpStream) -> IoFuture<Vec<u8>> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//!
//!     fn timeout(stream: Duration) -> IoFuture<()> {
//!         // ...
//! #       panic!("unimplemented");
//!     }
//! }
//! # fn main() {}
//! ```
//!
//! Some more information can also be found in the [README] for now, but
//! otherwise feel free to jump in to the docs below!
//!
//! [README]: https://github.com/alexcrichton/futures-rs#futures-rs

#![no_std]
#![doc(html_root_url = "https://docs.rs/futures/0.2")]

extern crate futures_core;
extern crate futures_channel;
extern crate futures_executor;
extern crate futures_io;
extern crate futures_sink;
extern crate futures_util;

pub use futures_core::future::{Future, IntoFuture};
pub use futures_util::future::FutureExt;
pub use futures_core::stream::Stream;
pub use futures_util::stream::StreamExt;
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt;

// Macros redefined here because macro re-exports are unstable.

/// A macro for extracting the successful type of a `Poll<T, E>`.
///
/// This macro bakes propagation of both errors and `Pending` signals by
/// returning early.
#[macro_export]
macro_rules! try_ready {
    ($e:expr) => (match $e {
        Ok($crate::prelude::Async::Ready(t)) => t,
        Ok($crate::prelude::Async::Pending) => return Ok($crate::prelude::Async::Pending),
        Err(e) => return Err(From::from(e)),
    })
}

// TODO: task_local macro

pub use futures_core::{Async, Poll};

#[cfg(feature = "std")]
pub mod channel {
    //! Channels
    //!
    //! This module contains channels for asynchronous
    //! communication.
    pub use futures_channel::*;
}

pub mod executor {
    //! Executors
    //!
    //! This module contains the `Executor` trait, which allows futures to be
    //! spawned and executed asynchronously.

    pub use futures_executor::*;
    pub use futures_core::executor::*;
}

pub mod future {
    //! Futures
    //!
    //! This module contains the `Future` trait and adapters for this trait.

    pub use futures_core::future::*;
    pub use futures_util::future::*;
}

#[cfg(feature = "std")]
pub mod io {
    //! IO
    //!
    //! This module contains the `AsyncRead` and `AsyncWrite` traits, as well
    //! as a number of combinators and extensions for using them.
    pub use futures_io::*;
    pub use futures_util::io::*;
}

#[cfg(feature = "std")]
pub mod never {
    //! This module contains the `Never` type.
    //!
    //! Values of this type can never be created and will never exist.
    pub use futures_core::never::*;
}

pub mod prelude {
	//! A "prelude" for crates using the `futures` crate.
	//!
	//! This prelude is similar to the standard library's prelude in that you'll
	//! almost always want to import its entire contents, but unlike the standard
	//! library's prelude you'll have to do so manually. An example of using this is:
	//!
	//! ```
	//! use futures::prelude::*;
	//! ```
	//!
	//! We may add items to this over time as they become ubiquitous as well, but
	//! otherwise this should help cut down on futures-related imports when you're
	//! working with the `futures` crate!

    pub use futures_core::{
        Future,
        IntoFuture,
        Stream,
        Async,
        Poll,
        task,
    };

    pub use futures_sink::Sink;

    pub use futures_util::{
		FutureExt,
		StreamExt,
        SinkExt,
    };

    #[cfg(feature = "std")]
    pub use futures_util::{
        AsyncRead,
        AsyncWrite,
        AsyncReadExt,
        AsyncWriteExt,
    };
}

pub mod sink {
	//! Asynchronous sinks
	//!
	//! This module contains the `Sink` trait, along with a number of adapter types
	//! for it. An overview is available in the documentation for the trait itself.
	//!
	//! You can find more information/tutorials about streams [online at
	//! https://tokio.rs][online]
	//!
	//! [online]: https://tokio.rs/docs/getting-started/streams-and-sinks/

    pub use futures_sink::*;
    pub use futures_util::sink::*;
}

pub mod stream {
	//! Asynchronous streams
	//!
	//! This module contains the `Stream` trait and a number of adaptors for this
	//! trait. This trait is very similar to the `Iterator` trait in the standard
	//! library except that it expresses the concept of blocking as well. A stream
	//! here is a sequential sequence of values which may take some amount of time
	//! in between to produce.
	//!
	//! A stream may request that it is blocked between values while the next value
	//! is calculated, and provides a way to get notified once the next value is
	//! ready as well.
	//!
	//! You can find more information/tutorials about streams [online at
	//! https://tokio.rs][online]
	//!
	//! [online]: https://tokio.rs/docs/getting-started/streams-and-sinks/

    pub use futures_core::stream::*;
    pub use futures_util::stream::*;
}

pub mod task {
    //! Task executon
    pub use futures_core::task::*;
}
<|endoftext|>