<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use option::{Option, Some, None};
use result::{Ok, Err};
use rt::io::{io_error};
use rt::rtio::{IoFactory, IoFactoryObject,
               RtioTimer, RtioTimerObject};
use rt::local::Local;

pub struct Timer(~RtioTimerObject);

impl Timer {

    pub fn new() -> Option<Timer> {
        let timer = unsafe {
            rtdebug!("Timer::init: borrowing io to init timer");
            let io: *mut IoFactoryObject = Local::unsafe_borrow();
            rtdebug!("about to init timer");
            (*io).timer_init()
        };
        match timer {
            Ok(t) => Some(Timer(t)),
            Err(ioerr) => {
                rtdebug!("Timer::init: failed to init: %?", ioerr);
                io_error::cond.raise(ioerr);
                None
            }
        }
    }

    pub fn sleep(&mut self, msecs: u64) {
        (**self).sleep(msecs);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::test::*;
    #[test]
    fn test_io_timer_sleep_simple() {
        do run_in_mt_newsched_task {
            let timer = Timer::new();
            do timer.map_move |mut t| { t.sleep(1) };
        }
    }
}
<commit_msg>std::rt: Add a standalone sleep function.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use option::{Option, Some, None};
use result::{Ok, Err};
use rt::io::{io_error};
use rt::rtio::{IoFactory, IoFactoryObject,
               RtioTimer, RtioTimerObject};
use rt::local::Local;

pub struct Timer(~RtioTimerObject);

/// Sleep the current task for `msecs` milliseconds.
pub fn sleep(msecs: u64) {
    let mut timer = Timer::new().expect("timer::sleep: could not create a Timer");

    timer.sleep(msecs)
}

impl Timer {

    pub fn new() -> Option<Timer> {
        let timer = unsafe {
            rtdebug!("Timer::init: borrowing io to init timer");
            let io: *mut IoFactoryObject = Local::unsafe_borrow();
            rtdebug!("about to init timer");
            (*io).timer_init()
        };
        match timer {
            Ok(t) => Some(Timer(t)),
            Err(ioerr) => {
                rtdebug!("Timer::init: failed to init: %?", ioerr);
                io_error::cond.raise(ioerr);
                None
            }
        }
    }

    pub fn sleep(&mut self, msecs: u64) {
        (**self).sleep(msecs);
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rt::test::*;
    #[test]
    fn test_io_timer_sleep_simple() {
        do run_in_mt_newsched_task {
            let timer = Timer::new();
            do timer.map_move |mut t| { t.sleep(1) };
        }
    }

    #[test]
    fn test_io_timer_sleep_standalone() {
        do run_in_mt_newsched_task {
            sleep(1)
        }
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Nicholas Juszczak <juszczakn@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;

static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
static OPT_MODE: &str = "mode";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

/**
 * Handles option parsing
 */
pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "context", "set SELinux security context" +
    // " of each created directory to CTX"),
    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_MODE)
                .short("m")
                .long(OPT_MODE)
                .help("set file mode")
                .default_value("755"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .alias("parent")
                .help("make parent directories as needed"),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("print a message for each printed directory"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let verbose = matches.is_present(OPT_VERBOSE);
    let recursive = matches.is_present(OPT_PARENTS);

    // Translate a ~str in octal form to u16, default to 755
    // Not tested on Windows
    let mode_match = matches.value_of(OPT_MODE);
    let mode: u16 = match mode_match {
        Some(m) => {
            let res: Option<u16> = u16::from_str_radix(&m, 8).ok();
            match res {
                Some(r) => r,
                _ => crash!(1, "no mode given"),
            }
        }
        _ => 0o755_u16,
    };

    exec(dirs, recursive, mode, verbose)
}

/**
 * Create the list of new directories
 */
fn exec(dirs: Vec<String>, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let mut status = 0;
    let empty = Path::new("");
    for dir in &dirs {
        let path = Path::new(dir);
        if !recursive {
            if let Some(parent) = path.parent() {
                if parent != empty && !parent.exists() {
                    show_error!(
                        "cannot create directory '{}': No such file or directory",
                        path.display()
                    );
                    status = 1;
                    continue;
                }
            }
        }
        status |= mkdir(path, recursive, mode, verbose);
    }
    status
}

/**
 * Wrapper to catch errors, return 1 if failed
 */
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let create_dir = if recursive {
        fs::create_dir_all
    } else {
        fs::create_dir
    };
    if let Err(e) = create_dir(path) {
        show_error!("{}: {}", path.display(), e.to_string());
        return 1;
    }

    if verbose {
        println!("{}: created directory '{}'", executable!(), path.display());
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn chmod(path: &Path, mode: u16) -> i32 {
        use std::fs::{set_permissions, Permissions};
        use std::os::unix::fs::PermissionsExt;

        let mode = Permissions::from_mode(u32::from(mode));

        if let Err(err) = set_permissions(path, mode) {
            show_error!("{}: {}", path.display(), err);
            return 1;
        }
        0
    }
    #[cfg(windows)]
    #[allow(unused_variables)]
    fn chmod(path: &Path, mode: u16) -> i32 {
        // chmod on Windows only sets the readonly flag, which isn't even honored on directories
        0
    }
    chmod(path, mode)
}
<commit_msg>refactor/mkdir ~ fix `cargo clippy` complaint (clippy::needless_borrow)<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Nicholas Juszczak <juszczakn@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;

static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
static OPT_MODE: &str = "mode";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

fn get_usage() -> String {
    format!("{0} [OPTION]... [USER]", executable!())
}

/**
 * Handles option parsing
 */
pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "context", "set SELinux security context" +
    // " of each created directory to CTX"),
    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_MODE)
                .short("m")
                .long(OPT_MODE)
                .help("set file mode")
                .default_value("755"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .alias("parent")
                .help("make parent directories as needed"),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("print a message for each printed directory"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let verbose = matches.is_present(OPT_VERBOSE);
    let recursive = matches.is_present(OPT_PARENTS);

    // Translate a ~str in octal form to u16, default to 755
    // Not tested on Windows
    let mode_match = matches.value_of(OPT_MODE);
    let mode: u16 = match mode_match {
        Some(m) => {
            let res: Option<u16> = u16::from_str_radix(m, 8).ok();
            match res {
                Some(r) => r,
                _ => crash!(1, "no mode given"),
            }
        }
        _ => 0o755_u16,
    };

    exec(dirs, recursive, mode, verbose)
}

/**
 * Create the list of new directories
 */
fn exec(dirs: Vec<String>, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let mut status = 0;
    let empty = Path::new("");
    for dir in &dirs {
        let path = Path::new(dir);
        if !recursive {
            if let Some(parent) = path.parent() {
                if parent != empty && !parent.exists() {
                    show_error!(
                        "cannot create directory '{}': No such file or directory",
                        path.display()
                    );
                    status = 1;
                    continue;
                }
            }
        }
        status |= mkdir(path, recursive, mode, verbose);
    }
    status
}

/**
 * Wrapper to catch errors, return 1 if failed
 */
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> i32 {
    let create_dir = if recursive {
        fs::create_dir_all
    } else {
        fs::create_dir
    };
    if let Err(e) = create_dir(path) {
        show_error!("{}: {}", path.display(), e.to_string());
        return 1;
    }

    if verbose {
        println!("{}: created directory '{}'", executable!(), path.display());
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn chmod(path: &Path, mode: u16) -> i32 {
        use std::fs::{set_permissions, Permissions};
        use std::os::unix::fs::PermissionsExt;

        let mode = Permissions::from_mode(u32::from(mode));

        if let Err(err) = set_permissions(path, mode) {
            show_error!("{}: {}", path.display(), err);
            return 1;
        }
        0
    }
    #[cfg(windows)]
    #[allow(unused_variables)]
    fn chmod(path: &Path, mode: u16) -> i32 {
        // chmod on Windows only sets the readonly flag, which isn't even honored on directories
        0
    }
    chmod(path, mode)
}
<|endoftext|>


<commit_before>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        registry::PackageRegistry,
        resolver::{self, Method, Resolve},
        source::MaybePackage,
        Dependency, Package, Source, SourceId,
    },
    sources::RegistrySource,
    util::Config,
};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{btree_map::Entry, BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename="crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename="id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all="kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

/// `"1.0.0"` or `{ version = "1.0.0", features = ["..."] }`
#[derive(Serialize, Clone)]
#[serde(untagged)]
enum DependencySpec {
    #[serde(serialize_with = "exact_version")]
    String(String),
    #[serde(rename_all = "kebab-case")]
    Explicit {
        #[serde(serialize_with = "exact_version")]
        version: String,
        #[serde(skip_serializing_if = "Vec::is_empty")]
        features: Vec<String>,
        #[serde(skip_serializing_if = "is_true")]
        default_features: bool,
    }
}

impl DependencySpec {
    fn version(&self) -> String {
        match *self {
            DependencySpec::String(ref version) |
            DependencySpec::Explicit { ref version, .. } => version.clone(),
        }
    }
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d)
            .expect("unable to parse crate modifications file")
    };
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            reqwest::get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
            .expect("Could not fetch top crates");
        assert!(resp.status().is_success());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

fn unique_latest_crates(resolve: Resolve) -> BTreeMap<String, DependencySpec> {
    let mut uniqs = BTreeMap::new();
    for pkg in resolve.iter() {
        if MODIFICATIONS.blacklisted(pkg.name().as_str()) {
            continue;
        }

        match uniqs.entry(pkg.name()) {
            Entry::Vacant(entry) => {
                // First time seeing this package.
                entry.insert(pkg.version());
            }
            Entry::Occupied(mut entry) => {
                // Seen before, keep the newest version.
                if &pkg.version() > entry.get() {
                    entry.insert(pkg.version());
                }
            }
        }
    }

    uniqs.into_iter()
         .map(|(name, version)| (
             name.to_string(),
             DependencySpec::String(version.to_string()),
         ))
         .collect()
}

/// Updates `dep` to include features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn fill_playground_metadata_features(dep: &mut DependencySpec, pkg: &Package) {
    let custom_metadata = match pkg.manifest().custom_metadata() {
        Some(custom_metadata) => custom_metadata,
        None => return,
    };

    let playground_metadata = match custom_metadata.get("playground") {
        Some(playground_metadata) => playground_metadata,
        None => return,
    };

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(), pkg.version(), err);
            return;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        *dep = DependencySpec::Explicit {
            version: dep.version(),
            features: enabled_features.into_iter().collect(),
            default_features: metadata.default_features,
        };
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches.into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((summary, Method::Required {
            dev_deps: false,
            features: &[],
            uses_default_features: true,
            all_features: false,
        }));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config)
        .expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let res = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Construct playground's Cargo.toml.
    let mut unique_latest_crates = unique_latest_crates(res);

