<commit_before>use crate::core::shell::Verbosity;
use crate::core::{GitReference, Workspace};
use crate::ops;
use crate::sources::path::PathSource;
use crate::sources::CRATES_IO_REGISTRY;
use crate::util::{CargoResult, Config};
use anyhow::{bail, Context as _};
use cargo_util::{paths, Sha256};
use serde::Serialize;
use std::collections::HashSet;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fs::{self, File, OpenOptions};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use toml_edit::easy as toml;

pub struct VendorOptions<'a> {
    pub no_delete: bool,
    pub versioned_dirs: bool,
    pub destination: &'a Path,
    pub extra: Vec<PathBuf>,
}

pub fn vendor(ws: &Workspace<'_>, opts: &VendorOptions<'_>) -> CargoResult<()> {
    let config = ws.config();
    let mut extra_workspaces = Vec::new();
    for extra in opts.extra.iter() {
        let extra = config.cwd().join(extra);
        let ws = Workspace::new(&extra, config)?;
        extra_workspaces.push(ws);
    }
    let workspaces = extra_workspaces.iter().chain(Some(ws)).collect::<Vec<_>>();
    let vendor_config = sync(config, &workspaces, opts).with_context(|| "failed to sync")?;

    if config.shell().verbosity() != Verbosity::Quiet {
        if vendor_config.source.is_empty() {
            crate::drop_eprintln!(config, "There is no dependency to vendor in this project.");
        } else {
            crate::drop_eprint!(
                config,
                "To use vendored sources, add this to your .cargo/config.toml for this project:\n\n"
            );
            crate::drop_print!(
                config,
                "{}",
                &toml::to_string_pretty(&vendor_config).unwrap()
            );
        }
    }

    Ok(())
}

#[derive(Serialize)]
struct VendorConfig {
    source: BTreeMap<String, VendorSource>,
}

#[derive(Serialize)]
#[serde(rename_all = "lowercase", untagged)]
enum VendorSource {
    Directory {
        directory: PathBuf,
    },
    Registry {
        registry: Option<String>,
        #[serde(rename = "replace-with")]
        replace_with: String,
    },
    Git {
        git: String,
        branch: Option<String>,
        tag: Option<String>,
        rev: Option<String>,
        #[serde(rename = "replace-with")]
        replace_with: String,
    },
}

fn sync(
    config: &Config,
    workspaces: &[&Workspace<'_>],
    opts: &VendorOptions<'_>,
) -> CargoResult<VendorConfig> {
    let canonical_destination = opts.destination.canonicalize();
    let canonical_destination = canonical_destination.as_deref().unwrap_or(opts.destination);
    let dest_dir_already_exists = canonical_destination.exists();

    paths::create_dir_all(&canonical_destination)?;
    let mut to_remove = HashSet::new();
    if !opts.no_delete {
        for entry in canonical_destination.read_dir()? {
            let entry = entry?;
            if !entry
                .file_name()
                .to_str()
                .map_or(false, |s| s.starts_with('.'))
            {
                to_remove.insert(entry.path());
            }
        }
    }

    // First up attempt to work around rust-lang/cargo#5956. Apparently build
    // artifacts sprout up in Cargo's global cache for whatever reason, although
    // it's unsure what tool is causing these issues at this time. For now we
    // apply a heavy-hammer approach which is to delete Cargo's unpacked version
    // of each crate to start off with. After we do this we'll re-resolve and
    // redownload again, which should trigger Cargo to re-extract all the
    // crates.
    //
    // Note that errors are largely ignored here as this is a best-effort
    // attempt. If anything fails here we basically just move on to the next
    // crate to work with.
    for ws in workspaces {
        let (packages, resolve) =
            ops::resolve_ws(ws).with_context(|| "failed to load pkg lockfile")?;

        packages
            .get_many(resolve.iter())
            .with_context(|| "failed to download packages")?;

        for pkg in resolve.iter() {
            // Don't delete actual source code!
            if pkg.source_id().is_path() {
                if let Ok(path) = pkg.source_id().url().to_file_path() {
                    if let Ok(path) = path.canonicalize() {
                        to_remove.remove(&path);
                    }
                }
                continue;
            }
            if pkg.source_id().is_git() {
                continue;
            }
            if let Ok(pkg) = packages.get_one(pkg) {
                drop(fs::remove_dir_all(pkg.manifest_path().parent().unwrap()));
            }
        }
    }

    let mut checksums = HashMap::new();
    let mut ids = BTreeMap::new();

    // Next up let's actually download all crates and start storing internal
    // tables about them.
    for ws in workspaces {
        let (packages, resolve) =
            ops::resolve_ws(ws).with_context(|| "failed to load pkg lockfile")?;

        packages
            .get_many(resolve.iter())
            .with_context(|| "failed to download packages")?;

        for pkg in resolve.iter() {
            // No need to vendor path crates since they're already in the
            // repository
            if pkg.source_id().is_path() {
                continue;
            }
            ids.insert(
                pkg,
                packages
                    .get_one(pkg)
                    .with_context(|| "failed to fetch package")?
                    .clone(),
            );

            checksums.insert(pkg, resolve.checksums().get(&pkg).cloned());
        }
    }

    let mut versions = HashMap::new();
    for id in ids.keys() {
        let map = versions.entry(id.name()).or_insert_with(BTreeMap::default);
        if let Some(prev) = map.get(&id.version()) {
            bail!(
                "found duplicate version of package `{} v{}` \
                 vendored from two sources:\n\
                 \n\
                 \tsource 1: {}\n\
                 \tsource 2: {}",
                id.name(),
                id.version(),
                prev,
                id.source_id()
            );
        }
        map.insert(id.version(), id.source_id());
    }

    let mut sources = BTreeSet::new();
    let mut tmp_buf = [0; 64 * 1024];
    for (id, pkg) in ids.iter() {
        // Next up, copy it to the vendor directory
        let src = pkg
            .manifest_path()
            .parent()
            .expect("manifest_path should point to a file");
        let max_version = *versions[&id.name()].iter().rev().next().unwrap().0;
        let dir_has_version_suffix = opts.versioned_dirs || id.version() != max_version;
        let dst_name = if dir_has_version_suffix {
            // Eg vendor/futures-0.1.13
            format!("{}-{}", id.name(), id.version())
        } else {
            // Eg vendor/futures
            id.name().to_string()
        };

        sources.insert(id.source_id());
        let dst = canonical_destination.join(&dst_name);
        to_remove.remove(&dst);
        let cksum = dst.join(".cargo-checksum.json");
        if dir_has_version_suffix && cksum.exists() {
            // Always re-copy directory without version suffix in case the version changed
            continue;
        }

        config.shell().status(
            "Vendoring",
            &format!("{} ({}) to {}", id, src.to_string_lossy(), dst.display()),
        )?;

        let _ = fs::remove_dir_all(&dst);
        let pathsource = PathSource::new(src, id.source_id(), config);
        let paths = pathsource.list_files(pkg)?;
        let mut map = BTreeMap::new();
        cp_sources(src, &paths, &dst, &mut map, &mut tmp_buf)
            .with_context(|| format!("failed to copy over vendored sources for: {}", id))?;

        // Finally, emit the metadata about this package
        let json = serde_json::json!({
            "package": checksums.get(id),
            "files": map,
        });

        paths::write(&cksum, json.to_string())?;
    }

    for path in to_remove {
        if path.is_dir() {
            paths::remove_dir_all(&path)?;
        } else {
            paths::remove_file(&path)?;
        }
    }

    // add our vendored source
    let mut config = BTreeMap::new();

    let merged_source_name = "vendored-sources";

    // replace original sources with vendor
    for source_id in sources {
        let name = if source_id.is_default_registry() {
            CRATES_IO_REGISTRY.to_string()
        } else {
            source_id.url().to_string()
        };

        let source = if source_id.is_default_registry() {
            VendorSource::Registry {
                registry: None,
                replace_with: merged_source_name.to_string(),
            }
        } else if source_id.is_remote_registry() {
            let registry = source_id.url().to_string();
            VendorSource::Registry {
                registry: Some(registry),
                replace_with: merged_source_name.to_string(),
            }
        } else if source_id.is_git() {
            let mut branch = None;
            let mut tag = None;
            let mut rev = None;
            if let Some(reference) = source_id.git_reference() {
                match *reference {
                    GitReference::Branch(ref b) => branch = Some(b.clone()),
                    GitReference::Tag(ref t) => tag = Some(t.clone()),
                    GitReference::Rev(ref r) => rev = Some(r.clone()),
                    GitReference::DefaultBranch => {}
                }
            }
            VendorSource::Git {
                git: source_id.url().to_string(),
                branch,
                tag,
                rev,
                replace_with: merged_source_name.to_string(),
            }
        } else {
            panic!("Invalid source ID: {}", source_id)
        };
        config.insert(name, source);
    }

    if !config.is_empty() {
        config.insert(
            merged_source_name.to_string(),
            VendorSource::Directory {
                directory: opts.destination.to_path_buf(),
            },
        );
    } else if !dest_dir_already_exists {
        // Nothing to vendor. Remove the destination dir we've just created.
        paths::remove_dir(canonical_destination)?;
    }

    Ok(VendorConfig { source: config })
}

fn cp_sources(
    src: &Path,
    paths: &[PathBuf],
    dst: &Path,
    cksums: &mut BTreeMap<String, String>,
    tmp_buf: &mut [u8],
) -> CargoResult<()> {
    for p in paths {
        let relative = p.strip_prefix(&src).unwrap();

        match relative.to_str() {
            // Skip git config files as they're not relevant to builds most of
            // the time and if we respect them (e.g.  in git) then it'll
            // probably mess with the checksums when a vendor dir is checked
            // into someone else's source control
            Some(".gitattributes") | Some(".gitignore") | Some(".git") => continue,

            // Temporary Cargo files
            Some(".cargo-ok") => continue,

            // Skip patch-style orig/rej files. Published crates on crates.io
            // have `Cargo.toml.orig` which we don't want to use here and
            // otherwise these are rarely used as part of the build process.
            Some(filename) => {
                if filename.ends_with(".orig") || filename.ends_with(".rej") {
                    continue;
                }
            }
            _ => {}
        };

        // Join pathname components individually to make sure that the joined
        // path uses the correct directory separators everywhere, since
        // `relative` may use Unix-style and `dst` may require Windows-style
        // backslashes.
        let dst = relative
            .iter()
            .fold(dst.to_owned(), |acc, component| acc.join(&component));

        paths::create_dir_all(dst.parent().unwrap())?;

        let cksum = copy_and_checksum(p, &dst, tmp_buf)?;
        cksums.insert(relative.to_str().unwrap().replace("\\", "/"), cksum);
    }
    Ok(())
}

fn copy_and_checksum(src_path: &Path, dst_path: &Path, buf: &mut [u8]) -> CargoResult<String> {
    let mut src = File::open(src_path).with_context(|| format!("failed to open {:?}", src_path))?;
    let mut dst_opts = OpenOptions::new();
    dst_opts.write(true).create(true).truncate(true);
    #[cfg(unix)]
    {
        use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
        let src_metadata = src
            .metadata()
            .with_context(|| format!("failed to stat {:?}", src_path))?;
        dst_opts.mode(src_metadata.mode());
    }
    let mut dst = dst_opts
        .open(dst_path)
        .with_context(|| format!("failed to create {:?}", dst_path))?;
    // Not going to bother setting mode on pre-existing files, since there
    // shouldn't be any under normal conditions.
    let mut cksum = Sha256::new();
    loop {
        let n = src
            .read(buf)
            .with_context(|| format!("failed to read from {:?}", src_path))?;
        if n == 0 {
            break Ok(cksum.finish_hex());
        }
        let data = &buf[..n];
        cksum.update(data);
        dst.write_all(data)
            .with_context(|| format!("failed to write to {:?}", dst_path))?;
    }
}
<commit_msg>cargo-vendor: path normalize for backslashes<commit_after>use crate::core::shell::Verbosity;
use crate::core::{GitReference, Workspace};
use crate::ops;
use crate::sources::path::PathSource;
use crate::sources::CRATES_IO_REGISTRY;
use crate::util::{CargoResult, Config};
use anyhow::{bail, Context as _};
use cargo_util::{paths, Sha256};
use serde::Serialize;
use std::collections::HashSet;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fs::{self, File, OpenOptions};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use toml_edit::easy as toml;

pub struct VendorOptions<'a> {
    pub no_delete: bool,
    pub versioned_dirs: bool,
    pub destination: &'a Path,
    pub extra: Vec<PathBuf>,
}