    let mut infos = Vec::new();

    for (name, spec) in &mut unique_latest_crates {
        let version = spec.version();

        let pkgid = cargo::core::PackageId::new(&name, &version, crates_io)
            .unwrap_or_else(|e| panic!("Unable to build PackageId for {} {}: {}", name, version, e));

        let pkg = source.download(pkgid)
            .unwrap_or_else(|e| panic!("Unable to download {} {}: {}", name, version, e));

        let pkg = match pkg {
            MaybePackage::Ready(pkg) => pkg,
            _ => panic!("Package {} {} was not downloaded", name, version),
        };

        for target in pkg.targets() {
            if let cargo::core::TargetKind::Lib(_) = *target.kind() {
                infos.push(CrateInformation {
                    name: name.clone(),
                    version: version.clone(),
                    id: target.crate_name()
                })
            }
        }

        fill_playground_metadata_features(spec, &pkg);
    }

    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile { codegen_units: 1, incremental: false },
            release: Profile { codegen_units: 1, incremental: false },
        },
        dependencies: unique_latest_crates,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path)
        .unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<commit_msg>Start using Cargo's PackageSet<commit_after>#![deny(rust_2018_idioms)]

use cargo::{
    core::{
        package::PackageSet,
        registry::PackageRegistry,
        resolver::{self, Method, Resolve},
        source::SourceMap,
        Dependency, Package, PackageId, Source, SourceId, TargetKind,
    },
    sources::RegistrySource,
    util::Config,
};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::{
    collections::{btree_map::Entry, BTreeMap, BTreeSet, HashSet},
    fs::File,
    io::{Read, Write},
};

/// The list of crates from crates.io
#[derive(Debug, Deserialize)]
struct TopCrates {
    crates: Vec<Crate>,
}

/// A single crate from crates.io
#[derive(Debug, Deserialize)]
struct OneCrate {
    #[serde(rename="crate")]
    krate: Crate,
}

/// The shared description of a crate
#[derive(Debug, Deserialize)]
struct Crate {
    #[serde(rename="id")]
    name: String,
}

/// A Cargo.toml file.
#[derive(Serialize)]
struct TomlManifest {
    package: TomlPackage,
    profile: Profiles,
    #[serde(serialize_with = "toml::ser::tables_last")]
    dependencies: BTreeMap<String, DependencySpec>,
}

/// Header of Cargo.toml file.
#[derive(Serialize)]
struct TomlPackage {
    name: String,
    version: String,
    authors: Vec<String>,
}

/// A mapping of a crates name to its identifier used in source code
#[derive(Debug, Serialize)]
struct CrateInformation {
    name: String,
    version: String,
    id: String,
}

/// Hand-curated changes to the crate list
#[derive(Debug, Deserialize)]
struct Modifications {
    #[serde(default)]
    blacklist: Vec<String>,
    #[serde(default)]
    additions: BTreeSet<String>,
}

/// A profile section in a Cargo.toml file
#[derive(Serialize)]
#[serde(rename_all="kebab-case")]
struct Profile {
    codegen_units: u32,
    incremental: bool,
}

/// Available profile types
#[derive(Serialize)]
struct Profiles {
    dev: Profile,
    release: Profile,
}

/// `"1.0.0"` or `{ version = "1.0.0", features = ["..."] }`
#[derive(Serialize, Clone)]
#[serde(untagged)]
enum DependencySpec {
    #[serde(serialize_with = "exact_version")]
    String(String),
    #[serde(rename_all = "kebab-case")]
    Explicit {
        #[serde(serialize_with = "exact_version")]
        version: String,
        #[serde(skip_serializing_if = "Vec::is_empty")]
        features: Vec<String>,
        #[serde(skip_serializing_if = "is_true")]
        default_features: bool,
    }
}

impl DependencySpec {
    fn version(&self) -> String {
        match *self {
            DependencySpec::String(ref version) |
            DependencySpec::Explicit { ref version, .. } => version.clone(),
        }
    }
}

fn exact_version<S>(version: &String, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    format!("={}", version).serialize(serializer)
}

fn is_true(b: &bool) -> bool {
    *b
}

impl Modifications {
    fn blacklisted(&self, name: &str) -> bool {
        self.blacklist.iter().any(|n| n == name)
    }
}

lazy_static! {
    static ref MODIFICATIONS: Modifications = {
        let mut f = File::open("crate-modifications.toml")
            .expect("unable to open crate modifications file");

        let mut d = Vec::new();
        f.read_to_end(&mut d)
            .expect("unable to read crate modifications file");

        toml::from_slice(&d)
            .expect("unable to parse crate modifications file")
    };
}

impl TopCrates {
    /// List top 100 crates by number of downloads on crates.io.
    fn download() -> TopCrates {
        let resp =
            reqwest::get("https://crates.io/api/v1/crates?page=1&per_page=100&sort=downloads")
            .expect("Could not fetch top crates");
        assert!(resp.status().is_success());

        serde_json::from_reader(resp).expect("Invalid JSON")
    }

    /// Add crates that have been hand-picked
    fn add_curated_crates(&mut self) {
        self.crates.extend({
            MODIFICATIONS
                .additions
                .iter()
                .cloned()
                .map(|name| Crate { name })
        });
    }
}

fn unique_latest_crates(resolve: Resolve) -> BTreeMap<String, DependencySpec> {
    let mut uniqs = BTreeMap::new();
    for pkg in resolve.iter() {
        if MODIFICATIONS.blacklisted(pkg.name().as_str()) {
            continue;
        }

        match uniqs.entry(pkg.name()) {
            Entry::Vacant(entry) => {
                // First time seeing this package.
                entry.insert(pkg.version());
            }
            Entry::Occupied(mut entry) => {
                // Seen before, keep the newest version.
                if &pkg.version() > entry.get() {
                    entry.insert(pkg.version());
                }
            }
        }
    }

    uniqs.into_iter()
         .map(|(name, version)| (
             name.to_string(),
             DependencySpec::String(version.to_string()),
         ))
         .collect()
}

/// Updates `dep` to include features specified by the custom metadata of `pkg`.
///
/// Our custom metadata format looks like:
///
///     [package.metadata.playground]
///     default-features = true
///     features = ["std", "extra-traits"]
///     all-features = false
///
/// All fields are optional.
fn fill_playground_metadata_features(dep: &mut DependencySpec, pkg: &Package) {
    let custom_metadata = match pkg.manifest().custom_metadata() {
        Some(custom_metadata) => custom_metadata,
        None => return,
    };

    let playground_metadata = match custom_metadata.get("playground") {
        Some(playground_metadata) => playground_metadata,
        None => return,
    };

    #[derive(Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    struct Metadata {
        features: Vec<String>,
        default_features: bool,
        all_features: bool,
    }

    impl Default for Metadata {
        fn default() -> Self {
            Metadata {
                features: Vec::new(),
                default_features: true,
                all_features: false,
            }
        }
    }

    let metadata = match playground_metadata.clone().try_into::<Metadata>() {
        Ok(metadata) => metadata,
        Err(err) => {
            eprintln!(
                "Failed to parse custom metadata for {} {}: {}",
                pkg.name(), pkg.version(), err);
            return;
        }
    };

    // If `all-features` is set then we ignore `features`.
    let summary = pkg.summary();
    let mut enabled_features: BTreeSet<String> = if metadata.all_features {
        summary.features().keys().map(ToString::to_string).collect()
    } else {
        metadata.features.into_iter().collect()
    };

    // If not opting out of default features, remove default features from the
    // explicit features list. This avoids ongoing spurious diffs in our
    // generated Cargo.toml as default features are added to a library.
    if metadata.default_features {
        if let Some(default_feature_names) = summary.features().get("default") {
            enabled_features.remove("default");
            for feature in default_feature_names {
                enabled_features.remove(&feature.to_string(summary));
            }
        }
    }

    if !enabled_features.is_empty() || !metadata.default_features {
        *dep = DependencySpec::Explicit {
            version: dep.version(),
            features: enabled_features.into_iter().collect(),
            default_features: metadata.default_features,
        };
    }
}

fn write_manifest(manifest: TomlManifest, path: &str) {
    let mut f = File::create(path).expect("Unable to create Cargo.toml");
    let content = toml::to_vec(&manifest).expect("Couldn't serialize TOML");
    f.write_all(&content).expect("Couldn't write Cargo.toml");
}

fn main() {
    // Setup to interact with cargo.
    let config = Config::default().expect("Unable to create default Cargo config");
    let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
    let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
    source.update().expect("Unable to update registry");

    let mut top = TopCrates::download();
    top.add_curated_crates();

    // Find the newest (non-prerelease, non-yanked) versions of all
    // the interesting crates.
    let mut summaries = Vec::new();
    for Crate { ref name } in top.crates {
        if MODIFICATIONS.blacklisted(name) {
            continue;
        }

        // Query the registry for a summary of this crate.
        // Usefully, this doesn't seem to include yanked versions
        let dep = Dependency::parse_no_deprecated(name, None, crates_io)
            .unwrap_or_else(|e| panic!("Unable to parse dependency for {}: {}", name, e));

        let matches = source.query_vec(&dep).unwrap_or_else(|e| {
            panic!("Unable to query registry for {}: {}", name, e);
        });

        // Find the newest non-prelease version
        let summary = matches.into_iter()
            .filter(|summary| !summary.version().is_prerelease())
            .max_by_key(|summary| summary.version().clone())
            .unwrap_or_else(|| panic!("Registry has no viable versions of {}", name));

        // Add a dependency on this crate.
        summaries.push((summary, Method::Required {
            dev_deps: false,
            features: &[],
            uses_default_features: true,
            all_features: false,
        }));
    }

    // Resolve transitive dependencies.
    let mut registry = PackageRegistry::new(&config)
        .expect("Unable to create package registry");
    registry.lock_patches();
    let try_to_use = HashSet::new();
    let res = resolver::resolve(&summaries, &[], &mut registry, &try_to_use, None, true)
        .expect("Unable to resolve dependencies");

    // Construct playground's Cargo.toml.
    let mut unique_latest_crates = unique_latest_crates(res);

    let mut infos = Vec::new();

    let package_ids: Vec<_> = unique_latest_crates
        .iter()
        .map(|(name, spec)| {
            let version = spec.version();
            PackageId::new(name, &version, crates_io).unwrap_or_else(|e| {
                panic!("Unable to build PackageId for {} {}: {}", name, version, e)
            })
        })
        .collect();

    let mut sources = SourceMap::new();
    sources.insert(Box::new(source));

    let package_set =
        PackageSet::new(&package_ids, sources, &config).expect("Unable to create a PackageSet");

    let packages = package_set
        .get_many(package_set.package_ids())
        .expect("Unable to download packages");

    for pkg in packages {
        let name = pkg.name().to_string();
        let version = pkg.version().to_string();

        let spec = unique_latest_crates
            .get_mut(&name)
            .expect("Crate went missing");

        for target in pkg.targets() {
            if let TargetKind::Lib(_) = *target.kind() {
                infos.push(CrateInformation {
                    name: name.clone(),
                    version: version.clone(),
                    id: target.crate_name(),
                })
            }
        }

        fill_playground_metadata_features(spec, &pkg);
    }

    infos.sort_by(|a, b| a.name.cmp(&b.name));

    let manifest = TomlManifest {
        package: TomlPackage {
            name: "playground".to_owned(),
            version: "0.0.1".to_owned(),
            authors: vec!["The Rust Playground".to_owned()],
        },
        profile: Profiles {
            dev: Profile { codegen_units: 1, incremental: false },
            release: Profile { codegen_units: 1, incremental: false },
        },
        dependencies: unique_latest_crates,
    };

    // Write manifest file.
    let cargo_toml = "../compiler/base/Cargo.toml";
    write_manifest(manifest, cargo_toml);
    println!("wrote {}", cargo_toml);

    let path = "../compiler/base/crate-information.json";
    let mut f = File::create(path)
        .unwrap_or_else(|e| panic!("Unable to create {}: {}", path, e));
    serde_json::to_writer_pretty(&mut f, &infos)
        .unwrap_or_else(|e| panic!("Unable to write {}: {}", path, e));
    println!("Wrote {}", path);
}
<|endoftext|>


<commit_before>pub fn init_fs() {
    let schemes = schemes_mut().unwrap();
    schemes.insert(SchemeNamespace(0), Box::new(*b"acpi"), |_| Arc::new(Box::new(AcpiScheme::new()))).unwrap();
}

struct AcpiScheme {

}

impl AcpiScheme {
    pub fn new() -> AcpiScheme {
        AcpiScheme
    }
}

impl Scheme for AcpiScheme {
    fn open(&self, url: &[u8], flags: usize, uid: u32, gid: u32) -> Result<usize> {
        let path = str::from_utf8(url).unwrap_or("").trim_matches('/');

<commit_msg>Removed spurious file<commit_after><|endoftext|>


<commit_before>use crate::errors::OscError;

use alloc::string::{String, ToString};
use alloc::vec::Vec;
use std::collections::HashSet;
use std::iter::FromIterator;
use nom::branch::alt;
use nom::bytes::complete::{is_a, is_not, tag, take, take_while1};
use nom::character::complete::{char, satisfy};
use nom::combinator::{all_consuming, complete, opt, recognize, verify};
use nom::error::{ErrorKind, ParseError};
use nom::multi::{many1, separated_list1};
use nom::sequence::{delimited, pair, separated_pair};
use nom::{IResult, Parser};

/// With a Matcher OSC method addresses can be [matched](Matcher::match_address) against an OSC address pattern.
/// Refer to the OSC specification for details about OSC address spaces: <http://opensoundcontrol.org/spec-1_0.html#osc-address-spaces-and-osc-addresses>
#[derive(Debug)]
pub struct Matcher {
    pub pattern: String,
    pattern_parts: Vec<AddressPatternComponent>,
}

impl Matcher {
    /// Instantiates a new `Matcher` with the given address pattern.
    /// An error will be returned if the given address pattern is invalid.
    ///
    /// Matcher should be instantiated once per pattern and reused because its construction requires parsing the address pattern which is computationally expensive.
    ///
    /// A valid address pattern begins with a `/` and contains at least a method name, e.g. `/tempo`.
    /// OSC defines a couple of rules that look like regular expression but are subtly different:
    ///
    /// - `?` matches a single character
    /// - `*` matches zero or more characters
    /// - `[a-z]` are basically regex [character classes](https://www.regular-expressions.info/charclass.html)
    /// - `{foo,bar}` is an alternative, matching either `foo` or `bar`
    /// - everything else is matched literally
    ///
    /// Refer to the OSC specification for details about address pattern matching: <osc-message-dispatching-and-pattern-matching>.
    ///
    /// # Examples
    ///
    /// ```
    /// use rosc::address::Matcher;
    ///
    /// Matcher::new("/tempo").expect("valid address");
    /// Matcher::new("").expect_err("address does not start with a slash");
    /// ```
    pub fn new(pattern: &str) -> Result<Self, OscError> {
        verify_address_pattern(pattern)?;
        let pattern_parts = match all_consuming(many1(map_address_pattern_component))(pattern) {
            Ok((_, parts)) => parts,
            // This should never happen because pattern is verified above
            Err(_) => panic!("Address pattern must be valid"),
        };

        Ok(Matcher {
            pattern: pattern.into(),
            pattern_parts,
        })
    }

    /// Match an OSC address against an address pattern.
    /// If the address matches the pattern the result will be `true`, otherwise `false`.
    /// An error is returned if the given OSC address is not valid.
    ///
    /// A valid OSC address begins with a `/` and contains at least a method name, e.g. `/tempo`.
    /// Despite OSC address patterns a plain address must not include any of the following characters `#*,/?[]{}`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rosc::address::Matcher;
    ///
    /// let matcher = Matcher::new("/oscillator/[0-9]/{frequency,phase}").unwrap();
    /// assert!(matcher.match_address("/oscillator/1/frequency").unwrap());
    /// assert!(matcher.match_address("/oscillator/8/phase").unwrap());
    /// assert_eq!(matcher.match_address("/oscillator/4/detune").unwrap(), false);
    /// ```
    pub fn match_address(&self, address: &str) -> Result<bool, OscError> {
        verify_address(address)?; // TODO: Create an address struct so we don't have to re-check addresses every time we match

        // Trivial case
        if address == self.pattern {
            return Ok(true);
        }
        let mut remainder: &str = address;
        // Match the the address component by component
        for (index, part) in self.pattern_parts.as_slice().iter().enumerate() {
            let result = match part {
                AddressPatternComponent::Tag(s) => match_literally(remainder, s.as_str()),
                AddressPatternComponent::WildcardSingle => match_wildcard_single(remainder),
                AddressPatternComponent::Wildcard(l) => {
                    // Check if this is the last pattern component
                    if index < self.pattern_parts.len() - 1 {
                        let next = &self.pattern_parts[index + 1];
                        match next {
                            // If the next component is a '/', there are no more components in the current part and it can be wholly consumed
                            AddressPatternComponent::Tag(s) if s == "/" => {
                                match_wildcard(remainder, *l, None)
                            }
                            _ => match_wildcard(remainder, *l, Some(next)),
                        }
                    } else {
                        match_wildcard(remainder, *l, None)
                    }
                }
                AddressPatternComponent::CharacterClass(cc) => match_character_class(remainder, cc),
                AddressPatternComponent::Choice(s) => match_choice(remainder, s),
            };

            match result {
                Ok((i, _)) => remainder = i,
                Err(_) => return Ok(false), // Component didn't match, goodbye
            };
        }

        // Address is only matched if it was consumed entirely
        Ok(remainder.is_empty())
    }
}

/// Check whether a character is an allowed address character
/// All printable ASCII characters except for a few special characters are allowed
fn is_address_character(x: char) -> bool {
    match x {
        ' ' | '#' | '*' | ',' | '/' | '?' | '[' | ']' | '{' | '}' => false,
        c => c > '\x20' && c < '\x7F',
    }
}

/// Parser to turn a choice like '{foo,bar}' into a vector containing the choices, like ["foo", "bar"]
fn pattern_choice(input: &str) -> IResult<&str, Vec<&str>> {
    delimited(
        char('{'),
        separated_list1(tag(","), take_while1(is_address_character)),
        char('}'),
    )(input)
}

/// Parser to recognize a character class like [!a-zA-Z] and return '!a-zA-Z'
fn pattern_character_class(input: &str) -> IResult<&str, &str> {
    let inner = pair(
        // It is important to read the leading negating '!' to make sure the rest of the parsed
        // character class isn't empty. E.g. '[!]' is not a valid character class.
        recognize(opt(tag("!"))),
        take_while1(is_address_character),
    );

    delimited(char('['), recognize(inner), char(']'))(input)
}

/// A characters class is defined by a set or range of characters that it matches.
/// For example, [a-z] matches all lowercase alphabetic letters. It can also contain multiple
/// ranges, like [a-zA-Z]. Instead of a range you can also directly provide the characters to match,
/// e.g. [abc123]. You can also combine this with ranges, like [a-z123].
/// If the first characters is an exclamation point, the match is negated, e.g. [!0-9] will match
/// anything except numbers.
#[derive(Debug)]
struct CharacterClass {
    pub negated: bool,
    pub characters: String,
}

/// Expand a character range like 'a-d' to all the letters contained in the range, e.g. 'abcd'
/// This is done by converting the characters to their ASCII values and then getting every ASCII
/// in between.
fn expand_character_range(first: char, second: char) -> String {
    let start = first as u8;
    let end = second as u8;

    let range = if start >= end {
        end..=start
    } else {
        start..=end
    };

    range
        .into_iter()
        .map(char::from)
        .filter(|c| is_address_character(*c))
        .collect()
}

impl CharacterClass {
    pub fn new(s: &str) -> Self {
        let mut input = s;
        let negated;
        match char::<_, nom::error::Error<&str>>('!')(input) {
            Ok((i, _)) => {
                negated = true;
                input = i;
            }
            Err(_) => negated = false,
        }

        let characters = complete(many1(alt((
            // '!' besides at beginning has no special meaning, but is legal
            char::<_, nom::error::Error<&str>>('!').map(|_| String::from("")),
            // attempt to match a range like a-z or 0-9
            separated_pair(
                satisfy(is_address_character),
                char('-'),
                satisfy(is_address_character),
            )
            .map(|(first, second)| expand_character_range(first, second)),
            // Match characters literally
            satisfy(is_address_character).map(|x| x.to_string()),
            // Trailing dash
            char('-').map(|_| String::from("-")),
        ))))(input);

        match characters {
            Ok((_, o)) => CharacterClass {
                negated,
                characters: HashSet::<char>::from_iter(o.concat().chars()).iter().collect(),
            },
            _ => {
                panic!("Invalid character class formatting {}", s)
            }
        }
    }
}

#[derive(Debug)]
enum AddressPatternComponent {
    Tag(String),
    Wildcard(usize),
    WildcardSingle,
    CharacterClass(CharacterClass),
    Choice(Vec<String>),
}

fn map_address_pattern_component(input: &str) -> IResult<&str, AddressPatternComponent> {
    alt((
        // Anything that's alphanumeric gets matched literally
        take_while1(is_address_character)
            .map(|s: &str| AddressPatternComponent::Tag(String::from(s))),
        // Slashes must be seperated into their own tag for the non-greedy implementation of wildcards
        char('/').map(|c: char| AddressPatternComponent::Tag(c.to_string())),
        tag("?").map(|_| AddressPatternComponent::WildcardSingle),
        // Combinations of wildcards are a bit tricky.
        // Multiple '*' wildcards in a row are equal to a single '*'.
        // A '*' wildcard followed by any number of '?' wildcards is also equal to '*' but must
        // match at least the same amount of characters as there are '?' wildcards in the combination.
        // For example, '*??' must match at least 2 characters.
        is_a("*?").map(|x: &str| AddressPatternComponent::Wildcard(x.matches('?').count())),
        pattern_choice.map(|choices: Vec<&str>| {
            AddressPatternComponent::Choice(choices.iter().map(|x| x.to_string()).collect())
        }),
        pattern_character_class
            .map(|s: &str| AddressPatternComponent::CharacterClass(CharacterClass::new(s))),
    ))(input)
}

fn match_literally<'a>(input: &'a str, pattern: &str) -> IResult<&'a str, &'a str> {
    tag(pattern)(input)
}

fn match_wildcard_single(input: &str) -> IResult<&str, &str> {
    // TODO: this has to be possible with a simpler parser?
    verify(take(1usize), |s: &str| s.chars().all(is_address_character))(input)
}

fn match_character_class<'a>(
    input: &'a str,
    character_class: &'a CharacterClass,
) -> IResult<&'a str, &'a str> {
    if character_class.negated {
        is_not(character_class.characters.as_str())(input)
    } else {
        is_a(character_class.characters.as_str())(input)
    }
}