pub fn vendor(ws: &Workspace<'_>, opts: &VendorOptions<'_>) -> CargoResult<()> {
    let config = ws.config();
    let mut extra_workspaces = Vec::new();
    for extra in opts.extra.iter() {
        let extra = config.cwd().join(extra);
        let ws = Workspace::new(&extra, config)?;
        extra_workspaces.push(ws);
    }
    let workspaces = extra_workspaces.iter().chain(Some(ws)).collect::<Vec<_>>();
    let vendor_config = sync(config, &workspaces, opts).with_context(|| "failed to sync")?;

    if config.shell().verbosity() != Verbosity::Quiet {
        if vendor_config.source.is_empty() {
            crate::drop_eprintln!(config, "There is no dependency to vendor in this project.");
        } else {
            crate::drop_eprint!(
                config,
                "To use vendored sources, add this to your .cargo/config.toml for this project:\n\n"
            );
            crate::drop_print!(
                config,
                "{}",
                &toml::to_string_pretty(&vendor_config).unwrap()
            );
        }
    }

    Ok(())
}

#[derive(Serialize)]
struct VendorConfig {
    source: BTreeMap<String, VendorSource>,
}

#[derive(Serialize)]
#[serde(rename_all = "lowercase", untagged)]
enum VendorSource {
    Directory {
        directory: String,
    },
    Registry {
        registry: Option<String>,
        #[serde(rename = "replace-with")]
        replace_with: String,
    },
    Git {
        git: String,
        branch: Option<String>,
        tag: Option<String>,
        rev: Option<String>,
        #[serde(rename = "replace-with")]
        replace_with: String,
    },
}