/// Try all the tags in a choice element
/// Example choice element: '{foo,bar}'
/// It will get parsed into a vector containing the strings "foo" and "bar", which are then matched
fn match_choice<'a>(input: &'a str, choices: &[String]) -> IResult<&'a str, &'a str> {
    for choice in choices {
        if let Ok((i, o)) = tag::<_, _, nom::error::Error<&str>>(choice.as_str())(input) {
            return Ok((i, o));
        }
    }
    Err(nom::Err::Error(nom::error::Error::from_error_kind(
        input,
        ErrorKind::Tag,
    )))
}

/// Match Wildcard '*' by either consuming the rest of the part, or, if it's not the last component
/// in the part, by looking ahead and matching the next component
fn match_wildcard<'a>(
    input: &'a str,
    minimum_length: usize,
    next: Option<&AddressPatternComponent>,
) -> IResult<&'a str, &'a str> {
    match next {
        // No next component, consume all allowed characters until end or next '/'
        None => verify(take_while1(is_address_character), |s: &str| {
            s.len() >= minimum_length
        })(input),
        // There is another element in this part, so logic gets a bit more complicated
        Some(component) => {
            // Wildcards can only match within the current address part, discard the rest
            let address_part = match input.split_once('/') {
                Some((p, _)) => p,
                None => input,
            };

            // Attempt to find the latest matching occurrence of the next pattern component
            // This is a greedy wildcard implementation
            let mut longest: usize = 0;
            for i in 0..address_part.len() {
                let (_, substring) = input.split_at(i);
                let result: IResult<_, _, nom::error::Error<&str>> = match component {
                    AddressPatternComponent::Tag(s) => match_literally(substring, s.as_str()),
                    AddressPatternComponent::CharacterClass(cc) => {
                        match_character_class(substring, cc)
                    }
                    AddressPatternComponent::Choice(s) => match_choice(substring, s),
                    // These two cases are prevented from happening by map_address_pattern_component
                    AddressPatternComponent::WildcardSingle => {
                        panic!("Single wildcard ('?') must not follow wildcard ('*')")
                    }
                    AddressPatternComponent::Wildcard(_) => {
                        panic!("Double wildcards must be condensed into one")
                    }
                };

                if result.is_ok() {
                    longest = i
                }
            }
            verify(take(longest), |s: &str| s.len() >= minimum_length)(input)
        }
    }
}

/// Verify that an address is valid
///
/// # Examples
/// ```
/// use rosc::address::verify_address;
///
/// match verify_address("/oscillator/1") {
///     Ok(()) => println!("Address is valid"),
///     Err(e) => println!("Address is not valid")
/// }
/// ```
pub fn verify_address(input: &str) -> Result<(), OscError> {
    match all_consuming::<_, _, nom::error::Error<&str>, _>(many1(pair(
        tag("/"),
        take_while1(is_address_character),
    )))(input)
    {
        Ok(_) => Ok(()),
        Err(_) => Err(OscError::BadAddress("Invalid address".to_string())),
    }
}

/// Parse an address pattern's part until the next '/' or the end
fn address_pattern_part_parser(input: &str) -> IResult<&str, Vec<&str>> {
    many1::<_, _, nom::error::Error<&str>, _>(alt((
        take_while1(is_address_character),
        tag("?"),
        tag("*"),
        recognize(pattern_choice),
        pattern_character_class,
    )))(input)
}

/// Verify that an address pattern is valid
///
/// # Examples
/// ```
/// use rosc::address::verify_address_pattern;
///
/// match verify_address_pattern("/oscillator/[0-9]/*") {
///     Ok(()) => println!("Address is valid"),
///     Err(e) => println!("Address is not valid")
/// }
/// ```
pub fn verify_address_pattern(input: &str) -> Result<(), OscError> {
    match all_consuming(many1(
        // Each part must start with a '/'. This automatically also prevents a trailing '/'
        pair(tag("/"), address_pattern_part_parser.map(|x| x.concat())),
    ))(input)
    {
        Ok(_) => Ok(()),
        Err(_) => Err(OscError::BadAddress("Invalid address pattern".to_string())),
    }
}
<commit_msg>Clarify docs<commit_after>use crate::errors::OscError;

use alloc::string::{String, ToString};
use alloc::vec::Vec;
use std::collections::HashSet;
use std::iter::FromIterator;
use nom::branch::alt;
use nom::bytes::complete::{is_a, is_not, tag, take, take_while1};
use nom::character::complete::{char, satisfy};
use nom::combinator::{all_consuming, complete, opt, recognize, verify};
use nom::error::{ErrorKind, ParseError};
use nom::multi::{many1, separated_list1};
use nom::sequence::{delimited, pair, separated_pair};
use nom::{IResult, Parser};

/// With a Matcher OSC method addresses can be [matched](Matcher::match_address) against an OSC address pattern.
/// Refer to the OSC specification for details about OSC address spaces: <http://opensoundcontrol.org/spec-1_0.html#osc-address-spaces-and-osc-addresses>
#[derive(Debug)]
pub struct Matcher {
    pub pattern: String,
    pattern_parts: Vec<AddressPatternComponent>,
}

impl Matcher {
    /// Instantiates a new `Matcher` with the given address pattern.
    /// An error will be returned if the given address pattern is invalid.
    ///
    /// Matcher should be instantiated once per pattern and reused because its construction requires parsing the address pattern which is computationally expensive.
    ///
    /// A valid address pattern begins with a `/` and contains at least a method name, e.g. `/tempo`.
    /// OSC defines a couple of rules that look like regular expression but are subtly different:
    ///
    /// - `?` matches a single character
    /// - `*` matches zero or more characters
    /// - `[a-z]` are basically regex [character classes](https://www.regular-expressions.info/charclass.html)
    /// - `{foo,bar}` is an alternative, matching either `foo` or `bar`
    /// - everything else is matched literally
    ///
    /// Refer to the OSC specification for details about address pattern matching: <osc-message-dispatching-and-pattern-matching>.
    ///
    /// # Examples
    ///
    /// ```
    /// use rosc::address::Matcher;
    ///
    /// Matcher::new("/tempo").expect("valid address");
    /// Matcher::new("").expect_err("address does not start with a slash");
    /// ```
    pub fn new(pattern: &str) -> Result<Self, OscError> {
        verify_address_pattern(pattern)?;
        let pattern_parts = match all_consuming(many1(map_address_pattern_component))(pattern) {
            Ok((_, parts)) => parts,
            // This should never happen because pattern is verified above
            Err(_) => panic!("Address pattern must be valid"),
        };

        Ok(Matcher {
            pattern: pattern.into(),
            pattern_parts,
        })
    }

    /// Match an OSC address against an address pattern.
    /// If the address matches the pattern the result will be `true`, otherwise `false`.
    /// An error is returned if the given OSC address is not valid.
    ///
    /// A valid OSC address begins with a `/` and contains at least a method name, e.g. `/tempo`.
    /// Despite OSC address patterns a plain address must not include any of the following characters `#*,/?[]{}`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rosc::address::Matcher;
    ///
    /// let matcher = Matcher::new("/oscillator/[0-9]/{frequency,phase}").unwrap();
    /// assert!(matcher.match_address("/oscillator/1/frequency").unwrap());
    /// assert!(matcher.match_address("/oscillator/8/phase").unwrap());
    /// assert_eq!(matcher.match_address("/oscillator/4/detune").unwrap(), false);
    /// ```
    pub fn match_address(&self, address: &str) -> Result<bool, OscError> {
        verify_address(address)?; // TODO: Create an address struct so we don't have to re-check addresses every time we match

        // Trivial case
        if address == self.pattern {
            return Ok(true);
        }
        let mut remainder: &str = address;
        // Match the the address component by component
        for (index, part) in self.pattern_parts.as_slice().iter().enumerate() {
            let result = match part {
                AddressPatternComponent::Tag(s) => match_literally(remainder, s.as_str()),
                AddressPatternComponent::WildcardSingle => match_wildcard_single(remainder),
                AddressPatternComponent::Wildcard(l) => {
                    // Check if this is the last pattern component
                    if index < self.pattern_parts.len() - 1 {
                        let next = &self.pattern_parts[index + 1];
                        match next {
                            // If the next component is a '/', there are no more components in the current part and it can be wholly consumed
                            AddressPatternComponent::Tag(s) if s == "/" => {
                                match_wildcard(remainder, *l, None)
                            }
                            _ => match_wildcard(remainder, *l, Some(next)),
                        }
                    } else {
                        match_wildcard(remainder, *l, None)
                    }
                }
                AddressPatternComponent::CharacterClass(cc) => match_character_class(remainder, cc),
                AddressPatternComponent::Choice(s) => match_choice(remainder, s),
            };

            match result {
                Ok((i, _)) => remainder = i,
                Err(_) => return Ok(false), // Component didn't match, goodbye
            };
        }

        // Address is only matched if it was consumed entirely
        Ok(remainder.is_empty())
    }
}

/// Check whether a character is an allowed address character
/// All printable ASCII characters except for a few special characters are allowed
fn is_address_character(x: char) -> bool {
    match x {
        ' ' | '#' | '*' | ',' | '/' | '?' | '[' | ']' | '{' | '}' => false,
        c => c > '\x20' && c < '\x7F',
    }
}

/// Parser to turn a choice like '{foo,bar}' into a vector containing the choices, like ["foo", "bar"]
fn pattern_choice(input: &str) -> IResult<&str, Vec<&str>> {
    delimited(
        char('{'),
        separated_list1(tag(","), take_while1(is_address_character)),
        char('}'),
    )(input)
}

/// Parser to recognize a character class like [!a-zA-Z] and return '!a-zA-Z'
fn pattern_character_class(input: &str) -> IResult<&str, &str> {
    let inner = pair(
        // It is important to read the leading negating '!' to make sure the rest of the parsed
        // character class isn't empty. E.g. '[!]' is not a valid character class.
        recognize(opt(tag("!"))),
        take_while1(is_address_character),
    );

    delimited(char('['), recognize(inner), char(']'))(input)
}

/// A characters class is defined by a set or range of characters that it matches.
/// For example, [a-z] matches all lowercase alphabetic letters. It can also contain multiple
/// ranges, like [a-zA-Z]. Instead of a range you can also directly provide the characters to match,
/// e.g. [abc123]. You can also combine this with ranges, like [a-z123].
/// If the first characters is an exclamation point, the match is negated, e.g. [!0-9] will match
/// anything except numbers.
#[derive(Debug)]
struct CharacterClass {
    pub negated: bool,
    pub characters: String,
}

/// Expand a character range like 'a-d' to all the letters contained in the range, e.g. 'abcd'
/// This is done by converting the characters to their ASCII values and then getting every ASCII
/// in between.
fn expand_character_range(first: char, second: char) -> String {
    let start = first as u8;
    let end = second as u8;

    let range = if start >= end {
        end..=start
    } else {
        start..=end
    };

    range
        .into_iter()
        .map(char::from)
        .filter(|c| is_address_character(*c))
        .collect()
}

impl CharacterClass {
    pub fn new(s: &str) -> Self {
        let mut input = s;
        let negated;
        match char::<_, nom::error::Error<&str>>('!')(input) {
            Ok((i, _)) => {
                negated = true;
                input = i;
            }
            Err(_) => negated = false,
        }

        let characters = complete(many1(alt((
            // '!' besides at beginning has no special meaning, but is legal
            char::<_, nom::error::Error<&str>>('!').map(|_| String::from("")),
            // attempt to match a range like a-z or 0-9
            separated_pair(
                satisfy(is_address_character),
                char('-'),
                satisfy(is_address_character),
            )
            .map(|(first, second)| expand_character_range(first, second)),
            // Match characters literally
            satisfy(is_address_character).map(|x| x.to_string()),
            // Trailing dash
            char('-').map(|_| String::from("-")),
        ))))(input);

        match characters {
            Ok((_, o)) => CharacterClass {
                negated,
                characters: HashSet::<char>::from_iter(o.concat().chars()).iter().collect(),
            },
            _ => {
                panic!("Invalid character class formatting {}", s)
            }
        }
    }
}

#[derive(Debug)]
enum AddressPatternComponent {
    Tag(String),
    Wildcard(usize),
    WildcardSingle,
    CharacterClass(CharacterClass),
    Choice(Vec<String>),
}

fn map_address_pattern_component(input: &str) -> IResult<&str, AddressPatternComponent> {
    alt((
        // Anything that's alphanumeric gets matched literally
        take_while1(is_address_character)
            .map(|s: &str| AddressPatternComponent::Tag(String::from(s))),
        // Slashes must be seperated into their own tag for the non-greedy implementation of wildcards
        char('/').map(|c: char| AddressPatternComponent::Tag(c.to_string())),
        tag("?").map(|_| AddressPatternComponent::WildcardSingle),
        // Combinations of wildcards are a bit tricky.
        // Multiple '*' wildcards in a row are equal to a single '*'.
        // A '*' wildcard followed by any number of '?' wildcards is also equal to '*' but must
        // match at least the same amount of characters as there are '?' wildcards in the combination.
        // For example, '*??' must match at least 2 characters.
        is_a("*?").map(|x: &str| AddressPatternComponent::Wildcard(x.matches('?').count())),
        pattern_choice.map(|choices: Vec<&str>| {
            AddressPatternComponent::Choice(choices.iter().map(|x| x.to_string()).collect())
        }),
        pattern_character_class
            .map(|s: &str| AddressPatternComponent::CharacterClass(CharacterClass::new(s))),
    ))(input)
}

fn match_literally<'a>(input: &'a str, pattern: &str) -> IResult<&'a str, &'a str> {
    tag(pattern)(input)
}

fn match_wildcard_single(input: &str) -> IResult<&str, &str> {
    // TODO: this has to be possible with a simpler parser?
    verify(take(1usize), |s: &str| s.chars().all(is_address_character))(input)
}

fn match_character_class<'a>(
    input: &'a str,
    character_class: &'a CharacterClass,
) -> IResult<&'a str, &'a str> {
    if character_class.negated {
        is_not(character_class.characters.as_str())(input)
    } else {
        is_a(character_class.characters.as_str())(input)
    }
}

/// Sequentially try all tags from choice element until one matches or return an error
/// Example choice element: '{foo,bar}'
/// It will get parsed into a vector containing the strings "foo" and "bar", which are then matched
fn match_choice<'a>(input: &'a str, choices: &[String]) -> IResult<&'a str, &'a str> {
    for choice in choices {
        if let Ok((i, o)) = tag::<_, _, nom::error::Error<&str>>(choice.as_str())(input) {
            return Ok((i, o));
        }
    }
    Err(nom::Err::Error(nom::error::Error::from_error_kind(
        input,
        ErrorKind::Tag,
    )))
}