fn sync(
    config: &Config,
    workspaces: &[&Workspace<'_>],
    opts: &VendorOptions<'_>,
) -> CargoResult<VendorConfig> {
    let canonical_destination = opts.destination.canonicalize();
    let canonical_destination = canonical_destination.as_deref().unwrap_or(opts.destination);
    let dest_dir_already_exists = canonical_destination.exists();

    paths::create_dir_all(&canonical_destination)?;
    let mut to_remove = HashSet::new();
    if !opts.no_delete {
        for entry in canonical_destination.read_dir()? {
            let entry = entry?;
            if !entry
                .file_name()
                .to_str()
                .map_or(false, |s| s.starts_with('.'))
            {
                to_remove.insert(entry.path());
            }
        }
    }

    // First up attempt to work around rust-lang/cargo#5956. Apparently build
    // artifacts sprout up in Cargo's global cache for whatever reason, although
    // it's unsure what tool is causing these issues at this time. For now we
    // apply a heavy-hammer approach which is to delete Cargo's unpacked version
    // of each crate to start off with. After we do this we'll re-resolve and
    // redownload again, which should trigger Cargo to re-extract all the
    // crates.
    //
    // Note that errors are largely ignored here as this is a best-effort
    // attempt. If anything fails here we basically just move on to the next
    // crate to work with.
    for ws in workspaces {
        let (packages, resolve) =
            ops::resolve_ws(ws).with_context(|| "failed to load pkg lockfile")?;

        packages
            .get_many(resolve.iter())
            .with_context(|| "failed to download packages")?;

        for pkg in resolve.iter() {
            // Don't delete actual source code!
            if pkg.source_id().is_path() {
                if let Ok(path) = pkg.source_id().url().to_file_path() {
                    if let Ok(path) = path.canonicalize() {
                        to_remove.remove(&path);
                    }
                }
                continue;
            }
            if pkg.source_id().is_git() {
                continue;
            }
            if let Ok(pkg) = packages.get_one(pkg) {
                drop(fs::remove_dir_all(pkg.manifest_path().parent().unwrap()));
            }
        }
    }

    let mut checksums = HashMap::new();
    let mut ids = BTreeMap::new();

    // Next up let's actually download all crates and start storing internal
    // tables about them.
    for ws in workspaces {
        let (packages, resolve) =
            ops::resolve_ws(ws).with_context(|| "failed to load pkg lockfile")?;

        packages
            .get_many(resolve.iter())
            .with_context(|| "failed to download packages")?;

        for pkg in resolve.iter() {
            // No need to vendor path crates since they're already in the
            // repository
            if pkg.source_id().is_path() {
                continue;
            }
            ids.insert(
                pkg,
                packages
                    .get_one(pkg)
                    .with_context(|| "failed to fetch package")?
                    .clone(),
            );

            checksums.insert(pkg, resolve.checksums().get(&pkg).cloned());
        }
    }

    let mut versions = HashMap::new();
    for id in ids.keys() {
        let map = versions.entry(id.name()).or_insert_with(BTreeMap::default);
        if let Some(prev) = map.get(&id.version()) {
            bail!(
                "found duplicate version of package `{} v{}` \
                 vendored from two sources:\n\
                 \n\
                 \tsource 1: {}\n\
                 \tsource 2: {}",
                id.name(),
                id.version(),
                prev,
                id.source_id()
            );
        }
        map.insert(id.version(), id.source_id());
    }

    let mut sources = BTreeSet::new();
    let mut tmp_buf = [0; 64 * 1024];
    for (id, pkg) in ids.iter() {
        // Next up, copy it to the vendor directory
        let src = pkg
            .manifest_path()
            .parent()
            .expect("manifest_path should point to a file");
        let max_version = *versions[&id.name()].iter().rev().next().unwrap().0;
        let dir_has_version_suffix = opts.versioned_dirs || id.version() != max_version;
        let dst_name = if dir_has_version_suffix {
            // Eg vendor/futures-0.1.13
            format!("{}-{}", id.name(), id.version())
        } else {
            // Eg vendor/futures
            id.name().to_string()
        };

        sources.insert(id.source_id());
        let dst = canonical_destination.join(&dst_name);
        to_remove.remove(&dst);
        let cksum = dst.join(".cargo-checksum.json");
        if dir_has_version_suffix && cksum.exists() {
            // Always re-copy directory without version suffix in case the version changed
            continue;
        }

        config.shell().status(
            "Vendoring",
            &format!("{} ({}) to {}", id, src.to_string_lossy(), dst.display()),
        )?;

        let _ = fs::remove_dir_all(&dst);
        let pathsource = PathSource::new(src, id.source_id(), config);
        let paths = pathsource.list_files(pkg)?;
        let mut map = BTreeMap::new();
        cp_sources(src, &paths, &dst, &mut map, &mut tmp_buf)
            .with_context(|| format!("failed to copy over vendored sources for: {}", id))?;

        // Finally, emit the metadata about this package
        let json = serde_json::json!({
            "package": checksums.get(id),
            "files": map,
        });

        paths::write(&cksum, json.to_string())?;
    }

    for path in to_remove {
        if path.is_dir() {
            paths::remove_dir_all(&path)?;
        } else {
            paths::remove_file(&path)?;
        }
    }

    // add our vendored source
    let mut config = BTreeMap::new();

    let merged_source_name = "vendored-sources";

    // replace original sources with vendor
    for source_id in sources {
        let name = if source_id.is_default_registry() {
            CRATES_IO_REGISTRY.to_string()
        } else {
            source_id.url().to_string()
        };

        let source = if source_id.is_default_registry() {
            VendorSource::Registry {
                registry: None,
                replace_with: merged_source_name.to_string(),
            }
        } else if source_id.is_remote_registry() {
            let registry = source_id.url().to_string();
            VendorSource::Registry {
                registry: Some(registry),
                replace_with: merged_source_name.to_string(),
            }
        } else if source_id.is_git() {
            let mut branch = None;
            let mut tag = None;
            let mut rev = None;
            if let Some(reference) = source_id.git_reference() {
                match *reference {
                    GitReference::Branch(ref b) => branch = Some(b.clone()),
                    GitReference::Tag(ref t) => tag = Some(t.clone()),
                    GitReference::Rev(ref r) => rev = Some(r.clone()),
                    GitReference::DefaultBranch => {}
                }
            }
            VendorSource::Git {
                git: source_id.url().to_string(),
                branch,
                tag,
                rev,
                replace_with: merged_source_name.to_string(),
            }
        } else {
            panic!("Invalid source ID: {}", source_id)
        };
        config.insert(name, source);
    }

    if !config.is_empty() {
        config.insert(
            merged_source_name.to_string(),
            VendorSource::Directory {
                directory: opts.destination.to_string_lossy().replace("\\", "/"),
            },
        );
    } else if !dest_dir_already_exists {
        // Nothing to vendor. Remove the destination dir we've just created.
        paths::remove_dir(canonical_destination)?;
    }

    Ok(VendorConfig { source: config })
}

fn cp_sources(
    src: &Path,
    paths: &[PathBuf],
    dst: &Path,
    cksums: &mut BTreeMap<String, String>,
    tmp_buf: &mut [u8],
) -> CargoResult<()> {
    for p in paths {
        let relative = p.strip_prefix(&src).unwrap();

        match relative.to_str() {
            // Skip git config files as they're not relevant to builds most of
            // the time and if we respect them (e.g.  in git) then it'll
            // probably mess with the checksums when a vendor dir is checked
            // into someone else's source control
            Some(".gitattributes") | Some(".gitignore") | Some(".git") => continue,

            // Temporary Cargo files
            Some(".cargo-ok") => continue,

            // Skip patch-style orig/rej files. Published crates on crates.io
            // have `Cargo.toml.orig` which we don't want to use here and
            // otherwise these are rarely used as part of the build process.
            Some(filename) => {
                if filename.ends_with(".orig") || filename.ends_with(".rej") {
                    continue;
                }
            }
            _ => {}
        };

        // Join pathname components individually to make sure that the joined
        // path uses the correct directory separators everywhere, since
        // `relative` may use Unix-style and `dst` may require Windows-style
        // backslashes.
        let dst = relative
            .iter()
            .fold(dst.to_owned(), |acc, component| acc.join(&component));

        paths::create_dir_all(dst.parent().unwrap())?;

        let cksum = copy_and_checksum(p, &dst, tmp_buf)?;
        cksums.insert(relative.to_str().unwrap().replace("\\", "/"), cksum);
    }
    Ok(())
}

fn copy_and_checksum(src_path: &Path, dst_path: &Path, buf: &mut [u8]) -> CargoResult<String> {
    let mut src = File::open(src_path).with_context(|| format!("failed to open {:?}", src_path))?;
    let mut dst_opts = OpenOptions::new();
    dst_opts.write(true).create(true).truncate(true);
    #[cfg(unix)]
    {
        use std::os::unix::fs::{MetadataExt, OpenOptionsExt};
        let src_metadata = src
            .metadata()
            .with_context(|| format!("failed to stat {:?}", src_path))?;
        dst_opts.mode(src_metadata.mode());
    }
    let mut dst = dst_opts
        .open(dst_path)
        .with_context(|| format!("failed to create {:?}", dst_path))?;
    // Not going to bother setting mode on pre-existing files, since there
    // shouldn't be any under normal conditions.
    let mut cksum = Sha256::new();
    loop {
        let n = src
            .read(buf)
            .with_context(|| format!("failed to read from {:?}", src_path))?;
        if n == 0 {
            break Ok(cksum.finish_hex());
        }
        let data = &buf[..n];
        cksum.update(data);
        dst.write_all(data)
            .with_context(|| format!("failed to write to {:?}", dst_path))?;
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::str;
use std::slice;
use std::os::raw;

use cassandra::error::CassError;
use cassandra::result::CassResult;
use cassandra::prepared::PreparedStatement;

use cassandra_sys::cass_true;

use cassandra_sys::CassFuture as _Future;
// use cassandra_sys::CassResult as _CassResult;
use cassandra_sys::cass_future_free;
use cassandra_sys::cass_future_error_message;
use cassandra_sys::cass_future_wait_timed;
use cassandra_sys::cass_future_wait;
use cassandra_sys::cass_future_ready;
use cassandra_sys::cass_future_error_code;
use cassandra_sys::cass_future_get_result;
use cassandra_sys::cass_future_get_prepared;
use cassandra_sys::cass_future_custom_payload_item;
use cassandra_sys::cass_future_custom_payload_item_count;
use cassandra_sys::cass_future_get_error_result;
use cassandra_sys::cass_future_set_callback;
use cassandra_sys::CassFutureCallback as _CassFutureCallback;
use cassandra::error::CassErrorResult;
use cassandra::util::Protected;

use cassandra_sys::CASS_OK;

///A CQL Future representing the status of any asynchronous calls to Cassandra
pub struct Future(*mut _Future);

///A callback registered to execute when the future returns
pub struct FutureCallback(_CassFutureCallback);

impl Drop for Future {
    ///Frees a future instance. A future can be freed anytime.
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl Future {
    ///Sets a callback that is called when a future is set
    pub fn set_callback(&mut self, callback: FutureCallback, data: *mut raw::c_void) -> Result<&Self, CassError> {
        unsafe { CassError::build(cass_future_set_callback(self.0, callback.0, data)).wrap(self) }
    }

    ///Gets the set status of the future.
    pub fn ready(&mut self) -> bool {
        unsafe { cass_future_ready(self.0) == cass_true }
    }

    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(self) -> Result<(), CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Wait for the future to be set or timeout.
    pub fn wait_timed(&mut self, timeout_us: u64) -> bool {
        unsafe { cass_future_wait_timed(self.0, timeout_us) == cass_true }
    }

    /// Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get_result(&self) -> CassResult {
        unsafe { CassResult::build((cass_future_get_result(self.0))) }
    }

    /// Gets the error result from a future that failed as a result of a server error. If the
    ///future is not ready this method will wait for the future to be set.
    pub fn get_error_result(&self) -> CassErrorResult {
        unsafe { CassErrorResult::build(cass_future_get_error_result(self.0)) }
    }

    ///Gets the error code from future. If the future is not ready this method will
    // wait for the future to be set.
    fn error_code(self) -> Result<(), CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_message(&mut self) -> String {
        unsafe {
            let message = mem::zeroed();
            let message_length = mem::zeroed();
            cass_future_error_message(self.0, message, message_length);

            let slice: &[u8] = slice::from_raw_parts(message as *const u8, message_length as usize);
            str::from_utf8(slice).expect("must be utf8").to_owned()
        }
    }

    /// Gets a the number of custom payload items from a response future. If the future is not
    /// ready this method will wait for the future to be set.
    pub fn payload_item_count(&self) -> u64 {
        unsafe { cass_future_custom_payload_item_count(self.0) }
    }

    ///Gets a custom payload item from a response future at the specified index. If the future is not
    ///ready this method will wait for the future to be set.
    pub fn payload_item(&self, index: u64) -> Result<(String, String), CassError> {
        unsafe {
            let name = mem::zeroed();
            let name_length = mem::zeroed();
            let value = mem::zeroed();
            let value_length = mem::zeroed();
            match cass_future_custom_payload_item(self.0, index, name, name_length, value, value_length) {
                CASS_OK => {
                    Ok((str::from_utf8(slice::from_raw_parts(name as *const u8, name_length as usize))
                            .expect("must be utf8")
                            .to_owned(),
                        str::from_utf8(slice::from_raw_parts(value as *const u8, value_length as usize))
                            .expect("must be utf8")
                            .to_owned()))
                }
                err => Err(CassError::build(err)),
            }

        }
    }
}

#[must_use]
///The future result of an operation.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct ResultFuture(*mut _Future);

impl Drop for ResultFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl ResultFuture {
    ///Blocks until the future returns or times out
    pub fn wait(&mut self) -> Result<CassResult, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&mut self) -> Result<CassResult, CassError> {
        unsafe {
            if let Some(x) = self.get() {
                CassError::build(cass_future_error_code(self.0)).wrap(x)
            } else {
                panic!("FIXME");
            }

        }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_message(&mut self) -> String {
        unsafe {
            let message = mem::zeroed();
            let message_length = mem::zeroed();
            cass_future_error_message(self.0, message, message_length);

            let slice = slice::from_raw_parts(message as *const u8, message_length as usize);
            str::from_utf8(slice).expect("must be utf8").to_owned()
        }
    }

    ///Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    ///a None response indicates that there was an error
    pub fn get(&mut self) -> Option<CassResult> {
        unsafe {
            let result = cass_future_get_result(self.0);
            if result.is_null() { None } else { Some((CassResult::build(result))) }
        }
    }
}

///The future result of an prepared statement.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct PreparedFuture(*mut _Future);

impl Drop for PreparedFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl PreparedFuture {
    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(&mut self) -> Result<PreparedStatement, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&mut self) -> Result<PreparedStatement, CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(self.get()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get(&mut self) -> PreparedStatement {
        unsafe { PreparedStatement::build(cass_future_get_prepared(self.0)) }
    }
}

pub struct ConnectFuture(*mut _Future);

impl Protected<*mut _Future> for ConnectFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        ConnectFuture(inner)
    }
}

impl Drop for ConnectFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}
///The future result of an attempt to create a new Cassandra session
///It can be waited on, polled or a callback
///can be attached.
pub struct SessionFuture(*mut _Future);

impl SessionFuture {
    ///blocks until the session connects or errors out
    pub fn wait(&mut self) -> Result<(), CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&self) -> Result<(), CassError> {
        unsafe {
            if let Some(_) = self.get() {
                CassError::build(cass_future_error_code(self.0)).wrap(())
            } else {
                panic!("FIXME")
            }
        }
    }

    ///Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    ///a None response indicates that there was an error
    pub fn get(&self) -> Option<CassResult> {
        unsafe {
            let result = cass_future_get_result(self.0);
            debug!("result is null: {}", result.is_null());
            if result.is_null() { None } else { Some(CassResult::build(result)) }
        }
    }
}

impl Drop for SessionFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

///The future result of a session close statement.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct CloseFuture(*mut _Future);

impl Protected<*mut _Future> for Future {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        Future(inner)
    }
}

impl Protected<*mut _Future> for PreparedFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        PreparedFuture(inner)
    }
}

impl Protected<*mut _Future> for ResultFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        ResultFuture(inner)
    }
}

impl Protected<*mut _Future> for SessionFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        SessionFuture(inner)
    }
}

impl Protected<*mut _Future> for CloseFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        CloseFuture(inner)
    }
}

impl Drop for CloseFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl CloseFuture {
    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(&self) -> Result<PreparedStatement, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&self) -> Result<PreparedStatement, CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(self.get()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get(&self) -> PreparedStatement {
        unsafe { PreparedStatement::build(cass_future_get_prepared(self.0)) }
    }
}
<commit_msg>Pass on error from ResultFuture::error_code to caller.<commit_after>use std::mem;
use std::str;
use std::slice;
use std::os::raw;

use cassandra::error::CassError;
use cassandra::result::CassResult;
use cassandra::prepared::PreparedStatement;

use cassandra_sys::cass_true;

use cassandra_sys::CassFuture as _Future;
// use cassandra_sys::CassResult as _CassResult;
use cassandra_sys::cass_future_free;
use cassandra_sys::cass_future_error_message;
use cassandra_sys::cass_future_wait_timed;
use cassandra_sys::cass_future_wait;
use cassandra_sys::cass_future_ready;
use cassandra_sys::cass_future_error_code;
use cassandra_sys::cass_future_get_result;
use cassandra_sys::cass_future_get_prepared;
use cassandra_sys::cass_future_custom_payload_item;
use cassandra_sys::cass_future_custom_payload_item_count;
use cassandra_sys::cass_future_get_error_result;
use cassandra_sys::cass_future_set_callback;
use cassandra_sys::CassFutureCallback as _CassFutureCallback;
use cassandra::error::CassErrorResult;
use cassandra::util::Protected;

use cassandra_sys::CASS_OK;

///A CQL Future representing the status of any asynchronous calls to Cassandra
pub struct Future(*mut _Future);

///A callback registered to execute when the future returns
pub struct FutureCallback(_CassFutureCallback);

impl Drop for Future {
    ///Frees a future instance. A future can be freed anytime.
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl Future {
    ///Sets a callback that is called when a future is set
    pub fn set_callback(&mut self, callback: FutureCallback, data: *mut raw::c_void) -> Result<&Self, CassError> {
        unsafe { CassError::build(cass_future_set_callback(self.0, callback.0, data)).wrap(self) }
    }

    ///Gets the set status of the future.
    pub fn ready(&mut self) -> bool {
        unsafe { cass_future_ready(self.0) == cass_true }
    }

    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(self) -> Result<(), CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Wait for the future to be set or timeout.
    pub fn wait_timed(&mut self, timeout_us: u64) -> bool {
        unsafe { cass_future_wait_timed(self.0, timeout_us) == cass_true }
    }

    /// Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get_result(&self) -> CassResult {
        unsafe { CassResult::build((cass_future_get_result(self.0))) }
    }

    /// Gets the error result from a future that failed as a result of a server error. If the
    ///future is not ready this method will wait for the future to be set.
    pub fn get_error_result(&self) -> CassErrorResult {
        unsafe { CassErrorResult::build(cass_future_get_error_result(self.0)) }
    }

    ///Gets the error code from future. If the future is not ready this method will
    // wait for the future to be set.
    fn error_code(self) -> Result<(), CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_message(&mut self) -> String {
        unsafe {
            let message = mem::zeroed();
            let message_length = mem::zeroed();
            cass_future_error_message(self.0, message, message_length);

            let slice: &[u8] = slice::from_raw_parts(message as *const u8, message_length as usize);
            str::from_utf8(slice).expect("must be utf8").to_owned()
        }
    }

    /// Gets a the number of custom payload items from a response future. If the future is not
    /// ready this method will wait for the future to be set.
    pub fn payload_item_count(&self) -> u64 {
        unsafe { cass_future_custom_payload_item_count(self.0) }
    }