/// Match Wildcard '*' by either consuming the rest of the part, or, if it's not the last component
/// in the part, by looking ahead and matching the next component
fn match_wildcard<'a>(
    input: &'a str,
    minimum_length: usize,
    next: Option<&AddressPatternComponent>,
) -> IResult<&'a str, &'a str> {
    match next {
        // No next component, consume all allowed characters until end or next '/'
        None => verify(take_while1(is_address_character), |s: &str| {
            s.len() >= minimum_length
        })(input),
        // There is another element in this part, so logic gets a bit more complicated
        Some(component) => {
            // Wildcards can only match within the current address part, discard the rest
            let address_part = match input.split_once('/') {
                Some((p, _)) => p,
                None => input,
            };

            // Attempt to find the latest matching occurrence of the next pattern component
            // This is a greedy wildcard implementation
            let mut longest: usize = 0;
            for i in 0..address_part.len() {
                let (_, substring) = input.split_at(i);
                let result: IResult<_, _, nom::error::Error<&str>> = match component {
                    AddressPatternComponent::Tag(s) => match_literally(substring, s.as_str()),
                    AddressPatternComponent::CharacterClass(cc) => {
                        match_character_class(substring, cc)
                    }
                    AddressPatternComponent::Choice(s) => match_choice(substring, s),
                    // These two cases are prevented from happening by map_address_pattern_component
                    AddressPatternComponent::WildcardSingle => {
                        panic!("Single wildcard ('?') must not follow wildcard ('*')")
                    }
                    AddressPatternComponent::Wildcard(_) => {
                        panic!("Double wildcards must be condensed into one")
                    }
                };

                if result.is_ok() {
                    longest = i
                }
            }
            verify(take(longest), |s: &str| s.len() >= minimum_length)(input)
        }
    }
}

/// Verify that an address is valid
///
/// # Examples
/// ```
/// use rosc::address::verify_address;
///
/// match verify_address("/oscillator/1") {
///     Ok(()) => println!("Address is valid"),
///     Err(e) => println!("Address is not valid")
/// }
/// ```
pub fn verify_address(input: &str) -> Result<(), OscError> {
    match all_consuming::<_, _, nom::error::Error<&str>, _>(many1(pair(
        tag("/"),
        take_while1(is_address_character),
    )))(input)
    {
        Ok(_) => Ok(()),
        Err(_) => Err(OscError::BadAddress("Invalid address".to_string())),
    }
}

/// Parse an address pattern's part until the next '/' or the end
fn address_pattern_part_parser(input: &str) -> IResult<&str, Vec<&str>> {
    many1::<_, _, nom::error::Error<&str>, _>(alt((
        take_while1(is_address_character),
        tag("?"),
        tag("*"),
        recognize(pattern_choice),
        pattern_character_class,
    )))(input)
}

/// Verify that an address pattern is valid
///
/// # Examples
/// ```
/// use rosc::address::verify_address_pattern;
///
/// match verify_address_pattern("/oscillator/[0-9]/*") {
///     Ok(()) => println!("Address is valid"),
///     Err(e) => println!("Address is not valid")
/// }
/// ```
pub fn verify_address_pattern(input: &str) -> Result<(), OscError> {
    match all_consuming(many1(
        // Each part must start with a '/'. This automatically also prevents a trailing '/'
        pair(tag("/"), address_pattern_part_parser.map(|x| x.concat())),
    ))(input)
    {
        Ok(_) => Ok(()),
        Err(_) => Err(OscError::BadAddress("Invalid address pattern".to_string())),
    }
}
<|endoftext|>


<commit_before>use ffmpeg_sys;
use std::ffi::{ CStr, CString };

use errors::*;

pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats<'a> {
    codec: &'a Codec,
    index: isize,
}

impl Codec {
    pub fn description(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    pub fn kind(&self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    pub fn is_video(&self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats<'a>(&'a self) -> Option<PixelFormats<'a>> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(&self))
            }
        }
    }
}

impl<'a> PixelFormats<'a> {
    fn new(codec: &'a Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl<'a> Iterator for PixelFormats<'a> {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<commit_msg>Make Codec Clone and Copy<commit_after>use ffmpeg_sys;
use std::ffi::{ CStr, CString };

use errors::*;

#[derive(Clone, Copy)]
pub struct Codec {
    ptr: *mut ffmpeg_sys::AVCodec,
}

unsafe impl Send for Codec {}
unsafe impl Sync for Codec {}

pub struct PixelFormats {
    codec: Codec,
    index: isize,
}

impl Codec {
    pub fn description(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.ptr).long_name).to_string_lossy().into_owned()
        }
    }

    pub fn kind(&self) -> ffmpeg_sys::AVMediaType {
        unsafe {
            (*self.ptr).kind
        }
    }

    pub fn is_video(&self) -> bool {
        self.kind() == ffmpeg_sys::AVMediaType::AVMEDIA_TYPE_VIDEO
    }

    pub fn pixel_formats(&self) -> Option<PixelFormats> {
        unsafe {
            if (*self.ptr).pix_fmts.is_null() {
                None
            } else {
                Some(PixelFormats::new(*self))
            }
        }
    }
}

impl PixelFormats {
    fn new(codec: Codec) -> Self {
        Self {
            codec,
            index: 0,
        }
    }
}

impl Iterator for PixelFormats {
    type Item = ffmpeg_sys::AVPixelFormat;

    fn next(&mut self) -> Option<Self::Item> {
        let format = unsafe {
            *(*self.codec.ptr).pix_fmts.offset(self.index)
        };

        if format == ffmpeg_sys::AVPixelFormat::AV_PIX_FMT_NONE {
            None
        } else {
            self.index += 1;
            Some(format)
        }
    }
}

pub fn initialize() {
    unsafe {
        ffmpeg_sys::avcodec_register_all();
    }
}

pub fn find_encoder_by_name(name: &str) -> Result<Option<Codec>> {
    let name = CString::new(name).chain_err(|| "could not convert name to CString")?;

    let codec = unsafe {
        ffmpeg_sys::avcodec_find_encoder_by_name(name.as_ptr())
    };

    if codec.is_null() {
        Ok(None)
    } else {
        Ok(Some(Codec { ptr: codec }))
    }
}
<|endoftext|>


<commit_before>extern crate cc;
use cc::ToolFamily::*;

fn main() {
    let mut build = cc::Build::new();
    build.cpp(true);
    let compiler = build.try_get_compiler();
    if compiler.is_ok() && compiler.unwrap().family == Clang {
        build.flag_if_supported("-std=c++11").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }
    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_glsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_msl.cpp")
        .compile("spirv-cross-rust-wrapper");
}
<commit_msg>Temporarily force C++11 for Clang<commit_after>extern crate cc;
use cc::ToolFamily::*;

fn main() {
    let mut build = cc::Build::new();
    build.cpp(true);
    let compiler = build.try_get_compiler();
    if compiler.is_ok() && compiler.unwrap().family == Clang {
        build.flag("-std=c++11").cpp_set_stdlib("c++");
    } else {
        build.flag_if_supported("-std=c++14");
    }
    build
        .file("src/wrapper.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cfg.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_cross.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_glsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_hlsl.cpp")
        .file("src/vendor/SPIRV-Cross/spirv_msl.cpp")
        .compile("spirv-cross-rust-wrapper");
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(gtk_3_10), allow(unused_imports))]

use libc::{c_char, c_long};

use glib::{self, types};
use glib::translate::*;
use ffi;

use object::{Object, Downcast, Upcast};

pub type Buildable = Object<ffi::GtkBuildable>;

impl types::StaticType for Buildable {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_buildable_get_type()) }
    }
}

pub type Builder = Object<ffi::GtkBuilder>;

impl Builder {
    pub fn new() -> Builder {
        unsafe { from_glib_full(ffi::gtk_builder_new()) }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_file(file_name: &str) -> Builder {
        unsafe { from_glib_full(ffi::gtk_builder_new_from_file(file_name.to_glib_none().0)) }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_resource(resource_path: &str) -> Builder {
        unsafe {
            from_glib_full(ffi::gtk_builder_new_from_resource(resource_path.to_glib_none().0))
        }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_string(string: &str) -> Builder {
        unsafe {
            // Don't need a null-terminated string here
            from_glib_full(
                ffi::gtk_builder_new_from_string(string.as_ptr() as *const c_char,
                    string.len() as c_long))
        }
    }

    pub fn get_object<T>(&self, name: &str) -> Option<T>
    where T: Upcast<Buildable> + Upcast<glib::object::Object> {
        unsafe {
            Option::<glib::object::Object>::from_glib_none(
                ffi::gtk_builder_get_object(self.to_glib_none().0, name.to_glib_none().0))
                .and_then(|obj| obj.downcast().ok())
        }
    }
}

impl types::StaticType for Builder {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_builder_get_type()) }
    }
}
<commit_msg>Fix win64 build after the last merge<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#![cfg_attr(not(gtk_3_10), allow(unused_imports))]

use libc::{c_char, ssize_t};

use glib::{self, types};
use glib::translate::*;
use ffi;

use object::{Object, Downcast, Upcast};

pub type Buildable = Object<ffi::GtkBuildable>;

impl types::StaticType for Buildable {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_buildable_get_type()) }
    }
}

pub type Builder = Object<ffi::GtkBuilder>;