    ///Gets a custom payload item from a response future at the specified index. If the future is not
    ///ready this method will wait for the future to be set.
    pub fn payload_item(&self, index: u64) -> Result<(String, String), CassError> {
        unsafe {
            let name = mem::zeroed();
            let name_length = mem::zeroed();
            let value = mem::zeroed();
            let value_length = mem::zeroed();
            match cass_future_custom_payload_item(self.0, index, name, name_length, value, value_length) {
                CASS_OK => {
                    Ok((str::from_utf8(slice::from_raw_parts(name as *const u8, name_length as usize))
                            .expect("must be utf8")
                            .to_owned(),
                        str::from_utf8(slice::from_raw_parts(value as *const u8, value_length as usize))
                            .expect("must be utf8")
                            .to_owned()))
                }
                err => Err(CassError::build(err)),
            }

        }
    }
}

#[must_use]
///The future result of an operation.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct ResultFuture(*mut _Future);

impl Drop for ResultFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl ResultFuture {
    ///Blocks until the future returns or times out
    pub fn wait(&mut self) -> Result<CassResult, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&mut self) -> Result<CassResult, CassError> {
        unsafe {
            let x = self.get();
            let error_code = CassError::build(cass_future_error_code(self.0));
            match x {
                Some(x) => error_code.wrap(x),
                None => Err(error_code)
            }
        }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_message(&mut self) -> String {
        unsafe {
            let message = mem::zeroed();
            let message_length = mem::zeroed();
            cass_future_error_message(self.0, message, message_length);

            let slice = slice::from_raw_parts(message as *const u8, message_length as usize);
            str::from_utf8(slice).expect("must be utf8").to_owned()
        }
    }

    ///Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    ///a None response indicates that there was an error
    pub fn get(&mut self) -> Option<CassResult> {
        unsafe {
            let result = cass_future_get_result(self.0);
            if result.is_null() { None } else { Some((CassResult::build(result))) }
        }
    }
}

///The future result of an prepared statement.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct PreparedFuture(*mut _Future);

impl Drop for PreparedFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl PreparedFuture {
    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(&mut self) -> Result<PreparedStatement, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&mut self) -> Result<PreparedStatement, CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(self.get()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get(&mut self) -> PreparedStatement {
        unsafe { PreparedStatement::build(cass_future_get_prepared(self.0)) }
    }
}

pub struct ConnectFuture(*mut _Future);

impl Protected<*mut _Future> for ConnectFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        ConnectFuture(inner)
    }
}

impl Drop for ConnectFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}
///The future result of an attempt to create a new Cassandra session
///It can be waited on, polled or a callback
///can be attached.
pub struct SessionFuture(*mut _Future);

impl SessionFuture {
    ///blocks until the session connects or errors out
    pub fn wait(&mut self) -> Result<(), CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&self) -> Result<(), CassError> {
        unsafe {
            if let Some(_) = self.get() {
                CassError::build(cass_future_error_code(self.0)).wrap(())
            } else {
                panic!("FIXME")
            }
        }
    }

    ///Gets the result of a successful future. If the future is not ready this method will
    ///wait for the future to be set.
    ///a None response indicates that there was an error
    pub fn get(&self) -> Option<CassResult> {
        unsafe {
            let result = cass_future_get_result(self.0);
            debug!("result is null: {}", result.is_null());
            if result.is_null() { None } else { Some(CassResult::build(result)) }
        }
    }
}

impl Drop for SessionFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

///The future result of a session close statement.
///It can represent a result if the operation completed successfully or an
///error if the operation failed. It can be waited on, polled or a callback
///can be attached.
pub struct CloseFuture(*mut _Future);

impl Protected<*mut _Future> for Future {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        Future(inner)
    }
}

impl Protected<*mut _Future> for PreparedFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        PreparedFuture(inner)
    }
}

impl Protected<*mut _Future> for ResultFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        ResultFuture(inner)
    }
}

impl Protected<*mut _Future> for SessionFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        SessionFuture(inner)
    }
}

impl Protected<*mut _Future> for CloseFuture {
    fn inner(&self) -> *mut _Future {
        self.0
    }
    fn build(inner: *mut _Future) -> Self {
        CloseFuture(inner)
    }
}

impl Drop for CloseFuture {
    fn drop(&mut self) {
        unsafe { cass_future_free(self.0) }
    }
}

impl CloseFuture {
    /// Wait for the future to be set with either a result or error.
    ///
    ///Important: Do not wait in a future callback. Waiting in a future
    ///callback will cause a deadlock.
    pub fn wait(&self) -> Result<PreparedStatement, CassError> {
        unsafe {
            cass_future_wait(self.0);
            self.error_code()
        }
    }

    ///Gets the error code from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn error_code(&self) -> Result<PreparedStatement, CassError> {
        unsafe { CassError::build(cass_future_error_code(self.0)).wrap(self.get()) }
    }

    ///Gets the error message from future. If the future is not ready this method will
    ///wait for the future to be set.
    pub fn get(&self) -> PreparedStatement {
        unsafe { PreparedStatement::build(cass_future_get_prepared(self.0)) }
    }
}
<|endoftext|>


<commit_before>use redox::Box;
use redox::fs;
use redox::io::Read;
use redox::rand;
use redox::ptr;
use redox::slice::SliceConcatExt;
use redox::string::*;
use redox::thread;
use redox::Vec;

pub fn main() {
    println!("Type help for a command list");
    loop {
        print!("# ");
        if let Some(line) = readln!() {
            let args: Vec<String> = line.split(' ').map(|arg| arg.to_string()).collect();

            if let Some(a_command) = args.get(0) {
                let console_commands = ["panic",
                                        "ls",
                                        "ptr_write",
                                        "box_write",
                                        "reboot",
                                        "shutdown",
                                        "clone",
                                        "leak_test"];

                match &a_command[..] {
                    command if command == console_commands[0] =>
                        panic!("Test panic"),
                    command if command == console_commands[1] => {
                        for entry in fs::read_dir("file:///").unwrap() {
                            println!("{}", entry.path());
                        }
                    }
                    command if command == console_commands[2] => {
                        let a_ptr = rand() as *mut u8;
                        unsafe { ptr::write(a_ptr, rand() as u8); }
                    }
                    command if command == console_commands[3] => {
                        let a_box = Box::new(rand() as u8);
                        unsafe { ptr::write(Box::into_raw(a_box), rand() as u8); }
                    }
                    command if command == console_commands[4] => {
                        unsafe {
                            let mut good: u8 = 2;
                            while good & 2 == 2 {
                                asm!("in al, dx" : "={al}"(good) : "{dx}"(0x64) : : "intel", "volatile");
                            }
                            asm!("out dx, al" : : "{dx}"(0x64), "{al}"(0xFE) : : "intel", "volatile");
                            loop {
                                asm!("cli" : : : : "intel", "volatile");
                                asm!("hlt" : : : : "intel", "volatile");
                            }
                        }
                    }
                    command if command == console_commands[5] => {
                        unsafe {
                            loop {
                                asm!("cli" : : : : "intel", "volatile");
                                asm!("hlt" : : : : "intel", "volatile");
                            }
                        }
                    }
                    command if command == console_commands[6] => {
                        let parent_message = "Parent Message";
                        let handle = thread::spawn(move || {
                            println!("Child after spawn: {}", parent_message);
                            return "Child message";
                        });
                        println!("Parent after spawn: {}", parent_message);
                        match handle.join() {
                            Some(child_message) => println!("Parent after join: {}", child_message),
                            None => println!("Failed to join")
                        }
                    }
                    command if command == console_commands[7] => {
                        let mut stack_it: Vec<Box<u8>> = Vec::new();
                        loop {
                            stack_it.push(Box::new(rand() as u8))
                        }
                    }
                    _ => println!("Commands: {}", console_commands.join(" ")),
                }
            }
        }else{
            println!("Failed to read line from stdin");
        }
    }
}
<commit_msg>Fix test<commit_after>use redox::Box;
use redox::fs;
use redox::io::Read;
use redox::rand;
use redox::ptr;
use redox::slice::SliceConcatExt;
use redox::string::*;
use redox::thread;
use redox::Vec;

pub fn main() {
    println!("Type help for a command list");
    loop {
        print!("# ");
        if let Some(line) = readln!() {
            let args: Vec<String> = line.trim().split(' ').map(|arg| arg.to_string()).collect();

            if let Some(a_command) = args.get(0) {
                let console_commands = ["panic",
                                        "ls",
                                        "ptr_write",
                                        "box_write",
                                        "reboot",
                                        "shutdown",
                                        "clone",
                                        "leak_test"];

                match &a_command[..] {
                    command if command == console_commands[0] =>
                        panic!("Test panic"),
                    command if command == console_commands[1] => {
                        for entry in fs::read_dir("file:///").unwrap() {
                            println!("{}", entry.path());
                        }
                    }
                    command if command == console_commands[2] => {
                        let a_ptr = rand() as *mut u8;
                        unsafe { ptr::write(a_ptr, rand() as u8); }
                    }
                    command if command == console_commands[3] => {
                        let a_box = Box::new(rand() as u8);
                        unsafe { ptr::write(Box::into_raw(a_box), rand() as u8); }
                    }
                    command if command == console_commands[4] => {
                        unsafe {
                            let mut good: u8 = 2;
                            while good & 2 == 2 {
                                asm!("in al, dx" : "={al}"(good) : "{dx}"(0x64) : : "intel", "volatile");
                            }
                            asm!("out dx, al" : : "{dx}"(0x64), "{al}"(0xFE) : : "intel", "volatile");
                            loop {
                                asm!("cli" : : : : "intel", "volatile");
                                asm!("hlt" : : : : "intel", "volatile");
                            }
                        }
                    }
                    command if command == console_commands[5] => {
                        unsafe {
                            loop {
                                asm!("cli" : : : : "intel", "volatile");
                                asm!("hlt" : : : : "intel", "volatile");
                            }
                        }
                    }
                    command if command == console_commands[6] => {
                        let parent_message = "Parent Message";
                        let handle = thread::spawn(move || {
                            println!("Child after spawn: {}", parent_message);
                            return "Child message";
                        });
                        println!("Parent after spawn: {}", parent_message);
                        match handle.join() {
                            Some(child_message) => println!("Parent after join: {}", child_message),
                            None => println!("Failed to join")
                        }
                    }
                    command if command == console_commands[7] => {
                        let mut stack_it: Vec<Box<u8>> = Vec::new();
                        loop {
                            stack_it.push(Box::new(rand() as u8))
                        }
                    }
                    _ => println!("Commands: {}", console_commands.join(" ")),
                }
            }
        }else{
            println!("Failed to read line from stdin");
        }
    }
}
<|endoftext|>


<commit_before>use std::clone::Clone;
use std::env::home_dir;
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches, SubCommand};
use log::LogLevel;
use ring::{digest, rand, hmac};
use ring::rand::SecureRandom;
use toml;

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use self::tempfile::NamedTempFile;
    use std::fs::File;

    use super::*;

    fn temp_file() -> (File, PathBuf) {
        let f = NamedTempFile::new().expect("failed to create temporary file");
        let path = f.path();
        (f.try_clone().unwrap(), path.to_path_buf())
    }

    #[test]
    fn it_generates_a_new_key() {
        let (_f, path) = temp_file();
        let config_file = Config::create_default(path.clone());
        let args = Config::matches().get_matches_from(vec!["bitcrustd", &format!("--config={}", path.to_string_lossy())[..], "stats", "peers"]);
        let config = Config::from_args(&args);
        assert_eq!(config_file.key, config.raw_key.to_vec());
    }

    #[test]
    fn it_can_be_cloned() {
        let (_f, path) = temp_file();
        let _= Config::create_default(path.clone());
        let args = Config::matches().get_matches_from(vec!["bitcrustd", &format!("--config={}", path.to_string_lossy())[..], "stats", "peers"]);
        let config = Config::from_args(&args);
        assert_eq!(config.clone().raw_key, config.raw_key);
    }
}

#[derive(Deserialize, Serialize, Debug)]
pub struct ConfigFile {
    key: Vec<u8>
}

pub struct Config {
    pub log_level: LogLevel,
    raw_key: [u8; 32],
    signing_key: hmac::SigningKey
}

impl<'a, 'b> Config {
    pub fn from_args(matches: &ArgMatches) -> Config {
        let mut path = home_dir().expect("Can't figure out where your $HOME is");
        path.push(".bitcrust.toml");
        let log_level = match matches.occurrences_of("debug") {
            0 => LogLevel::Warn,
            1 => LogLevel::Info,
            2 => LogLevel::Debug,
            3 | _ => LogLevel::Trace,
        };
        let config_file_path: PathBuf = matches.value_of("config").map(|p| PathBuf::from(&p)).unwrap_or(path);
        let config_from_file: ConfigFile = if config_file_path.exists() {
            let mut f = File::open(config_file_path.clone()).unwrap();
            let mut s = String::new();
            let _ = f.read_to_string(&mut s);
            toml::from_str(&s).unwrap_or_else(|_| Config::create_default(config_file_path))
        } else {
            Config::create_default(config_file_path)
        };

        let key = hmac::SigningKey::new(&digest::SHA256, &config_from_file.key);

        let mut a: [u8; 32] = [0; 32];
        a.copy_from_slice(&config_from_file.key);

        Config {
            log_level: log_level,
            raw_key: a,
            signing_key: key,
        }

    }

    pub fn matches() -> App<'a, 'b> {
        App::new("bitcrustd")
            .version(crate_version!())
            .author("Chris M., Tomas W.")
            .arg(Arg::with_name("config")
                .short("c")
                .long("config")
                .takes_value(true)
                .help("Location of the Bitcrust Config File, default: $HOME/.bitcrust.toml"))
            .arg(Arg::with_name("debug")
                .short("d")
                .long("debug")
                .multiple(true)
                .help("Turn debugging information on"))
            .subcommand(SubCommand::with_name("node").about("Bitcrust peer node"))
            .subcommand(SubCommand::with_name("stats")
                .about("Get stats from a running Bitcrust node")
                .arg(Arg::with_name("host")
                    .short("h")
                    .long("host")
                    .takes_value(true))
                .subcommand(SubCommand::with_name("peers"))
            )
            .subcommand(SubCommand::with_name("balance")
                .about("Get balance for address")
                .arg(Arg::with_name("address")
                    .short("a")
                    .long("address")
                    .help("Address to get balance for")
                    .takes_value(true)
                    .required(true))
            )
    }

    pub fn create_default(path: PathBuf) -> ConfigFile {
        let rng = rand::SystemRandom::new();
        let mut key = [0; 32];
        rng.fill(&mut key).unwrap();
        let c = ConfigFile {
            key: key.to_vec()
        };
        let s = toml::to_string(&c).unwrap();
        println!("Making a new config file with: {}", s);
        let mut f = File::create(path).unwrap();
        let _ = f.write_all(&s.as_bytes());//.to_string());
        c
    }

    pub fn key(&self) -> &hmac::SigningKey {
        &self.signing_key
    }
}

impl Clone for Config {
    fn clone(&self) -> Config {
        Config {
            log_level: self.log_level,
            raw_key: self.raw_key,
            signing_key: hmac::SigningKey::new(&digest::SHA256, &self.raw_key)
        }
    }
}<commit_msg>only need to initialize that default PATH if none is configured<commit_after>use std::clone::Clone;
use std::env::home_dir;
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches, SubCommand};
use log::LogLevel;
use ring::{digest, rand, hmac};
use ring::rand::SecureRandom;
use toml;

#[cfg(test)]
mod tests {
    extern crate tempfile;
    use self::tempfile::NamedTempFile;
    use std::fs::File;

    use super::*;

    fn temp_file() -> (File, PathBuf) {
        let f = NamedTempFile::new().expect("failed to create temporary file");
        let path = f.path();
        (f.try_clone().unwrap(), path.to_path_buf())
    }

    #[test]
    fn it_generates_a_new_key() {
        let (_f, path) = temp_file();
        let config_file = Config::create_default(path.clone());
        let args = Config::matches().get_matches_from(vec!["bitcrustd", &format!("--config={}", path.to_string_lossy())[..], "stats", "peers"]);
        let config = Config::from_args(&args);
        assert_eq!(config_file.key, config.raw_key.to_vec());
    }

    #[test]
    fn it_can_be_cloned() {
        let (_f, path) = temp_file();
        let _= Config::create_default(path.clone());
        let args = Config::matches().get_matches_from(vec!["bitcrustd", &format!("--config={}", path.to_string_lossy())[..], "stats", "peers"]);
        let config = Config::from_args(&args);
        assert_eq!(config.clone().raw_key, config.raw_key);
    }
}

#[derive(Deserialize, Serialize, Debug)]
pub struct ConfigFile {
    key: Vec<u8>
}

pub struct Config {
    pub log_level: LogLevel,
    raw_key: [u8; 32],
    signing_key: hmac::SigningKey
}