impl Builder {
    pub fn new() -> Builder {
        unsafe { from_glib_full(ffi::gtk_builder_new()) }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_file(file_name: &str) -> Builder {
        unsafe { from_glib_full(ffi::gtk_builder_new_from_file(file_name.to_glib_none().0)) }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_resource(resource_path: &str) -> Builder {
        unsafe {
            from_glib_full(ffi::gtk_builder_new_from_resource(resource_path.to_glib_none().0))
        }
    }

    #[cfg(gtk_3_10)]
    pub fn new_from_string(string: &str) -> Builder {
        unsafe {
            // Don't need a null-terminated string here
            from_glib_full(
                ffi::gtk_builder_new_from_string(string.as_ptr() as *const c_char,
                    string.len() as ssize_t))
        }
    }

    pub fn get_object<T>(&self, name: &str) -> Option<T>
    where T: Upcast<Buildable> + Upcast<glib::object::Object> {
        unsafe {
            Option::<glib::object::Object>::from_glib_none(
                ffi::gtk_builder_get_object(self.to_glib_none().0, name.to_glib_none().0))
                .and_then(|obj| obj.downcast().ok())
        }
    }
}

impl types::StaticType for Builder {
    #[inline]
    fn static_type() -> types::Type {
        unsafe { from_glib(ffi::gtk_builder_get_type()) }
    }
}
<|endoftext|>


<commit_before>use core::mem::transmute;
use core::ptr::{set_memory, copy_memory, offset};
use core::i32::ctlz32;
use core::fail::out_of_memory;

use kernel::ptr::mut_offset;

#[repr(u8)]
enum Node {
    UNUSED = 0,
    USED = 1,
    SPLIT = 2,
    FULL = 3
}

pub trait Allocator {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint);

    fn zero_alloc(&mut self, s: uint) -> (*mut u8, uint) {
        let (ptr, size) = self.alloc(s);
        unsafe { set_memory(ptr, 0, size); }
        (ptr, size)
    }

    fn realloc(&mut self, src: *mut u8, size: uint) -> (*mut u8, uint) {
        self.free(src);
        let (ptr, sz) = self.alloc(size);
        unsafe { copy_memory(ptr, src as *u8, sz); }
        (ptr, sz)
    }

    fn free(&mut self, ptr: *mut u8);
}

trait BitvTrait {
    fn get(&self, i: uint) -> Node;
    fn set(&self, i: uint, x: Node);
    fn to_bytes(&self) -> *mut u8;
    fn size(&self) -> uint;
}

static BITV_SIZE: uint = 0x10_000;
pub type BitvStorage = *mut [u32, ..BITV_SIZE / 4];

// vector of 2-bit
pub struct Bitv {
    storage: BitvStorage
}

impl BitvTrait for Bitv {
    #[inline]
    fn get(&self, i: uint) -> Node {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { transmute(((*self.storage)[w] as uint >> b) as u8 & 3) }
    }

    #[inline]
    fn set(&self, i: uint, x: Node) {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe { (*self.storage)[w] = (((*self.storage)[w] & !(3 << b)) | (x as u32 << b)); }
    }

    #[inline]
    fn to_bytes(&self) -> *mut u8 {
        self.storage as *mut u8
    }

    #[inline]
    fn size(&self) -> uint {
        BITV_SIZE
    }
}

pub struct BuddyAlloc {
    order: uint,
    tree: Bitv
}

pub struct Alloc {
    parent: BuddyAlloc,
    base: *mut u8,
    el_size: uint
}

impl BuddyAlloc {
    pub fn new(order: uint, storage: Bitv) -> BuddyAlloc {
        unsafe { set_memory(storage.to_bytes(), 0, storage.size()); }

        BuddyAlloc { order: order, tree: storage }
    }

    #[inline]
    fn offset(&self, index: uint, level: uint) -> uint {
        /* unsafe { - unnecessary */
            (index + 1 - (1 << (self.order - level))) << level
        /* } */
    }

    fn alloc(&mut self, mut size: uint) -> (uint, uint) {
        if size == 0 {
            size = 1;
        }
        // smallest power of 2 >= size
        let lg2_size = 32 - unsafe { ctlz32(size as i32 - 1) } as uint;

        let mut index = 0; // points to current tree node
        let mut level = self.order; // current height

        loop {
            match (self.tree.get(index), level == lg2_size) {
                (UNUSED, true) => {
                    // Found appropriate unused node
                    self.tree.set(index, USED); // use

                    let mut parent = index;
                    loop {
                        let buddy = parent - 1 + (parent & 1) * 2;
                        match self.tree.get(buddy) {
                            USED | FULL if parent > 0 => {
                                parent = (parent + 1) / 2 - 1;
                                self.tree.set(parent, FULL);
                            }
                            _ => break
                        }
                    }
                    return (
                        self.offset(index, level),
                        1 << lg2_size
                    );
                }
                (UNUSED, false) => {
                    // This large node is unused, split it!
                    self.tree.set(index, SPLIT);
                    self.tree.set(index*2 + 1, UNUSED);
                    self.tree.set(index*2 + 2, UNUSED);
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                (SPLIT, false) => {
                    // Traverse children
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                _ => loop {
                    // Go either right or back up
                    if index & 1 == 1 {
                        // right sibling
                        index += 1;
                        break;
                    }

                    // go up by one level
                    level += 1;

                    if index == 0 {
                        // out of memory -- back at tree's root after traversal
			out_of_memory();
                        return (0, 0);
                    }

                    index = (index + 1) / 2 - 1; // parent
                }
            }
        }
    }

    fn free(&mut self, offset: uint) {
        let mut length = 1 << self.order;
        let mut left = 0;
        let mut index = 0;

        loop {
            match self.tree.get(index) {
                UNUSED => return,
                USED => self.tree.set(index, UNUSED),
                _ => {
                    length /= 2;
                    if offset < left + length {
                        index = index * 2 + 1; // left child
                    }
                    else {
                        left += length;
                        index = index * 2 + 2; // right child
                    }
                }
            }
        }
    }
}

impl Allocator for Alloc {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint) {
        let (offset, size) = self.parent.alloc(size);
        unsafe {
            return (
                mut_offset(self.base, (offset << self.el_size) as int),
                size << self.el_size
            )
        }
    }

    fn free(&mut self, ptr: *mut u8) {
        let length = 1 << self.parent.order << self.el_size;

        unsafe {
            if ptr < self.base || ptr >= mut_offset(self.base, length) {
                return;
            }
        }

        let offset = (ptr as uint - self.base as uint) >> self.el_size;
        self.parent.free(offset);
    }
}
<commit_msg>closes #8: rejoin split blocks when empty<commit_after>use core::mem::transmute;
use core::ptr::{set_memory, copy_memory, offset};
use core::i32::ctlz32;
use core::fail::out_of_memory;

use kernel::ptr::mut_offset;

#[repr(u8)]
enum Node {
    UNUSED = 0,
    USED = 1,
    SPLIT = 2,
    FULL = 3
}

pub trait Allocator {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint);

    fn zero_alloc(&mut self, s: uint) -> (*mut u8, uint) {
        let (ptr, size) = self.alloc(s);
        unsafe { set_memory(ptr, 0, size); }
        (ptr, size)
    }

    fn realloc(&mut self, src: *mut u8, size: uint) -> (*mut u8, uint) {
        self.free(src);
        let (ptr, sz) = self.alloc(size);
        unsafe { copy_memory(ptr, src as *u8, sz); }
        (ptr, sz)
    }

    fn free(&mut self, ptr: *mut u8);
}

trait BitvTrait {
    fn get(&self, i: uint) -> Node;
    fn set(&self, i: uint, x: Node);
    fn to_bytes(&self) -> *mut u8;
    fn size(&self) -> uint;
}

static BITV_SIZE: uint = 0x10_000;
pub type BitvStorage = *mut [u32, ..BITV_SIZE / 4];

// vector of 2-bit
pub struct Bitv {
    storage: BitvStorage
}

impl BitvTrait for Bitv {
    #[inline]
    fn get(&self, i: uint) -> Node {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe {
            transmute(((*self.storage)[w] as uint >> b) as u8 & 3)
        }
    }

    #[inline]
    fn set(&self, i: uint, x: Node) {
        let w = i / 16;
        let b = (i % 16) * 2;
        unsafe {
            (*self.storage)[w] = (((*self.storage)[w] & !(3 << b)) | (x as u32 << b));
        }
    }

    #[inline]
    fn to_bytes(&self) -> *mut u8 {
        self.storage as *mut u8
    }

    #[inline]
    fn size(&self) -> uint {
        BITV_SIZE
    }
}

pub struct BuddyAlloc {
    order: uint,
    tree: Bitv
}

pub struct Alloc {
    parent: BuddyAlloc,
    base: *mut u8,
    el_size: uint
}

impl BuddyAlloc {
    pub fn new(order: uint, storage: Bitv) -> BuddyAlloc {
        unsafe { set_memory(storage.to_bytes(), 0, storage.size()); }

        BuddyAlloc { order: order, tree: storage }
    }

    #[inline]
    fn offset(&self, index: uint, level: uint) -> uint {
        /* unsafe { - unnecessary */
            (index + 1 - (1 << (self.order - level))) << level
        /* } */
    }

    fn lg2_size(self, size: uint) -> uint {
        32 - unsafe { ctlz32(size as i32 - 1) } as uint
    }