impl<'a, 'b> Config {
    pub fn from_args(matches: &ArgMatches) -> Config {
        let log_level = match matches.occurrences_of("debug") {
            0 => LogLevel::Warn,
            1 => LogLevel::Info,
            2 => LogLevel::Debug,
            3 | _ => LogLevel::Trace,
        };
        let config_file_path: PathBuf = matches.value_of("config").map(|p| PathBuf::from(&p)).unwrap_or_else(|| {
            let mut path = home_dir().expect("Can't figure out where your $HOME is");
            path.push(".bitcrust.toml");
            path
        });
        let config_from_file: ConfigFile = if config_file_path.exists() {
            let mut f = File::open(config_file_path.clone()).unwrap();
            let mut s = String::new();
            let _ = f.read_to_string(&mut s);
            toml::from_str(&s).unwrap_or_else(|_| Config::create_default(config_file_path))
        } else {
            Config::create_default(config_file_path)
        };

        let key = hmac::SigningKey::new(&digest::SHA256, &config_from_file.key);

        let mut a: [u8; 32] = [0; 32];
        a.copy_from_slice(&config_from_file.key);

        Config {
            log_level: log_level,
            raw_key: a,
            signing_key: key,
        }

    }

    pub fn matches() -> App<'a, 'b> {
        App::new("bitcrustd")
            .version(crate_version!())
            .author("Chris M., Tomas W.")
            .arg(Arg::with_name("config")
                .short("c")
                .long("config")
                .takes_value(true)
                .help("Location of the Bitcrust Config File, default: $HOME/.bitcrust.toml"))
            .arg(Arg::with_name("debug")
                .short("d")
                .long("debug")
                .multiple(true)
                .help("Turn debugging information on"))
            .subcommand(SubCommand::with_name("node").about("Bitcrust peer node"))
            .subcommand(SubCommand::with_name("stats")
                .about("Get stats from a running Bitcrust node")
                .arg(Arg::with_name("host")
                    .short("h")
                    .long("host")
                    .takes_value(true))
                .subcommand(SubCommand::with_name("peers"))
            )
            .subcommand(SubCommand::with_name("balance")
                .about("Get balance for address")
                .arg(Arg::with_name("address")
                    .short("a")
                    .long("address")
                    .help("Address to get balance for")
                    .takes_value(true)
                    .required(true))
            )
    }

    pub fn create_default(path: PathBuf) -> ConfigFile {
        let rng = rand::SystemRandom::new();
        let mut key = [0; 32];
        rng.fill(&mut key).unwrap();
        let c = ConfigFile {
            key: key.to_vec()
        };
        let s = toml::to_string(&c).unwrap();
        println!("Making a new config file with: {}", s);
        let mut f = File::create(path).unwrap();
        let _ = f.write_all(&s.as_bytes());//.to_string());
        c
    }

    pub fn key(&self) -> &hmac::SigningKey {
        &self.signing_key
    }
}

impl Clone for Config {
    fn clone(&self) -> Config {
        Config {
            log_level: self.log_level,
            raw_key: self.raw_key,
            signing_key: hmac::SigningKey::new(&digest::SHA256, &self.raw_key)
        }
    }
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Implementation of cookie creation and matching as specified by
//! http://tools.ietf.org/html/rfc6265

use cookie_rs;
use hyper_serde::{self, Serde};
use net_traits::CookieSource;
use net_traits::pub_domains::is_pub_domain;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::net::{Ipv4Addr, Ipv6Addr};
use time::{Tm, now, at, Duration};

/// A stored cookie that wraps the definition in cookie-rs. This is used to implement
/// various behaviours defined in the spec that rely on an associated request URL,
/// which cookie-rs and hyper's header parsing do not support.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Cookie {
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub cookie: cookie_rs::Cookie,
    pub host_only: bool,
    pub persistent: bool,
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub creation_time: Tm,
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub last_access: Tm,
    pub expiry_time: Option<Serde<Tm>>,
}

impl Cookie {
    /// http://tools.ietf.org/html/rfc6265#section-5.3
    pub fn new_wrapped(mut cookie: cookie_rs::Cookie, request: &ServoUrl, source: CookieSource)
                       -> Option<Cookie> {
        // Step 3
        let (persistent, expiry_time) = match (&cookie.max_age, &cookie.expires) {
            (&Some(max_age), _) => {
                (true, Some(at(now().to_timespec() + Duration::seconds(max_age as i64))))
            }
            (_, &Some(expires)) => (true, Some(expires)),
            _ => (false, None)
        };

        let url_host = request.host_str().unwrap_or("").to_owned();

        // Step 4
        let mut domain = cookie.domain.clone().unwrap_or("".to_owned());

        // Step 5
        if is_pub_domain(&domain) {
            if domain == url_host {
                domain = "".to_owned();
            } else {
                return None
            }
        }

        // Step 6
        let host_only = if !domain.is_empty() {
            if !Cookie::domain_match(&url_host, &domain) {
                return None;
            } else {
                cookie.domain = Some(domain);
                false
            }
        } else {
            cookie.domain = Some(url_host);
            true
        };

        // Step 7
        let mut path = cookie.path.unwrap_or("".to_owned());
        if path.chars().next() != Some('/') {
            path = Cookie::default_path(request.path()).to_owned();
        }
        cookie.path = Some(path);

        // Step 10
        if cookie.httponly && source == CookieSource::NonHTTP {
            return None;
        }

        Some(Cookie {
            cookie: cookie,
            host_only: host_only,
            persistent: persistent,
            creation_time: now(),
            last_access: now(),
            expiry_time: expiry_time.map(Serde),
        })
    }

    pub fn touch(&mut self) {
        self.last_access = now();
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.4
    pub fn default_path(request_path: &str) -> &str {
        // Step 2
        if request_path.chars().next() != Some('/') {
            return "/";
        }

        // Step 3
        let rightmost_slash_idx = request_path.rfind("/").unwrap();
        if rightmost_slash_idx == 0 {
            // There's only one slash; it's the first character
            return "/";
        }

        // Step 4
        &request_path[..rightmost_slash_idx]
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.4
    pub fn path_match(request_path: &str, cookie_path: &str) -> bool {
        // A request-path path-matches a given cookie-path if at least one of
        // the following conditions holds:

        // The cookie-path and the request-path are identical.
        request_path == cookie_path ||

        (request_path.starts_with(cookie_path) && (
            // The cookie-path is a prefix of the request-path, and the last
            // character of the cookie-path is %x2F ("/").
            cookie_path.ends_with("/") ||
            // The cookie-path is a prefix of the request-path, and the first
            // character of the request-path that is not included in the cookie-
            // path is a %x2F ("/") character.
            request_path[cookie_path.len()..].starts_with("/")
        ))
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.3
    pub fn domain_match(string: &str, domain_string: &str) -> bool {
        string == domain_string ||
        (string.ends_with(domain_string) &&
         string.as_bytes()[string.len()-domain_string.len()-1] == b'.' &&
         string.parse::<Ipv4Addr>().is_err() &&
         string.parse::<Ipv6Addr>().is_err())
    }

    // http://tools.ietf.org/html/rfc6265#section-5.4 step 1
    pub fn appropriate_for_url(&self, url: &ServoUrl, source: CookieSource) -> bool {
        let domain = url.host_str();
        if self.host_only {
            if self.cookie.domain.as_ref().map(String::as_str) != domain {
                return false;
            }
        } else {
            if let (Some(domain), &Some(ref cookie_domain)) = (domain, &self.cookie.domain) {
                if !Cookie::domain_match(domain, cookie_domain) {
                    return false;
                }
            }
        }

        if let Some(ref cookie_path) = self.cookie.path {
            if !Cookie::path_match(url.path(), cookie_path) {
                return false;
            }
        }

        if self.cookie.secure && !url.is_secure_scheme() {
            return false;
        }
        if self.cookie.httponly && source == CookieSource::NonHTTP {
            return false;
        }

        true
    }
}
<commit_msg>Assert that `domain_match` is operating on lowercase text<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Implementation of cookie creation and matching as specified by
//! http://tools.ietf.org/html/rfc6265

use cookie_rs;
use hyper_serde::{self, Serde};
use net_traits::CookieSource;
use net_traits::pub_domains::is_pub_domain;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::net::{Ipv4Addr, Ipv6Addr};
use time::{Tm, now, at, Duration};

/// A stored cookie that wraps the definition in cookie-rs. This is used to implement
/// various behaviours defined in the spec that rely on an associated request URL,
/// which cookie-rs and hyper's header parsing do not support.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Cookie {
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub cookie: cookie_rs::Cookie,
    pub host_only: bool,
    pub persistent: bool,
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub creation_time: Tm,
    #[serde(deserialize_with = "hyper_serde::deserialize",
            serialize_with = "hyper_serde::serialize")]
    pub last_access: Tm,
    pub expiry_time: Option<Serde<Tm>>,
}