    fn alloc(&mut self, mut size: uint) -> (uint, uint) {
        if size == 0 {
            size = 1;
        }
        // smallest power of 2 >= size
        let lg2_size = self.lg2_size(size);

        let mut index = 0; // points to current tree node
        let mut level = self.order; // current height

        loop {
            match (self.tree.get(index), level == lg2_size) {
                (UNUSED, true) => {
                    // Found appropriate unused node
                    self.tree.set(index, USED); // use

                    let mut parent = index;
                    loop {
                        let buddy = parent - 1 + (parent & 1) * 2;
                        match self.tree.get(buddy) {
                            USED | FULL if parent > 0 => {
                                parent = (parent + 1) / 2 - 1;
                                self.tree.set(parent, FULL);
                            }
                            _ => break
                        }
                    }
                    return (
                        self.offset(index, level),
                        1 << lg2_size
                    );
                }
                (UNUSED, false) => {
                    // This large node is unused, split it!
                    self.tree.set(index, SPLIT);
                    self.tree.set(index*2 + 1, UNUSED);
                    self.tree.set(index*2 + 2, UNUSED);
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                (SPLIT, false) => {
                    // Traverse children
                    index = index * 2 + 1; // left child
                    level -= 1;
                }
                _ => loop {
                    // Go either right or back up
                    if index & 1 == 1 {
                        // right sibling
                        index += 1;
                        break;
                    }

                    // go up by one level
                    level += 1;

                    if index == 0 {
                        // out of memory -- back at tree's root after traversal
                    out_of_memory();
                        return (0, 0);
                    }

                    index = (index + 1) / 2 - 1; // parent
                }
            }
        }
    }

    fn free(&mut self, offset: uint) {
        let mut length = 1 << self.order;
        let mut left = 0;
        let mut index = 0;
        let mut order = self.order; // current height
        loop {
            match self.tree.get(index) {
                UNUSED => {
                    return
                },
                USED => {
                    // Free *this* block.
                    self.tree.set(index, UNUSED);

                    // Check for buddy block to free.
                    let mut parent = index;
                    loop {
                        let buddy = parent - 1 + (parent & 1) * 2;
                        match self.tree.get(buddy) {
                            UNUSED if parent > 0 => {
                                // Go up one, free the parent, check the
                                // parent's buddy. Repeat until we don't have
                                // an empty split block above us.
                                parent = (parent + 1) / 2 - 1;
                                self.tree.set(parent, UNUSED);
                            }
                            _ => break
                        }
                    }
                },
                _ => {
                    length /= 2;
                    if offset < left + length {
                        index = index * 2 + 1; // left child
                    }
                    else {
                        left += length;
                        index = index * 2 + 2; // right child
                    }
                }
            }
        }
    }
}

impl Allocator for Alloc {
    fn alloc(&mut self, size: uint) -> (*mut u8, uint) {
        let (offset, size) = self.parent.alloc(size);
        unsafe {
            return (
                mut_offset(self.base, (offset << self.el_size) as int),
                size << self.el_size
            )
        }
    }

    fn free(&mut self, ptr: *mut u8) {
        let length = 1 << self.parent.order << self.el_size;

        unsafe {
            if ptr < self.base || ptr >= mut_offset(self.base, length) {
                return;
            }
        }

        let offset = (ptr as uint - self.base as uint) >> self.el_size;
        self.parent.free(offset);
    }
}
<|endoftext|>


<commit_before>extern crate chrono;

use chrono::prelude::*;
use regex::Regex;

#[derive(Debug)]
pub enum Command {
    BadCommand,
    OneTimeEvent(OneTimeEventImpl),
}

#[derive(Debug)]
pub struct OneTimeEventImpl{
    pub event_time : DateTime<Utc>,
    pub event_text : String,
}

pub fn parse_command(command_line : String) -> Command {
    debug!("parse incoming text: {}", command_line);
    let reg_main    = Regex::new(r"(?P<spec>[\d\w]*)(?P<divider> )(?P<main_text>.*)").unwrap();

    let reg_day     = r"(?P<days>[\d]*)[D|d|Д|д]";
    let reg_hour    = r"(?P<hours>[\d]*)[H|h|Ч|ч]";
    let reg_min     = r"(?P<minuts>[\d]*)[M|m|М|м]";
    let reg_sec     = r"(?P<seconds>[\d]*)[S|s|С|с]";

    let caps = reg_main.captures(&command_line);
    if caps.is_none() {
        warn!("parse_command: incoming text doesn't match main regex");
        return Command::BadCommand;
    }
    let caps = caps.unwrap();
    let spec = caps.name("spec").unwrap().as_str();
    let text = caps.name("main_text").unwrap().as_str();

    let days    = get_first_regex_group_as_u32(reg_day,  spec);
    let hours   = get_first_regex_group_as_u32(reg_hour, spec);
    let minutes = get_first_regex_group_as_u32(reg_min,  spec);
    let seconds = get_first_regex_group_as_u32(reg_sec,  spec);

    if days == 0 && hours == 0 && minutes == 0 && seconds == 0 {
        warn!("parse_command: incoming text doesn't match main regex");
        return Command::BadCommand;
    }

    // TODO: should we a better way to do this
    let dt = chrono::Duration::seconds((days as i64) * (60*60*24)
                                    + (hours as i64) * (60*60)
                                    + (minutes as i64) * 60
                                    + (seconds as i64)
                                    );

    let event_time = Utc::now() + dt;

    Command::OneTimeEvent(OneTimeEventImpl
            { event_text : String::from(text)
            , event_time : event_time }
        )
}

fn get_first_regex_group_as_u32(reg : &str, text : &str) -> u32{
    let reg = Regex::new(reg).expect("get_first_regex_group_as_u32: wrong regex string");
    let number = match reg.captures(text){
        None => "0",
        Some(d) => d.get(1)
            .expect("get_first_regex_group_as_u32: expect regex string with at least 1 group")
            .as_str(),
    };
    number.parse().unwrap_or(0)
}
<commit_msg>Add <at> command. First version<commit_after>extern crate chrono;

use chrono::prelude::*;
use regex::{Regex, Captures};

#[derive(Debug)]
pub enum Command {
    BadCommand,
    OneTimeEvent(OneTimeEventImpl),
}

#[derive(Debug)]
pub struct OneTimeEventImpl{
    pub event_time : DateTime<Utc>,
    pub event_text : String,
}

pub fn parse_command(command_line : String) -> Command {
    let command_line = String::from(command_line.trim());
    debug!("parse incoming text: {}", command_line);
    let mut result;
    result = try_parse_for(&command_line);
    if result.is_some() {
        return result.unwrap();
    }

    result = try_parse_at(&command_line);
    if result.is_some() {
        return result.unwrap();
    }
    Command::BadCommand
}

fn try_parse_at(command_line : &String) -> Option<Command>{
    let time_format = Regex::new(r"[at|в]\s*(?P<day>[\d]*)(?:-(?P<month>[\d]*))?(?:-(?P<year>[\d]*))? (?P<hour>[\d]*).(?P<minute>[\d]*) (?P<main_text>.*)").unwrap();

    let date_captures = time_format.captures(command_line);
    if date_captures.is_none() {
        warn!("parse_command: line {} doesn't match time_format regex", command_line);
        return None;
    }

    let date_captures = date_captures.unwrap();

    let text = date_captures.name("main_text").unwrap().as_str();
    let d = get_datetime_from_capture(&date_captures);

    Some(Command::OneTimeEvent(OneTimeEventImpl
            { event_text : String::from(text)
            , event_time : d }
        ))
}

fn try_parse_for(command_line : &String) -> Option<Command>{
    let reg_main    = Regex::new(r"(?P<spec>[\d\w]*)(?P<divider> )(?P<main_text>.*)").unwrap();

    let reg_day     = r"(?P<days>[\d]*)[D|d|Д|д]";
    let reg_hour    = r"(?P<hours>[\d]*)[H|h|Ч|ч]";
    let reg_min     = r"(?P<minuts>[\d]*)[M|m|М|м]";
    let reg_sec     = r"(?P<seconds>[\d]*)[S|s|С|с]";

    let caps = reg_main.captures(command_line);
    if caps.is_none() {
        warn!("parse_command: incoming text doesn't match main regex");
        return None;
    }
    let caps = caps.unwrap();
    let spec = caps.name("spec").unwrap().as_str();
    let text = caps.name("main_text").unwrap().as_str();

    let days    = get_first_regex_group_as_u32(reg_day,  spec);
    let hours   = get_first_regex_group_as_u32(reg_hour, spec);
    let minutes = get_first_regex_group_as_u32(reg_min,  spec);
    let seconds = get_first_regex_group_as_u32(reg_sec,  spec);

    if days == 0 && hours == 0 && minutes == 0 && seconds == 0 {
        warn!("parse_command: incoming text doesn't match main regex");
        return None;
    }

    // TODO: should we a better way to do this
    let dt = chrono::Duration::seconds((days as i64) * (60*60*24)
                                    + (hours as i64) * (60*60)
                                    + (minutes as i64) * 60
                                    + (seconds as i64)
                                    );

    let event_time = Utc::now() + dt;

    Some(Command::OneTimeEvent(OneTimeEventImpl
            { event_text : String::from(text)
            , event_time : event_time }
        ))
}

fn get_first_regex_group_as_u32(reg : &str, text : &str) -> u32{
    let reg = Regex::new(reg).expect("get_first_regex_group_as_u32: wrong regex string");
    let number = match reg.captures(text){
        None => "0",
        Some(d) => d.get(1)
            .expect("get_first_regex_group_as_u32: expect regex string with at least 1 group")
            .as_str(),
    };
    number.parse().unwrap_or(0)
}

fn get_datetime_from_capture(cap: &Captures) -> DateTime<Utc>{
    let day = cap.name("day").unwrap().as_str().parse().unwrap();
    let hour = cap.name("hour").unwrap().as_str().parse().unwrap();
    let minute = cap.name("minute").unwrap().as_str().parse().unwrap();

    let now = Utc::now();

    let month = match cap.name("month"){
        None => now.month(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    let year = match cap.name("year"){
        None => now.year(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    const DEFAULT_TZ : i64 = -3;
    let dt = chrono::Duration::seconds(DEFAULT_TZ * 60 * 60);

    Utc.ymd(year, month, day).and_hms(hour, minute, 0) + dt
}
<|endoftext|>