impl Cookie {
    /// http://tools.ietf.org/html/rfc6265#section-5.3
    pub fn new_wrapped(mut cookie: cookie_rs::Cookie, request: &ServoUrl, source: CookieSource)
                       -> Option<Cookie> {
        // Step 3
        let (persistent, expiry_time) = match (&cookie.max_age, &cookie.expires) {
            (&Some(max_age), _) => {
                (true, Some(at(now().to_timespec() + Duration::seconds(max_age as i64))))
            }
            (_, &Some(expires)) => (true, Some(expires)),
            _ => (false, None)
        };

        let url_host = request.host_str().unwrap_or("").to_owned();

        // Step 4
        let mut domain = cookie.domain.clone().unwrap_or("".to_owned());

        // Step 5
        if is_pub_domain(&domain) {
            if domain == url_host {
                domain = "".to_owned();
            } else {
                return None
            }
        }

        // Step 6
        let host_only = if !domain.is_empty() {
            if !Cookie::domain_match(&url_host, &domain) {
                return None;
            } else {
                cookie.domain = Some(domain);
                false
            }
        } else {
            cookie.domain = Some(url_host);
            true
        };

        // Step 7
        let mut path = cookie.path.unwrap_or("".to_owned());
        if path.chars().next() != Some('/') {
            path = Cookie::default_path(request.path()).to_owned();
        }
        cookie.path = Some(path);

        // Step 10
        if cookie.httponly && source == CookieSource::NonHTTP {
            return None;
        }

        Some(Cookie {
            cookie: cookie,
            host_only: host_only,
            persistent: persistent,
            creation_time: now(),
            last_access: now(),
            expiry_time: expiry_time.map(Serde),
        })
    }

    pub fn touch(&mut self) {
        self.last_access = now();
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.4
    pub fn default_path(request_path: &str) -> &str {
        // Step 2
        if request_path.chars().next() != Some('/') {
            return "/";
        }

        // Step 3
        let rightmost_slash_idx = request_path.rfind("/").unwrap();
        if rightmost_slash_idx == 0 {
            // There's only one slash; it's the first character
            return "/";
        }

        // Step 4
        &request_path[..rightmost_slash_idx]
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.4
    pub fn path_match(request_path: &str, cookie_path: &str) -> bool {
        // A request-path path-matches a given cookie-path if at least one of
        // the following conditions holds:

        // The cookie-path and the request-path are identical.
        request_path == cookie_path ||

        (request_path.starts_with(cookie_path) && (
            // The cookie-path is a prefix of the request-path, and the last
            // character of the cookie-path is %x2F ("/").
            cookie_path.ends_with("/") ||
            // The cookie-path is a prefix of the request-path, and the first
            // character of the request-path that is not included in the cookie-
            // path is a %x2F ("/") character.
            request_path[cookie_path.len()..].starts_with("/")
        ))
    }

    // http://tools.ietf.org/html/rfc6265#section-5.1.3
    pub fn domain_match(string: &str, domain_string: &str) -> bool {
        debug_assert!(string.to_lowercase() == string);
        debug_assert!(domain_string.to_lowercase() == domain_string);
        string == domain_string ||
        (string.ends_with(domain_string) &&
         string.as_bytes()[string.len()-domain_string.len()-1] == b'.' &&
         string.parse::<Ipv4Addr>().is_err() &&
         string.parse::<Ipv6Addr>().is_err())
    }

    // http://tools.ietf.org/html/rfc6265#section-5.4 step 1
    pub fn appropriate_for_url(&self, url: &ServoUrl, source: CookieSource) -> bool {
        let domain = url.host_str();
        if self.host_only {
            if self.cookie.domain.as_ref().map(String::as_str) != domain {
                return false;
            }
        } else {
            if let (Some(domain), &Some(ref cookie_domain)) = (domain, &self.cookie.domain) {
                if !Cookie::domain_match(domain, cookie_domain) {
                    return false;
                }
            }
        }

        if let Some(ref cookie_path) = self.cookie.path {
            if !Cookie::path_match(url.path(), cookie_path) {
                return false;
            }
        }

        if self.cookie.secure && !url.is_secure_scheme() {
            return false;
        }
        if self.cookie.httponly && source == CookieSource::NonHTTP {
            return false;
        }

        true
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(ascii_ctype)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(const_ptr_null)]
#![feature(const_ptr_null_mut)]
#![feature(core_intrinsics)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(plugin)]
#![feature(proc_macro)]
#![feature(try_from)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(script_plugins)]

extern crate angle;
extern crate app_units;
extern crate audio_video_metadata;
extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields;
extern crate devtools_traits;
extern crate dom_struct;
#[macro_use]
extern crate domobject_derive;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate half;
#[macro_use] extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
#[macro_use] extern crate html5ever;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate metrics;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
extern crate servo_arc;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate swapper;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;
extern crate utf8;
extern crate uuid;
extern crate webrender_api;
extern crate webvr_traits;
extern crate xml5ever;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
mod layout_image;
mod mem;
mod microtask;
mod network_listener;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

/// A module with everything layout can use from script.
///
/// Try to keep this small!
///
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
pub mod layout_exports {
    pub use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
    pub use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
    pub use dom::bindings::js::LayoutJS;
    pub use dom::characterdata::LayoutCharacterDataHelpers;
    pub use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
    pub use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
    pub use dom::node::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
    pub use dom::node::{HANDLED_SNAPSHOT, HAS_SNAPSHOT};
    pub use dom::node::{LayoutNodeHelpers, Node};
    pub use dom::text::Text;
}

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<commit_msg>Remove unused 'unboxed_closures' feature flag<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(ascii_ctype)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(const_ptr_null)]
#![feature(const_ptr_null_mut)]
#![feature(core_intrinsics)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(plugin)]
#![feature(proc_macro)]
#![feature(try_from)]
#![feature(untagged_unions)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(script_plugins)]

extern crate angle;
extern crate app_units;
extern crate audio_video_metadata;
extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
extern crate byteorder;
extern crate canvas_traits;
extern crate caseless;
extern crate cookie as cookie_rs;
extern crate core;
#[macro_use] extern crate cssparser;
#[macro_use] extern crate deny_public_fields;
extern crate devtools_traits;
extern crate dom_struct;
#[macro_use]
extern crate domobject_derive;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate gleam;
extern crate half;
#[macro_use] extern crate heapsize;
#[macro_use] extern crate heapsize_derive;
#[macro_use] extern crate html5ever;
#[macro_use]
extern crate hyper;
extern crate hyper_serde;
extern crate image;
extern crate ipc_channel;
#[macro_use]
extern crate js;
#[macro_use]
extern crate jstraceable_derive;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate metrics;
#[macro_use]
extern crate mime;
extern crate mime_guess;
extern crate msg;
extern crate net_traits;
extern crate num_traits;
extern crate offscreen_gl_context;
extern crate open;
extern crate parking_lot;
extern crate phf;
#[macro_use]
extern crate profile_traits;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;
extern crate serde;
extern crate servo_arc;
#[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_rand;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate swapper;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;
extern crate utf8;
extern crate uuid;
extern crate webrender_api;
extern crate webvr_traits;
extern crate xml5ever;

mod body;
pub mod clipboard_provider;
mod devtools;
pub mod document_loader;
#[macro_use]
mod dom;
pub mod fetch;
mod layout_image;
mod mem;
mod microtask;
mod network_listener;
pub mod script_runtime;
#[allow(unsafe_code)]
pub mod script_thread;
mod serviceworker_manager;
mod serviceworkerjob;
mod stylesheet_loader;
mod task_source;
pub mod test;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

/// A module with everything layout can use from script.
///
/// Try to keep this small!
///
/// TODO(emilio): A few of the FooHelpers can go away, presumably...
pub mod layout_exports {
    pub use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
    pub use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
    pub use dom::bindings::js::LayoutJS;
    pub use dom::characterdata::LayoutCharacterDataHelpers;
    pub use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
    pub use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
    pub use dom::node::{CAN_BE_FRAGMENTED, HAS_DIRTY_DESCENDANTS, IS_IN_DOC};
    pub use dom::node::{HANDLED_SNAPSHOT, HAS_SNAPSHOT};
    pub use dom::node::{LayoutNodeHelpers, Node};
    pub use dom::text::Text;
}

use dom::bindings::codegen::RegisterBindings;
use dom::bindings::proxyhandler;
use script_traits::SWManagerSenders;
use serviceworker_manager::ServiceWorkerManager;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

pub fn init_service_workers(sw_senders: SWManagerSenders) {
    // Spawn the service worker manager passing the constellation sender
    ServiceWorkerManager::spawn_manager(sw_senders);
}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        proxyhandler::init();

        // Create the global vtables used by the (generated) DOM
        // bindings to implement JS proxies.
        RegisterBindings::RegisterProxyHandlers();
    }

    perform_platform_specific_initialization();
}
<|endoftext|>