<commit_before>#![deny(bare_trait_objects)]

mod compiler;
mod decls;
mod error;
mod function;
mod heap;
mod load;
mod module;
mod name;
mod output;
mod patch;
mod pointer;
mod runtime;
pub mod signature;
mod sparsedata;
mod stack_probe;
mod table;
mod traps;
mod types;

use crate::load::read_bytes;
pub use crate::{
    compiler::{Compiler, CompilerBuilder, CpuFeatures, OptLevel, SpecificFeature, TargetCpu},
    error::Error,
    heap::HeapSettings,
    load::read_module,
    patch::patch_module,
};
pub use lucet_module::bindings::Bindings;
pub use lucet_validate::Validator;
use signature::{PublicKey, SecretKey};
use std::env;
use std::path::{Path, PathBuf};
use target_lexicon::Triple;

enum LucetcInput {
    Bytes(Vec<u8>),
    Path(PathBuf),
}

pub struct Lucetc {
    input: LucetcInput,
    bindings: Vec<Bindings>,
    builtins_paths: Vec<PathBuf>,
    builder: CompilerBuilder,
    sk: Option<SecretKey>,
    pk: Option<PublicKey>,
    sign: bool,
    verify: bool,
}

pub trait AsLucetc {
    fn as_lucetc(&mut self) -> &mut Lucetc;
}

impl AsLucetc for Lucetc {
    fn as_lucetc(&mut self) -> &mut Lucetc {
        self
    }
}

pub trait LucetcOpts {
    fn bindings(&mut self, bindings: Bindings);
    fn with_bindings(self, bindings: Bindings) -> Self;

    fn target(&mut self, target: Triple);
    fn with_target(self, target: Triple) -> Self;

    fn opt_level(&mut self, opt_level: OptLevel);
    fn with_opt_level(self, opt_level: OptLevel) -> Self;

    fn cpu_features(&mut self, cpu_features: CpuFeatures);
    fn with_cpu_features(self, cpu_features: CpuFeatures) -> Self;

    fn builtins<P: AsRef<Path>>(&mut self, builtins_path: P);
    fn with_builtins<P: AsRef<Path>>(self, builtins_path: P) -> Self;

    fn validator(&mut self, validator: Validator);
    fn with_validator(self, validator: Validator) -> Self;

    fn min_reserved_size(&mut self, min_reserved_size: u64);
    fn with_min_reserved_size(self, min_reserved_size: u64) -> Self;

    fn max_reserved_size(&mut self, max_reserved_size: u64);
    fn with_max_reserved_size(self, max_reserved_size: u64) -> Self;

    /// Set the reserved size exactly.
    ///
    /// Equivalent to setting the minimum and maximum reserved sizes to the same value.
    fn reserved_size(&mut self, reserved_size: u64);
    /// Set the reserved size exactly.
    ///
    /// Equivalent to setting the minimum and maximum reserved sizes to the same value.
    fn with_reserved_size(self, reserved_size: u64) -> Self;

    fn guard_size(&mut self, guard_size: u64);
    fn with_guard_size(self, guard_size: u64) -> Self;

    fn pk(&mut self, pk: PublicKey);
    fn with_pk(self, pk: PublicKey) -> Self;
    fn sk(&mut self, sk: SecretKey);
    fn with_sk(self, sk: SecretKey) -> Self;
    fn verify(&mut self);
    fn with_verify(self) -> Self;
    fn sign(&mut self);
    fn with_sign(self) -> Self;
    fn count_instructions(&mut self, enable_count: bool);
    fn with_count_instructions(self, enable_count: bool) -> Self;
    fn canonicalize_nans(&mut self, enable_canonicalize_nans: bool);
    fn with_canonicalize_nans(self, enable_canonicalize_nans: bool) -> Self;
}

impl<T: AsLucetc> LucetcOpts for T {
    fn bindings(&mut self, bindings: Bindings) {
        self.as_lucetc().bindings.push(bindings);
    }

    fn with_bindings(mut self, bindings: Bindings) -> Self {
        self.bindings(bindings);
        self
    }

    fn target(&mut self, target: Triple) {
        self.as_lucetc().builder.target(target);
    }

    fn with_target(mut self, target: Triple) -> Self {
        self.target(target);
        self
    }

    fn opt_level(&mut self, opt_level: OptLevel) {
        self.as_lucetc().builder.opt_level(opt_level);
    }

    fn with_opt_level(mut self, opt_level: OptLevel) -> Self {
        self.opt_level(opt_level);
        self
    }

    fn cpu_features(&mut self, cpu_features: CpuFeatures) {
        self.as_lucetc().builder.cpu_features(cpu_features);
    }

    fn with_cpu_features(mut self, cpu_features: CpuFeatures) -> Self {
        self.cpu_features(cpu_features);
        self
    }

    fn builtins<P: AsRef<Path>>(&mut self, builtins_path: P) {
        self.as_lucetc()
            .builtins_paths
            .push(builtins_path.as_ref().to_owned());
    }

    fn with_builtins<P: AsRef<Path>>(mut self, builtins_path: P) -> Self {
        self.builtins(builtins_path);
        self
    }

    fn validator(&mut self, validator: Validator) {
        self.as_lucetc().builder.validator(Some(validator));
    }

    fn with_validator(mut self, validator: Validator) -> Self {
        self.validator(validator);
        self
    }

    fn min_reserved_size(&mut self, min_reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .min_reserved_size = min_reserved_size;
    }

    fn with_min_reserved_size(mut self, min_reserved_size: u64) -> Self {
        self.min_reserved_size(min_reserved_size);
        self
    }

    fn max_reserved_size(&mut self, max_reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .max_reserved_size = max_reserved_size;
    }

    fn with_max_reserved_size(mut self, max_reserved_size: u64) -> Self {
        self.max_reserved_size(max_reserved_size);
        self
    }

    fn reserved_size(&mut self, reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .min_reserved_size = reserved_size;
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .max_reserved_size = reserved_size;
    }

    fn with_reserved_size(mut self, reserved_size: u64) -> Self {
        self.reserved_size(reserved_size);
        self
    }

    fn guard_size(&mut self, guard_size: u64) {
        self.as_lucetc().builder.heap_settings_mut().guard_size = guard_size;
    }

    fn with_guard_size(mut self, guard_size: u64) -> Self {
        self.guard_size(guard_size);
        self
    }

    fn pk(&mut self, pk: PublicKey) {
        self.as_lucetc().pk = Some(pk);
    }

    fn with_pk(mut self, pk: PublicKey) -> Self {
        self.pk(pk);
        self
    }

    fn sk(&mut self, sk: SecretKey) {
        self.as_lucetc().sk = Some(sk);
    }

    fn with_sk(mut self, sk: SecretKey) -> Self {
        self.sk(sk);
        self
    }

    fn verify(&mut self) {
        self.as_lucetc().verify = true;
    }

    fn with_verify(mut self) -> Self {
        self.verify();
        self
    }

    fn sign(&mut self) {
        self.as_lucetc().sign = true;
    }

    fn with_sign(mut self) -> Self {
        self.sign();
        self
    }

    fn count_instructions(&mut self, count_instructions: bool) {
        self.as_lucetc()
            .builder
            .count_instructions(count_instructions);
    }

    fn with_count_instructions(mut self, count_instructions: bool) -> Self {
        self.count_instructions(count_instructions);
        self
    }

    fn canonicalize_nans(&mut self, enable_nans_canonicalization: bool) {
        self.as_lucetc()
            .builder
            .canonicalize_nans(enable_nans_canonicalization);
    }

    fn with_canonicalize_nans(mut self, enable_nans_canonicalization: bool) -> Self {
        self.canonicalize_nans(enable_nans_canonicalization);
        self
    }
}

impl Lucetc {
    pub fn new<P: AsRef<Path>>(input: P) -> Self {
        let input = input.as_ref();
        Self {
            input: LucetcInput::Path(input.to_owned()),
            bindings: vec![],
            builder: Compiler::builder(),
            builtins_paths: vec![],
            pk: None,
            sk: None,
            sign: false,
            verify: false,
        }
    }

    pub fn try_from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, Error> {
        let input = read_bytes(bytes.as_ref().to_vec())?;
        Ok(Self {
            input: LucetcInput::Bytes(input),
            bindings: vec![],
            builder: Compiler::builder(),
            builtins_paths: vec![],
            pk: None,
            sk: None,
            sign: false,
            verify: false,
        })
    }

    fn build(&self) -> Result<(Vec<u8>, Bindings), Error> {
        use parity_wasm::elements::{deserialize_buffer, serialize};

        let mut builtins_bindings = vec![];
        let mut module_binary = match &self.input {
            LucetcInput::Bytes(bytes) => bytes.clone(),
            LucetcInput::Path(path) => read_module(&path, &self.pk, self.verify)?,
        };

        if !self.builtins_paths.is_empty() {
            let mut module = deserialize_buffer(&module_binary)?;
            for builtins in self.builtins_paths.iter() {
                let (newmodule, builtins_map) = patch_module(module, builtins)?;
                module = newmodule;
                builtins_bindings.push(Bindings::env(builtins_map));
            }
            module_binary = serialize(module)?;
        }

        let mut bindings = Bindings::empty();

        for binding in builtins_bindings.iter().chain(self.bindings.iter()) {
            bindings.extend(binding)?;
        }

        Ok((module_binary, bindings))
    }

    pub fn object_file<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let (module_contents, bindings) = self.build()?;
        let compiler = self.builder.create(&module_contents, &bindings)?;
        let obj = compiler.object_file()?;
        obj.write(output.as_ref())?;

        Ok(())
    }

    pub fn clif_ir<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let (module_contents, bindings) = self.build()?;

        let compiler = self.builder.create(&module_contents, &bindings)?;

        compiler.cranelift_funcs()?.write(&output)?;

        Ok(())
    }

    pub fn shared_object_file<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let dir = tempfile::Builder::new().prefix("lucetc").tempdir()?;
        let objpath = dir.path().join("tmp.o");
        self.object_file(objpath.clone())?;
        link_so(objpath, self.builder.target_ref(), &output)?;
        if self.sign {
            let sk = self.sk.as_ref().ok_or(Error::Signature(
                "signing requires a secret key".to_string(),
            ))?;
            signature::sign_module(&output, sk)?;
        }
        Ok(())
    }
}

const LD_DEFAULT: &str = "ld";

fn link_so<P, Q>(objpath: P, target: &Triple, sopath: Q) -> Result<(), Error>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    use std::process::Command;

    // Let `LD` be something like "clang --target=... ..." for convenience.
    let env_ld = env::var("LD").unwrap_or(LD_DEFAULT.into());
    let mut ld_iter = env_ld.split_whitespace();
    let ld_prog = ld_iter.next().expect("LD must not be empty");
    let mut cmd_ld = Command::new(ld_prog);
    for flag in ld_iter {
        cmd_ld.arg(flag);
    }

    cmd_ld.arg(objpath.as_ref());
    let env_ldflags = env::var("LDFLAGS").unwrap_or_else(|_| ldflags_default(target));
    for flag in env_ldflags.split_whitespace() {
        cmd_ld.arg(flag);
    }
    cmd_ld.arg("-o");
    cmd_ld.arg(sopath.as_ref());

    let run_ld = cmd_ld.output()?;

    if !run_ld.status.success() {
        let message = format!(
            "ld of {} failed: {}",
            objpath.as_ref().to_str().unwrap(),
            String::from_utf8_lossy(&run_ld.stderr)
        );
        return Err(Error::LdError(message));
    }
    Ok(())
}

fn ldflags_default(target: &Triple) -> String {
    use target_lexicon::OperatingSystem;

    match target.operating_system {
        OperatingSystem::Linux => "-shared",
        OperatingSystem::Darwin | OperatingSystem::MacOSX { .. } => {
            "-dylib -dead_strip -export_dynamic -undefined dynamic_lookup"
        }
        _ => panic!(
            "Cannot determine default flags for {}.

Please define the LDFLAGS environment variable with the necessary command-line
flags for generating shared libraries.",
            Triple::host()
        ),
    }
    .into()
}
<commit_msg>fix lucetc error message about linker flags<commit_after>#![deny(bare_trait_objects)]

mod compiler;
mod decls;
mod error;
mod function;
mod heap;
mod load;
mod module;
mod name;
mod output;
mod patch;
mod pointer;
mod runtime;
pub mod signature;
mod sparsedata;
mod stack_probe;
mod table;
mod traps;
mod types;

use crate::load::read_bytes;
pub use crate::{
    compiler::{Compiler, CompilerBuilder, CpuFeatures, OptLevel, SpecificFeature, TargetCpu},
    error::Error,
    heap::HeapSettings,
    load::read_module,
    patch::patch_module,
};
pub use lucet_module::bindings::Bindings;
pub use lucet_validate::Validator;
use signature::{PublicKey, SecretKey};
use std::env;
use std::path::{Path, PathBuf};
use target_lexicon::Triple;

enum LucetcInput {
    Bytes(Vec<u8>),
    Path(PathBuf),
}

pub struct Lucetc {
    input: LucetcInput,
    bindings: Vec<Bindings>,
    builtins_paths: Vec<PathBuf>,
    builder: CompilerBuilder,
    sk: Option<SecretKey>,
    pk: Option<PublicKey>,
    sign: bool,
    verify: bool,
}

pub trait AsLucetc {
    fn as_lucetc(&mut self) -> &mut Lucetc;
}

impl AsLucetc for Lucetc {
    fn as_lucetc(&mut self) -> &mut Lucetc {
        self
    }
}

pub trait LucetcOpts {
    fn bindings(&mut self, bindings: Bindings);
    fn with_bindings(self, bindings: Bindings) -> Self;

    fn target(&mut self, target: Triple);
    fn with_target(self, target: Triple) -> Self;

    fn opt_level(&mut self, opt_level: OptLevel);
    fn with_opt_level(self, opt_level: OptLevel) -> Self;

    fn cpu_features(&mut self, cpu_features: CpuFeatures);
    fn with_cpu_features(self, cpu_features: CpuFeatures) -> Self;

    fn builtins<P: AsRef<Path>>(&mut self, builtins_path: P);
    fn with_builtins<P: AsRef<Path>>(self, builtins_path: P) -> Self;

    fn validator(&mut self, validator: Validator);
    fn with_validator(self, validator: Validator) -> Self;

    fn min_reserved_size(&mut self, min_reserved_size: u64);
    fn with_min_reserved_size(self, min_reserved_size: u64) -> Self;

    fn max_reserved_size(&mut self, max_reserved_size: u64);
    fn with_max_reserved_size(self, max_reserved_size: u64) -> Self;

    /// Set the reserved size exactly.
    ///
    /// Equivalent to setting the minimum and maximum reserved sizes to the same value.
    fn reserved_size(&mut self, reserved_size: u64);
    /// Set the reserved size exactly.
    ///
    /// Equivalent to setting the minimum and maximum reserved sizes to the same value.
    fn with_reserved_size(self, reserved_size: u64) -> Self;

    fn guard_size(&mut self, guard_size: u64);
    fn with_guard_size(self, guard_size: u64) -> Self;

    fn pk(&mut self, pk: PublicKey);
    fn with_pk(self, pk: PublicKey) -> Self;
    fn sk(&mut self, sk: SecretKey);
    fn with_sk(self, sk: SecretKey) -> Self;
    fn verify(&mut self);
    fn with_verify(self) -> Self;
    fn sign(&mut self);
    fn with_sign(self) -> Self;
    fn count_instructions(&mut self, enable_count: bool);
    fn with_count_instructions(self, enable_count: bool) -> Self;
    fn canonicalize_nans(&mut self, enable_canonicalize_nans: bool);
    fn with_canonicalize_nans(self, enable_canonicalize_nans: bool) -> Self;
}

impl<T: AsLucetc> LucetcOpts for T {
    fn bindings(&mut self, bindings: Bindings) {
        self.as_lucetc().bindings.push(bindings);
    }

    fn with_bindings(mut self, bindings: Bindings) -> Self {
        self.bindings(bindings);
        self
    }

    fn target(&mut self, target: Triple) {
        self.as_lucetc().builder.target(target);
    }

    fn with_target(mut self, target: Triple) -> Self {
        self.target(target);
        self
    }

    fn opt_level(&mut self, opt_level: OptLevel) {
        self.as_lucetc().builder.opt_level(opt_level);
    }

    fn with_opt_level(mut self, opt_level: OptLevel) -> Self {
        self.opt_level(opt_level);
        self
    }

    fn cpu_features(&mut self, cpu_features: CpuFeatures) {
        self.as_lucetc().builder.cpu_features(cpu_features);
    }

    fn with_cpu_features(mut self, cpu_features: CpuFeatures) -> Self {
        self.cpu_features(cpu_features);
        self
    }

    fn builtins<P: AsRef<Path>>(&mut self, builtins_path: P) {
        self.as_lucetc()
            .builtins_paths
            .push(builtins_path.as_ref().to_owned());
    }

    fn with_builtins<P: AsRef<Path>>(mut self, builtins_path: P) -> Self {
        self.builtins(builtins_path);
        self
    }

    fn validator(&mut self, validator: Validator) {
        self.as_lucetc().builder.validator(Some(validator));
    }

    fn with_validator(mut self, validator: Validator) -> Self {
        self.validator(validator);
        self
    }

    fn min_reserved_size(&mut self, min_reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .min_reserved_size = min_reserved_size;
    }

    fn with_min_reserved_size(mut self, min_reserved_size: u64) -> Self {
        self.min_reserved_size(min_reserved_size);
        self
    }

    fn max_reserved_size(&mut self, max_reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .max_reserved_size = max_reserved_size;
    }

    fn with_max_reserved_size(mut self, max_reserved_size: u64) -> Self {
        self.max_reserved_size(max_reserved_size);
        self
    }

    fn reserved_size(&mut self, reserved_size: u64) {
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .min_reserved_size = reserved_size;
        self.as_lucetc()
            .builder
            .heap_settings_mut()
            .max_reserved_size = reserved_size;
    }

    fn with_reserved_size(mut self, reserved_size: u64) -> Self {
        self.reserved_size(reserved_size);
        self
    }

    fn guard_size(&mut self, guard_size: u64) {
        self.as_lucetc().builder.heap_settings_mut().guard_size = guard_size;
    }

    fn with_guard_size(mut self, guard_size: u64) -> Self {
        self.guard_size(guard_size);
        self
    }

    fn pk(&mut self, pk: PublicKey) {
        self.as_lucetc().pk = Some(pk);
    }

    fn with_pk(mut self, pk: PublicKey) -> Self {
        self.pk(pk);
        self
    }

    fn sk(&mut self, sk: SecretKey) {
        self.as_lucetc().sk = Some(sk);
    }

    fn with_sk(mut self, sk: SecretKey) -> Self {
        self.sk(sk);
        self
    }

    fn verify(&mut self) {
        self.as_lucetc().verify = true;
    }

    fn with_verify(mut self) -> Self {
        self.verify();
        self
    }

    fn sign(&mut self) {
        self.as_lucetc().sign = true;
    }

    fn with_sign(mut self) -> Self {
        self.sign();
        self
    }

    fn count_instructions(&mut self, count_instructions: bool) {
        self.as_lucetc()
            .builder
            .count_instructions(count_instructions);
    }

    fn with_count_instructions(mut self, count_instructions: bool) -> Self {
        self.count_instructions(count_instructions);
        self
    }

    fn canonicalize_nans(&mut self, enable_nans_canonicalization: bool) {
        self.as_lucetc()
            .builder
            .canonicalize_nans(enable_nans_canonicalization);
    }

    fn with_canonicalize_nans(mut self, enable_nans_canonicalization: bool) -> Self {
        self.canonicalize_nans(enable_nans_canonicalization);
        self
    }
}

impl Lucetc {
    pub fn new<P: AsRef<Path>>(input: P) -> Self {
        let input = input.as_ref();
        Self {
            input: LucetcInput::Path(input.to_owned()),
            bindings: vec![],
            builder: Compiler::builder(),
            builtins_paths: vec![],
            pk: None,
            sk: None,
            sign: false,
            verify: false,
        }
    }

    pub fn try_from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, Error> {
        let input = read_bytes(bytes.as_ref().to_vec())?;
        Ok(Self {
            input: LucetcInput::Bytes(input),
            bindings: vec![],
            builder: Compiler::builder(),
            builtins_paths: vec![],
            pk: None,
            sk: None,
            sign: false,
            verify: false,
        })
    }

    fn build(&self) -> Result<(Vec<u8>, Bindings), Error> {
        use parity_wasm::elements::{deserialize_buffer, serialize};

        let mut builtins_bindings = vec![];
        let mut module_binary = match &self.input {
            LucetcInput::Bytes(bytes) => bytes.clone(),
            LucetcInput::Path(path) => read_module(&path, &self.pk, self.verify)?,
        };

        if !self.builtins_paths.is_empty() {
            let mut module = deserialize_buffer(&module_binary)?;
            for builtins in self.builtins_paths.iter() {
                let (newmodule, builtins_map) = patch_module(module, builtins)?;
                module = newmodule;
                builtins_bindings.push(Bindings::env(builtins_map));
            }
            module_binary = serialize(module)?;
        }

        let mut bindings = Bindings::empty();

        for binding in builtins_bindings.iter().chain(self.bindings.iter()) {
            bindings.extend(binding)?;
        }

        Ok((module_binary, bindings))
    }

    pub fn object_file<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let (module_contents, bindings) = self.build()?;
        let compiler = self.builder.create(&module_contents, &bindings)?;
        let obj = compiler.object_file()?;
        obj.write(output.as_ref())?;

        Ok(())
    }

    pub fn clif_ir<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let (module_contents, bindings) = self.build()?;

        let compiler = self.builder.create(&module_contents, &bindings)?;

        compiler.cranelift_funcs()?.write(&output)?;

        Ok(())
    }

    pub fn shared_object_file<P: AsRef<Path>>(&self, output: P) -> Result<(), Error> {
        let dir = tempfile::Builder::new().prefix("lucetc").tempdir()?;
        let objpath = dir.path().join("tmp.o");
        self.object_file(objpath.clone())?;
        link_so(objpath, self.builder.target_ref(), &output)?;
        if self.sign {
            let sk = self.sk.as_ref().ok_or(Error::Signature(
                "signing requires a secret key".to_string(),
            ))?;
            signature::sign_module(&output, sk)?;
        }
        Ok(())
    }
}

const LD_DEFAULT: &str = "ld";

fn link_so<P, Q>(objpath: P, target: &Triple, sopath: Q) -> Result<(), Error>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    use std::process::Command;

    // Let `LD` be something like "clang --target=... ..." for convenience.
    let env_ld = env::var("LD").unwrap_or(LD_DEFAULT.into());
    let mut ld_iter = env_ld.split_whitespace();
    let ld_prog = ld_iter.next().expect("LD must not be empty");
    let mut cmd_ld = Command::new(ld_prog);
    for flag in ld_iter {
        cmd_ld.arg(flag);
    }

    cmd_ld.arg(objpath.as_ref());
    let env_ldflags = env::var("LDFLAGS").unwrap_or_else(|_| ldflags_default(target));
    for flag in env_ldflags.split_whitespace() {
        cmd_ld.arg(flag);
    }
    cmd_ld.arg("-o");
    cmd_ld.arg(sopath.as_ref());

    let run_ld = cmd_ld.output()?;

    if !run_ld.status.success() {
        let message = format!(
            "ld of {} failed: {}",
            objpath.as_ref().to_str().unwrap(),
            String::from_utf8_lossy(&run_ld.stderr)
        );
        return Err(Error::LdError(message));
    }
    Ok(())
}

fn ldflags_default(target: &Triple) -> String {
    use target_lexicon::OperatingSystem;

    match target.operating_system {
        OperatingSystem::Linux => "-shared",
        OperatingSystem::Darwin | OperatingSystem::MacOSX { .. } => {
            "-dylib -dead_strip -export_dynamic -undefined dynamic_lookup"
        }
        _ => panic!(
            "Cannot determine default flags for {}.

Please define the LDFLAGS environment variable with the necessary command-line
flags for generating shared libraries.",
            target
        ),
    }
    .into()
}
<|endoftext|>


<commit_before>//! Provides functions to read and write segment registers.

use crate::structures::gdt::SegmentSelector;

/// Reload code segment register.
///
/// Note this is special since we can not directly move
/// to %cs. Instead we push the new segment selector
/// and return value on the stack and use lretq
/// to reload cs and continue at 1:.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid code segment descriptor.
#[inline]
pub unsafe fn set_cs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        // FIXME - Use intel syntax
        asm!("pushq {}; leaq 1f(%rip), %rax; pushq %rax; lretq; 1:", in(reg) u64::from(sel.0), out("rax") _, options(att_syntax));
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        crate::asm::x86_64_asm_set_cs(u64::from(sel.0))
    }

    inner(sel)
}

/// Reload stack segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid stack segment descriptor.
#[inline]
pub unsafe fn load_ss(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov ss, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_ss(sel.0);
}

/// Reload data segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid data segment descriptor.
#[inline]
pub unsafe fn load_ds(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov ds, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_ds(sel.0);
}

/// Reload es segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid extra segment descriptor.
#[inline]
pub unsafe fn load_es(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov es, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_es(sel.0);
}

/// Reload fs segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid fs segment descriptor.
#[inline]
pub unsafe fn load_fs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov fs, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_fs(sel.0);
}

/// Reload gs segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid gs segment descriptor.
#[inline]
pub unsafe fn load_gs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov gs, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_gs(sel.0);
}

/// Swap `KernelGsBase` MSR and `GsBase` MSR.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that the
/// swap operation cannot lead to undefined behavior.
#[inline]
pub unsafe fn swap_gs() {
    #[cfg(feature = "inline_asm")]
    asm!("swapgs", options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_swapgs();
}

/// Returns the current value of the code segment register.
#[inline]
pub fn cs() -> SegmentSelector {
    #[cfg(feature = "inline_asm")]
    {
        let segment: u16;
        unsafe { asm!("mov {0:x}, cs", out(reg) segment, options(nostack, nomem)) };
        SegmentSelector(segment)
    }

    #[cfg(not(feature = "inline_asm"))]
    {
        let segment: u16 = unsafe { crate::asm::x86_64_asm_get_cs() };
        SegmentSelector(segment)
    }
}

/// Writes the FS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
///
/// The caller must ensure that this write operation has no unsafe side
/// effects, as the FS segment base address is often used for thread
/// local storage.
#[inline]
pub unsafe fn wrfsbase(val: u64) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        llvm_asm!("wrfsbase $0" :: "r"(val) :: "volatile")
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        crate::asm::x86_64_asm_wrfsbase(val)
    }

    inner(val)
}

/// Reads the FS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
#[inline]
pub unsafe fn rdfsbase() -> u64 {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        let val: u64;
        llvm_asm!("rdfsbase $0" : "=r" (val) ::: "volatile");
        val
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        crate::asm::x86_64_asm_rdfsbase()
    }

    inner()
}

/// Writes the GS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
///
/// The caller must ensure that this write operation has no unsafe side
/// effects, as the GS segment base address might be in use.
#[inline]
pub unsafe fn wrgsbase(val: u64) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        llvm_asm!("wrgsbase $0" :: "r"(val) :: "volatile")
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        crate::asm::x86_64_asm_wrgsbase(val)
    }

    inner(val)
}

/// Reads the GS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
#[inline]
pub unsafe fn rdgsbase() -> u64 {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        let val: u64;
        llvm_asm!("rdgsbase $0" : "=r" (val) ::: "volatile");
        val
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        crate::asm::x86_64_asm_rdgsbase()
    }

    inner()
}
<commit_msg>Move set_cs to Intel Syntax<commit_after>//! Provides functions to read and write segment registers.

use crate::structures::gdt::SegmentSelector;

/// Reload code segment register.
///
/// Note this is special since we can not directly move
/// to cs. Instead we push the new segment selector
/// and return value on the stack and use retf
/// to reload cs and continue at 1:.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid code segment descriptor.
#[inline]
pub unsafe fn set_cs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        asm!(
            "push {sel}",
            "lea {tmp}, [1f + rip]",
            "push {tmp}",
            "retfq",
            "1:",
            sel = in(reg) u64::from(sel.0),
            tmp = lateout(reg) _,
        );
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        crate::asm::x86_64_asm_set_cs(u64::from(sel.0))
    }

    inner(sel)
}

/// Reload stack segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid stack segment descriptor.
#[inline]
pub unsafe fn load_ss(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov ss, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_ss(sel.0);
}

/// Reload data segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid data segment descriptor.
#[inline]
pub unsafe fn load_ds(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov ds, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_ds(sel.0);
}

/// Reload es segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid extra segment descriptor.
#[inline]
pub unsafe fn load_es(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov es, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_es(sel.0);
}

/// Reload fs segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid fs segment descriptor.
#[inline]
pub unsafe fn load_fs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov fs, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_fs(sel.0);
}

/// Reload gs segment register.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that `sel`
/// is a valid gs segment descriptor.
#[inline]
pub unsafe fn load_gs(sel: SegmentSelector) {
    #[cfg(feature = "inline_asm")]
    asm!("mov gs, {0:x}", in(reg) sel.0, options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_load_gs(sel.0);
}

/// Swap `KernelGsBase` MSR and `GsBase` MSR.
///
/// ## Safety
///
/// This function is unsafe because the caller must ensure that the
/// swap operation cannot lead to undefined behavior.
#[inline]
pub unsafe fn swap_gs() {
    #[cfg(feature = "inline_asm")]
    asm!("swapgs", options(nostack));

    #[cfg(not(feature = "inline_asm"))]
    crate::asm::x86_64_asm_swapgs();
}

/// Returns the current value of the code segment register.
#[inline]
pub fn cs() -> SegmentSelector {
    #[cfg(feature = "inline_asm")]
    {
        let segment: u16;
        unsafe { asm!("mov {0:x}, cs", out(reg) segment, options(nostack, nomem)) };
        SegmentSelector(segment)
    }

    #[cfg(not(feature = "inline_asm"))]
    {
        let segment: u16 = unsafe { crate::asm::x86_64_asm_get_cs() };
        SegmentSelector(segment)
    }
}

/// Writes the FS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
///
/// The caller must ensure that this write operation has no unsafe side
/// effects, as the FS segment base address is often used for thread
/// local storage.
#[inline]
pub unsafe fn wrfsbase(val: u64) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        llvm_asm!("wrfsbase $0" :: "r"(val) :: "volatile")
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        crate::asm::x86_64_asm_wrfsbase(val)
    }

    inner(val)
}

/// Reads the FS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
#[inline]
pub unsafe fn rdfsbase() -> u64 {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        let val: u64;
        llvm_asm!("rdfsbase $0" : "=r" (val) ::: "volatile");
        val
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        crate::asm::x86_64_asm_rdfsbase()
    }

    inner()
}

/// Writes the GS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
///
/// The caller must ensure that this write operation has no unsafe side
/// effects, as the GS segment base address might be in use.
#[inline]
pub unsafe fn wrgsbase(val: u64) {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        llvm_asm!("wrgsbase $0" :: "r"(val) :: "volatile")
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner(val: u64) {
        crate::asm::x86_64_asm_wrgsbase(val)
    }

    inner(val)
}

/// Reads the GS segment base address
///
/// ## Safety
///
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
#[inline]
pub unsafe fn rdgsbase() -> u64 {
    #[cfg(feature = "inline_asm")]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        let val: u64;
        llvm_asm!("rdgsbase $0" : "=r" (val) ::: "volatile");
        val
    }

    #[cfg(not(feature = "inline_asm"))]
    #[inline(always)]
    unsafe fn inner() -> u64 {
        crate::asm::x86_64_asm_rdgsbase()
    }

    inner()
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("06.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum Action {Toggle, TurnOff, TurnOn}

#[derive(Debug, Copy, Clone, PartialEq)]
struct Point(usize, usize);

#[derive(Debug)]
struct Instruction {
    action: Action,
    point1: Point,
    point2: Point
}

fn parse_point(string: &str) -> Option<Point> {
    let mut coords = string.split(',')
        .map(|x| x.parse::<usize>())
        .map(|x| match x {
            Ok(y) => Some(y),
            Err(_) => None
        });

    match (coords.next(), coords.next()) {
        (Some(Some(x)), Some(Some(y))) if x < 1000 && y < 1000 => {
            Some(Point(x, y))
        },
        _ => return None
    }
}

fn parse_line(line: &str) -> Option<Instruction> {
    let words: Vec<&str> = line.split(' ').collect();
    let action = match words.len() {
        l if l == 4 => {
            Action::Toggle
        },
        l if l == 5 && *words.get(1).unwrap() == "off" => {
            Action::TurnOff
        },
        l if l == 5 && *words.get(1).unwrap() == "on" => {
            Action::TurnOn
        },
        _ => return None
    };

    let point1 = parse_point(*words.get(words.len() - 3).unwrap());
    let point2 = parse_point(*words.get(words.len() - 1).unwrap());

    match (point1, point2) {
        (Some(p), Some(q)) => Some(Instruction {action, point1: p, point2: q}),
        _ => None
    }
}

fn get_rectangle(p: Point, q: Point) -> Option<Vec<Point>> {
    match (p, q) {
        (Point(x1, y1), Point(x2, y2))
        if x1 < 1000 && y1 < 1000 && x2 < 1000 && y2 < 1000
        && x1 <= x2 && y1 <= y2 => {
            Some(
                (x1..x2 + 1).flat_map(move |x| {
                    (y1..y2 + 1).map(move |y| {
                        Point(x, y)
                    })
                }).collect()
            )
        },
        _ => None
    }
}

fn main() {
    let input = get_input().unwrap();
    let instructions: Vec<Instruction> = input.lines().filter_map(parse_line).collect();

    let mut lit_grid = [[false; 1000]; 1000];
    let mut brightness_grid = (0..1000).map(|_| (0..1000).map(|_| 0).collect::<Vec<_>>()).collect::<Vec<_>>();

    for &Instruction {action, point1, point2} in instructions.iter() {
        let rectangle = match get_rectangle(point1, point2) {
            Some(x) => x,
            None => continue
        };

        for Point(x, y) in rectangle.into_iter() {
            lit_grid[x][y] = match action {
                Action::Toggle => !lit_grid[x][y],
                Action::TurnOn => true,
                Action::TurnOff => false
            };

            brightness_grid[x][y] += match action {
                Action::Toggle => 2,
                Action::TurnOn => 1,
                Action::TurnOff if brightness_grid[x][y] > 0 => -1,
                _ => 0
            };
        }
    }

    let lit_count = lit_grid.into_iter()
        .flat_map(|x| x.into_iter())
        .filter(|&&x| x)
        .count();

    let brightness = brightness_grid.into_iter()
        .flat_map(|x| x.into_iter())
        .sum::<isize>();

    println!("Part 1: {}", lit_count);
    println!("Part 2: {}", brightness);
}
<commit_msg>Use .into_iter() instead of .iter()<commit_after>use std::fs::File;
use std::io::Read;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("06.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

#[derive(Debug, Copy, Clone, PartialEq)]
enum Action {Toggle, TurnOff, TurnOn}

#[derive(Debug, Copy, Clone, PartialEq)]
struct Point(usize, usize);

#[derive(Debug)]
struct Instruction {
    action: Action,
    point1: Point,
    point2: Point
}

fn parse_point(string: &str) -> Option<Point> {
    let mut coords = string.split(',')
        .map(|x| x.parse::<usize>())
        .map(|x| match x {
            Ok(y) => Some(y),
            Err(_) => None
        });

    match (coords.next(), coords.next()) {
        (Some(Some(x)), Some(Some(y))) if x < 1000 && y < 1000 => {
            Some(Point(x, y))
        },
        _ => return None
    }
}

fn parse_line(line: &str) -> Option<Instruction> {
    let words: Vec<&str> = line.split(' ').collect();
    let action = match words.len() {
        l if l == 4 => {
            Action::Toggle
        },
        l if l == 5 && *words.get(1).unwrap() == "off" => {
            Action::TurnOff
        },
        l if l == 5 && *words.get(1).unwrap() == "on" => {
            Action::TurnOn
        },
        _ => return None
    };

    let point1 = parse_point(*words.get(words.len() - 3).unwrap());
    let point2 = parse_point(*words.get(words.len() - 1).unwrap());

    match (point1, point2) {
        (Some(p), Some(q)) => Some(Instruction {action, point1: p, point2: q}),
        _ => None
    }
}

fn get_rectangle(p: Point, q: Point) -> Option<Vec<Point>> {
    match (p, q) {
        (Point(x1, y1), Point(x2, y2))
        if x1 < 1000 && y1 < 1000 && x2 < 1000 && y2 < 1000
        && x1 <= x2 && y1 <= y2 => {
            Some(
                (x1..x2 + 1).flat_map(move |x| {
                    (y1..y2 + 1).map(move |y| {
                        Point(x, y)
                    })
                }).collect()
            )
        },
        _ => None
    }
}

fn main() {
    let input = get_input().unwrap();
    let instructions: Vec<Instruction> = input.lines().filter_map(parse_line).collect();

    let mut lit_grid = [[false; 1000]; 1000];
    let mut brightness_grid = (0..1000).map(|_| {
        (0..1000).map(|_| 0).collect::<Vec<_>>()
    }).collect::<Vec<_>>();

    for Instruction {action, point1, point2} in instructions.into_iter() {
        let rectangle = match get_rectangle(point1, point2) {
            Some(x) => x,
            None => continue
        };

        for Point(x, y) in rectangle.into_iter() {
            lit_grid[x][y] = match action {
                Action::Toggle => !lit_grid[x][y],
                Action::TurnOn => true,
                Action::TurnOff => false
            };

            brightness_grid[x][y] += match action {
                Action::Toggle => 2,
                Action::TurnOn => 1,
                Action::TurnOff if brightness_grid[x][y] > 0 => -1,
                _ => 0
            };
        }
    }

    let lit_count = lit_grid.into_iter()
        .flat_map(|x| x.into_iter())
        .filter(|&&x| x)
        .count();

    let brightness = brightness_grid.into_iter()
        .flat_map(|x| x.into_iter())
        .sum::<i32>();

    println!("Part 1: {}", lit_count);
    println!("Part 2: {}", brightness);
}
<|endoftext|>


<commit_before>#![feature(attr_literals)]

#[macro_use] extern crate validator_derive;
extern crate validator;
use validator::Validate;

#[derive(Validate)]
struct Test {
    #[validate(range(min = 1, max = 2.2))]
    s: isize,
    #[validate(range(min = 1, max = 2))]
    s2: usize,
    #[validate(range(min = 18, max = 22))]
    s3: i32,
    #[validate(range(min = 18, max = 22))]
    s4: i64,
    #[validate(range(min = 18, max = 22))]
    s5: u32,
    #[validate(range(min = 18, max = 22))]
    s6: u64,
    #[validate(range(min = 18.1, max = 22))]
    s7: i8,
    #[validate(range(min = 18.0, max = 22))]
    s8: u8,
}

fn main() {}
<commit_msg>Add test for Option in range validator<commit_after>#![feature(attr_literals)]

#[macro_use] extern crate validator_derive;
extern crate validator;
use validator::Validate;

#[derive(Validate)]
struct Test {
    #[validate(range(min = 1, max = 2.2))]
    s: isize,
    #[validate(range(min = 1, max = 2))]
    s2: usize,
    #[validate(range(min = 18, max = 22))]
    s3: i32,
    #[validate(range(min = 18, max = 22))]
    s4: i64,
    #[validate(range(min = 18, max = 22))]
    s5: u32,
    #[validate(range(min = 18, max = 22))]
    s6: u64,
    #[validate(range(min = 18.1, max = 22))]
    s7: i8,
    #[validate(range(min = 18.0, max = 22))]
    s8: u8,
    #[validate(range(min = 18.0, max = 22))]
    s9: Option<u8>,
}

fn main() {}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This code used to produce the following ICE:
//
//    error: internal compiler error: get_unique_type_id_of_type() -
//    unexpected type: closure,
//    ty_unboxed_closure(syntax::ast::DefId{krate: 0u32, node: 66u32},
//    ReScope(63u32))
//
// This is a regression test for issue #17021.

#![feature(unboxed_closures, overloaded_calls)]

use std::ptr;

pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
    unsafe { *src = prod(ptr::read(src as *mut T as *const T)); }
}

pub fn main() {
    let mut a = 7u;
    let b = &mut a;
    replace_map(b, |: x: uint| x * 2);
    assert_eq!(*b, 14u);
}
<commit_msg>Build regression test for issue #17021 with -g<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This code used to produce the following ICE:
//
//    error: internal compiler error: get_unique_type_id_of_type() -
//    unexpected type: closure,
//    ty_unboxed_closure(syntax::ast::DefId{krate: 0u32, node: 66u32},
//    ReScope(63u32))
//
// This is a regression test for issue #17021.
//
// compile-flags: -g

#![feature(unboxed_closures, overloaded_calls)]

use std::ptr;

pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T {
    unsafe { *src = prod(ptr::read(src as *mut T as *const T)); }
}

pub fn main() {
    let mut a = 7u;
    let b = &mut a;
    replace_map(b, |: x: uint| x * 2);
    assert_eq!(*b, 14u);
}
<|endoftext|>


<commit_before><commit_msg>Specify types where the manual vtable relies on them<commit_after><|endoftext|>


<commit_before><commit_msg>Add `Error::cause()` method impl for `GLError`<commit_after><|endoftext|>


<commit_before>use std::path::Path;

pub fn is_song(path: &Path) -> bool {
	let extension = match path.extension() {
		Some(e) => e,
		_ => return false,
	};
	let extension = match extension.to_str() {
		Some(e) => e,
		_ => return false,
	};
	match extension.to_lowercase().as_str() {
		"mp3" => true,
		"ogg" => true,
		"m4a" => true,
		"flac" => true,
		_ => false,
	}
}

pub fn is_image(path: &Path) -> bool {
	let extension = match path.extension() {
		Some(e) => e,
		_ => return false,
	};
	let extension = match extension.to_str() {
		Some(e) => e,
		_ => return false,
	};
	match extension.to_lowercase().as_str() {
		"png" => true,
		"gif" => true,
		"jpg" => true,
		"jpeg" => true,
		"bmp" => true,
		_ => false,
	}
}<commit_msg>Extracted audio format detection from is_song()<commit_after>use std::path::Path;

pub enum AudioFormat {
	FLAC,
	MP3,
	MP4,
	MPC,
	OGG,
}

pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
	let extension = match path.extension() {
		Some(e) => e,
		_ => return None,
	};
	let extension = match extension.to_str() {
		Some(e) => e,
		_ => return None,
	};
	match extension.to_lowercase().as_str() {
		"flac" => Some(AudioFormat::FLAC),
		"mp3" => Some(AudioFormat::MP3),
		"m4a" => Some(AudioFormat::MP4),
		"mpc" => Some(AudioFormat::MPC),
		"ogg" => Some(AudioFormat::OGG),
		_ => None,
	}
}

pub fn is_song(path: &Path) -> bool {
	get_audio_format(path).is_some()
}

pub fn is_image(path: &Path) -> bool {
	let extension = match path.extension() {
		Some(e) => e,
		_ => return false,
	};
	let extension = match extension.to_str() {
		Some(e) => e,
		_ => return false,
	};
	match extension.to_lowercase().as_str() {
		"png" => true,
		"gif" => true,
		"jpg" => true,
		"jpeg" => true,
		"bmp" => true,
		_ => false,
	}
}<|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/. */

extern crate serde_json;

// Macros to help with json serializing of undeclared structs.
// json_value!({ }) retunns a serde_json::value::Value from an anonymous struct.
// json!({ }) returns a string from an anonymous struct.
// Combining both macros let you build arbitrary complex json objects easily.
//
// Examples: json!({ type: "light", value: 1.2, on: true });
//           json!({ type: "notification", value: json_value!({ r: 54, g: 12, b: 88 }) });

#[macro_export]
macro_rules! json {
    ({ $($i:ident: $v:expr),* }) => {
        {
            use std::collections::BTreeMap;
            let mut map: BTreeMap<String, serde_json::Value> = BTreeMap::new();
            $(
                map.insert(String::from(stringify!($i)), serde_json::to_value(&$v));
            )*
            serde_json::to_string(&map).unwrap_or("{}".to_owned())
        }
    };

    ([ $($v:expr),* ]) => {
        {
            use std::collections::BTreeMap;
            let mut vec: Vec<serde_json::Value> = Vec::new();
            $(
                vec.push(serde_json::to_value(&$v));
            )*
            serde_json::to_string(&vec).unwrap_or("[]".to_owned())
        }
    }
}

#[macro_export]
macro_rules! json_value {
    ({ $($i:ident: $v:expr),* }) => {
        {
            let mut map: BTreeMap<String, serde_json::Value> = BTreeMap::new();
            $(
                map.insert(String::from(stringify!($i)), serde_json::to_value(&$v));
            )*
            serde_json::to_value(&map)
        }
    };

    ([ $($v:expr),* ]) => {
        {
            let mut vec: Vec<serde_json::Value> = Vec::new();
            $(
                vec.push(serde_json::to_value(&$v));
            )*
            serde_json::to_value(&vec)
        }
    }
}

#[test]
fn test_json_macro() {
    // Object tests.
    assert_eq!(json!({ foo: "bar" }), "{\"foo\":\"bar\"}");
    assert_eq!(json!({ val: 1.02 }), "{\"val\":1.02}");
    assert_eq!(json!({ type: "light", value: 1.2, on: true }), "{\"on\":true,\"type\":\"light\",\"value\":1.2}");
    assert_eq!(json!({ array: vec![1, 2, 3]}), "{\"array\":[1,2,3]}");
    assert_eq!(json!({ type: "complex", sub: json_value!({ a: 1, b: "foo" }) }), "{\"sub\":{\"a\":1,\"b\":\"foo\"},\"type\":\"complex\"}");

    // Array tests.
    assert_eq!(json!([1, 100, 1000]), "[1,100,1000]");
    assert_eq!(json!(["one", "two", json_value!(["three", "four"]), 5]), "[\"one\",\"two\",[\"three\",\"four\"],5]");
    assert_eq!(json!(["one", 2, 3.33, false]), "[\"one\",2,3.33,false]");
}
<commit_msg>Fix unused import warning in tests. r=jlorenzo<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/. */

extern crate serde_json;

// Macros to help with json serializing of undeclared structs.
// json_value!({ }) retunns a serde_json::value::Value from an anonymous struct.
// json!({ }) returns a string from an anonymous struct.
// Combining both macros let you build arbitrary complex json objects easily.
//
// Examples: json!({ type: "light", value: 1.2, on: true });
//           json!({ type: "notification", value: json_value!({ r: 54, g: 12, b: 88 }) });

#[macro_export]
macro_rules! json {
    ({ $($i:ident: $v:expr),* }) => {
        {
            use std::collections::BTreeMap;
            let mut map: BTreeMap<String, serde_json::Value> = BTreeMap::new();
            $(
                map.insert(String::from(stringify!($i)), serde_json::to_value(&$v));
            )*
            serde_json::to_string(&map).unwrap_or("{}".to_owned())
        }
    };

    ([ $($v:expr),* ]) => {
        {
            let mut vec: Vec<serde_json::Value> = Vec::new();
            $(
                vec.push(serde_json::to_value(&$v));
            )*
            serde_json::to_string(&vec).unwrap_or("[]".to_owned())
        }
    }
}

#[macro_export]
macro_rules! json_value {
    ({ $($i:ident: $v:expr),* }) => {
        {
            let mut map: BTreeMap<String, serde_json::Value> = BTreeMap::new();
            $(
                map.insert(String::from(stringify!($i)), serde_json::to_value(&$v));
            )*
            serde_json::to_value(&map)
        }
    };

    ([ $($v:expr),* ]) => {
        {
            let mut vec: Vec<serde_json::Value> = Vec::new();
            $(
                vec.push(serde_json::to_value(&$v));
            )*
            serde_json::to_value(&vec)
        }
    }
}

#[test]
fn test_json_macro() {
    // Object tests.
    assert_eq!(json!({ foo: "bar" }), "{\"foo\":\"bar\"}");
    assert_eq!(json!({ val: 1.02 }), "{\"val\":1.02}");
    assert_eq!(json!({ type: "light", value: 1.2, on: true }), "{\"on\":true,\"type\":\"light\",\"value\":1.2}");
    assert_eq!(json!({ array: vec![1, 2, 3]}), "{\"array\":[1,2,3]}");
    assert_eq!(json!({ type: "complex", sub: json_value!({ a: 1, b: "foo" }) }), "{\"sub\":{\"a\":1,\"b\":\"foo\"},\"type\":\"complex\"}");

    // Array tests.
    assert_eq!(json!([1, 100, 1000]), "[1,100,1000]");
    assert_eq!(json!(["one", "two", json_value!(["three", "four"]), 5]), "[\"one\",\"two\",[\"three\",\"four\"],5]");
    assert_eq!(json!(["one", 2, 3.33, false]), "[\"one\",2,3.33,false]");
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::{CString, OsString};
use std::os::unix::ffi::OsStringExt;
use std::ptr;

use errno;
use libc;

fn osstring2cstring(s: &OsString) -> CString {
    unsafe { CString::from_vec_unchecked(s.clone().into_vec()) }
}

fn split_string(s: &OsString) -> Vec<OsString> {
    match s.clone().into_string() {
        Ok(cmd) => cmd.split_whitespace().map(OsString::from).collect(),
        Err(cmd) => vec![cmd],
    }
}

// Helper wrappers around libc::* API
pub fn fork() -> libc::pid_t {
    unsafe { libc::fork() }
}

pub fn execvp(cmd: &OsString) {
    let cstrings = split_string(cmd).iter().map(osstring2cstring).collect::<Vec<_>>();
    let mut args = cstrings.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();

    args.push(ptr::null());
    errno::set_errno(errno::Errno(0));
    unsafe { libc::execvp(args[0], args.as_ptr()) };
}

pub fn dup2(fd1: i32, fd2: i32) {
    assert!(unsafe { libc::dup2(fd1, fd2) } > -1);
}

pub fn close(fd: i32) {
    assert_eq!(unsafe { libc::close(fd) }, 0);
}

pub fn pipe() -> (i32, i32) {
    let mut fds = [0; 2];
    assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0);
    (fds[0], fds[1])
}

fn which(exec: &str) -> Option<OsString> {
    if let Some(path) = env::var_os("PATH") {
        let paths = env::split_paths(&path);
        for path in paths {
            let candidate = path.join(exec);
            if path.join(exec).exists() {
                return Some(candidate.into_os_string());
            }
        }
    }
    None
}

pub fn find_pager(env: &str) -> Option<OsString> {
    if env::var_os("NOPAGER").is_some() {
        return None;
    }
    let default_pager = || which("more");
    env::var_os(env).or_else(default_pager)
}

#[cfg(test)]
mod tests {
    use super::{find_pager, which};
    use std::ffi::OsString;

    #[cfg(target_os = "linux")]
    const MORE: &'static str = "/bin/more";

    #[cfg(target_os = "macos")]
    const MORE: &'static str = "/usr/bin/more";

    #[test]
    fn more_found_in_path() {
        assert!(which("more").is_some())
    }

    #[test]
    fn erom_not_found_in_path() {
        assert!(which("erom").is_none())
    }

    #[test]
    fn which_more() {
        assert_eq!(which("more"), Some(OsString::from(MORE)));
    }

    #[test]
    fn usr_bin_more_default_pager() {
        assert_eq!(find_pager("__RANDOM_NAME"), Some(OsString::from(MORE)));
    }
}
<commit_msg>whitespaces<commit_after>use std::env;
use std::ffi::{CString, OsString};
use std::os::unix::ffi::OsStringExt;
use std::ptr;

use errno;
use libc;

fn osstring2cstring(s: &OsString) -> CString {
    unsafe { CString::from_vec_unchecked(s.clone().into_vec()) }
}

fn split_string(s: &OsString) -> Vec<OsString> {
    match s.clone().into_string() {
        Ok(cmd) => cmd.split_whitespace().map(OsString::from).collect(),
        Err(cmd) => vec![cmd],
    }
}

// Helper wrappers around libc::* API
pub fn fork() -> libc::pid_t {
    unsafe { libc::fork() }
}

pub fn execvp(cmd: &OsString) {
    let cstrings = split_string(cmd).iter().map(osstring2cstring).collect::<Vec<_>>();
    let mut args = cstrings.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
    args.push(ptr::null());
    errno::set_errno(errno::Errno(0));
    unsafe { libc::execvp(args[0], args.as_ptr()) };
}

pub fn dup2(fd1: i32, fd2: i32) {
    assert!(unsafe { libc::dup2(fd1, fd2) } > -1);
}

pub fn close(fd: i32) {
    assert_eq!(unsafe { libc::close(fd) }, 0);
}

pub fn pipe() -> (i32, i32) {
    let mut fds = [0; 2];
    assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0);
    (fds[0], fds[1])
}

fn which(exec: &str) -> Option<OsString> {
    if let Some(path) = env::var_os("PATH") {
        let paths = env::split_paths(&path);
        for path in paths {
            let candidate = path.join(exec);
            if path.join(exec).exists() {
                return Some(candidate.into_os_string());
            }
        }
    }
    None
}

pub fn find_pager(env: &str) -> Option<OsString> {
    if env::var_os("NOPAGER").is_some() {
        return None;
    }
    let default_pager = || which("more");
    env::var_os(env).or_else(default_pager)
}

#[cfg(test)]
mod tests {
    use super::{find_pager, which};
    use std::ffi::OsString;

    #[cfg(target_os = "linux")]
    const MORE: &'static str = "/bin/more";

    #[cfg(target_os = "macos")]
    const MORE: &'static str = "/usr/bin/more";

    #[test]
    fn more_found_in_path() {
        assert!(which("more").is_some())
    }

    #[test]
    fn erom_not_found_in_path() {
        assert!(which("erom").is_none())
    }

    #[test]
    fn which_more() {
        assert_eq!(which("more"), Some(OsString::from(MORE)));
    }

    #[test]
    fn usr_bin_more_default_pager() {
        assert_eq!(find_pager("__RANDOM_NAME"), Some(OsString::from(MORE)));
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use alloc::boxed::Box;
use collections::string::String;
use core::{ptr, mem, raw, fmt};
use core::ptr::RawMutPtr;
use core::any::{Any, AnyRefExt};
use core::fmt::Show;
use core::iter;
use libc::{c_void, c_char};
use core::borrow::IntoCow;
use collections::vec::Vec;
use collections::str::MaybeOwned;

use jni::{jobject, jclass, jmethodID, jfieldID, JNIEnv, jint, jstring, jvalue, JNINativeMethod, JavaVM};
#[cfg(target_word_size = "64")] use jni::jlong;
use jni_constants::*;

use glinit::GLInit;
use drawevent::Events;
use glcommon::MString;
use libc::types::os::arch::posix88::pid_t;

use std;

extern "C" {
    pub fn gettid() -> pid_t;
}

#[macro_use]
mod macros;
pub mod texturethread;
pub mod android_bitmap;
pub mod gldataclasses;
pub mod motionevent;

#[cfg(target_word_size = "32")]
#[allow(non_camel_case_types)]
pub type jpointer = jint;
#[cfg(target_word_size = "64")]
#[allow(non_camel_case_types)]
pub type jpointer = jlong;

struct CaseClass {
    constructor: jmethodID,
    class: jclass,
}

static mut GL_EXCEPTION: CaseClass = CaseClass { constructor: 0 as jmethodID, class: 0 as jclass };

struct GLInitEvents<'a> {
    glinit: GLInit<'a>,
    events: Events<'a>,
    jni_undo_callback: JNIUndoCallback,
    owning_thread: pid_t,
    //lua: LuaInterpolatorState<LuaCallbackType>,
}

#[deriving(Copy)]
pub struct JNIUndoCallback {
    callback_obj: jobject,
    callback_method: jmethodID,
}

pub struct JNICallbackClosure<'a> {
    undo_callback: &'a JNIUndoCallback,
    env: *mut JNIEnv,
}

impl JNIUndoCallback {
    pub unsafe fn new(env: *mut JNIEnv, obj: jobject) -> JNIUndoCallback {
        let obj = ((**env).NewGlobalRef)(env, obj);
        let objclass = ((**env).GetObjectClass)(env, obj);
        let method = ((**env).GetMethodID)(env, objclass, cstr!("undoBufferChanged"), cstr!("(I)V"));
        JNIUndoCallback { callback_obj: obj, callback_method: method }
    }

    pub unsafe fn call(&self, env: *mut JNIEnv, new_undo_size: i32) {
        ((**env).CallVoidMethod)(env, self.callback_obj, self.callback_method, new_undo_size as jint);
    }

    pub unsafe fn destroy(self, env: *mut JNIEnv) {
        ((**env).DeleteGlobalRef)(env, self.callback_obj);
    }
    pub fn create_closure(&self, env: *mut JNIEnv) -> JNICallbackClosure {
        JNICallbackClosure { undo_callback: self, env: env }
    }
}

impl CaseClass {
    pub unsafe fn new(env: *mut JNIEnv, name: *const c_char, sig: *const c_char) -> CaseClass {
        let class = ((**env).FindClass)(env, name);
        let constructor = ((**env).GetMethodID)(env, class, cstr!("<init>"), sig);
        let globalclass = ((**env).NewGlobalRef)(env, class);

        CaseClass { constructor: constructor, class: globalclass }
    }
    pub unsafe fn construct(&self, env: *mut JNIEnv, arg: &mut [jvalue]) -> jobject {
        ((**env).NewObjectA)(env, self.class, self.constructor, arg.as_mut_ptr())
    }
    pub unsafe fn destroy(&mut self, env: *mut JNIEnv) {
        ((**env).DeleteGlobalRef)(env, self.class);
    }
}

unsafe fn get_string(env: *mut JNIEnv, string: jstring) -> Option<String> {
    let string = try_opt!(string.as_mut());
    let c = try_opt!(((**env).GetStringChars)(env, string, ptr::null_mut()).as_ref());
    let len = ((**env).GetStringLength)(env, string);
    let strslice: &[u16] = mem::transmute(raw::Slice { data: c, len: len as uint });
    let ruststr = String::from_utf16(strslice);
    ((**env).ReleaseStringChars)(env, string as jstring, strslice.as_ptr());
    Some(try_opt!(ruststr))
}

unsafe fn get_mstring(env: *mut JNIEnv, string: jstring) -> Option<MString> {
    match get_string(env, string) {
        Some(s) => Some(s.into_cow()),
        None => None,
    }
}

unsafe fn str_to_jstring(env: *mut JNIEnv, s: &str) -> jstring {
    let u16msg: Vec<u16> = s.utf16_units().collect();
    ((**env).NewString)(env, u16msg.as_ptr(), u16msg.len() as i32)
}

pub unsafe fn register_classmethods(env: *mut JNIEnv, classname: *const i8, methods: &[JNINativeMethod]) {
    let class = ((**env).FindClass)(env, classname);
    ((**env).RegisterNatives)(env, class, methods.as_ptr(), methods.len() as i32);
}

fn get_safe_data<'a>(data: jpointer) -> &'a mut GLInitEvents<'a> {
    unsafe {
        let data: &'a mut GLInitEvents<'a> = mem::transmute(data);
        assert_eq!(gettid(), data.owning_thread);
        data
    }
}

#[cfg(target_word_size = "32")]
#[inline(always)]
unsafe fn get_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    ((**env).GetIntField)(env, obj, field)
}
#[cfg(target_word_size = "64")]
#[inline(always)]
unsafe fn get_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    ((**env).GetLongField)(env, obj, field)
}

//#[cfg(target_word_size = "32")]
//#[inline(always)]
//fn set_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    //((**env).SetIntField)(env, obj, field)
//}
//#[cfg(target_word_size = "64")]
//#[inline(always)]
//fn set_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    //((**env).SetLongField)(env, obj, field)
//}

fn on_unwind(msg: &(Any + Send), file: &'static str, line: uint) {
    use core::fmt::FormatWriter;
    // as far as I know there's no way to identify traits that can be cast to Show at runtime
    if let Some(s) = msg.downcast_ref::<&Show>() {
        loge!("fatal error in {}:{} as &Show: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<Box<Show>>() {
        loge!("fatal error in {}:{} as Box<Show>: {}", file, line, &**s);
    } else if let Some(s) = msg.downcast_ref::<&str>() {
        loge!("fatal error in {}:{} as &str: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<String>() {
        loge!("fatal error in {}:{} as String: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<MaybeOwned<'static>>() {
        loge!("fatal error in {}:{} as MaybeOwned: {}", file, line, s);
    } else {
        loge!("fatal error in {}:{}: unknown error message type {}!", file, line, msg.get_type_id());
        loge!("Printing start:");
        unsafe {
            let mut line = Vec::new();
            // stolen from unwind.rs
            struct VecWriter<'a> { v: &'a mut Vec<u8> }
            impl<'a> ::core::fmt::FormatWriter for VecWriter<'a> {
                fn write(&mut self, buf: &[u8]) -> fmt::Result {
                    self.v.push_all(buf);
                    Ok(())
                }
            }

            let width = 32;
            let raw::TraitObject { data: msgptr, vtable: _ } = mem::transmute(msg);
            let msgslice: &[u8] = mem::transmute(raw::Slice { data: msgptr as *const (), len: 1000 });
            let poscounter = iter::count(msgptr as u32, width as u32);
            for (chunk, pos) in msgslice.chunks(width).zip(poscounter) {
                {
                    let mut writer = VecWriter { v: &mut line };
                    let _ = write!(&mut writer, "{:08x}: ", pos);
                    for byte in chunk.iter() {
                        let _ = write!(&mut writer, "{} ", byte);
                    }
                }
                loge!("{}", ::core::str::from_utf8_unchecked(line.as_slice().init()));
                line.clear();
            }
        }
    }
    // Unwinding always fails, but not before messing up android's crash report backtrace.
    // So, commit suicide before that can happen.
    unsafe {
        let null: *mut u16 = ptr::null_mut();
        *null = 0xdead;
    }
}

#[allow(non_snake_case, unused_variables)]
#[no_mangle]
pub unsafe extern "C" fn JNI_OnLoad(vm: *mut JavaVM, reserved: *mut c_void) -> jint {
    logi!("jni onload!!");
    let mut env: *mut c_void = ptr::null_mut();
    if ((**vm).GetEnv)(vm, (&mut env as *mut *mut c_void), JNI_VERSION_1_6) != JNI_OK {
        return -1;
    }
    let env = env as *mut JNIEnv;
    logi!("got environment!: {}", env);

    texturethread::init(env);
    texturethread::init(env);
    android_bitmap::init(env);
    gldataclasses::init(env);
    motionevent::init(env);

    GL_EXCEPTION = CaseClass::new(env, cstr!("com/github/wartman4404/gldraw/GLException"), cstr!("(Ljava/lang/String;)V"));

    //rustrt::init(1, ["rustjni".as_ptr()].as_ptr());
    std::rt::unwind::register(on_unwind);

    logi!("finished jni_onload");
    JNI_VERSION_1_2
}

#[allow(non_snake_case, unused_variables)]
#[no_mangle]
pub unsafe extern "C" fn JNI_OnUnload(vm: *mut JavaVM, reserved: *mut c_void) {
    logi!("jni onload!!");
    let mut env: *mut c_void = ptr::null_mut();
    if ((**vm).GetEnv)(vm, (&mut env as *mut *mut c_void), JNI_VERSION_1_6) != JNI_OK {
        return;
    }
    let env = env as *mut JNIEnv;
    texturethread::destroy(env);
    texturethread::destroy(env);
    android_bitmap::destroy(env);
    gldataclasses::destroy(env);
    motionevent::destroy(env);
    GL_EXCEPTION.destroy(env);
}
<commit_msg>apparently cfg(target_word_size) isn't 32 or 64<commit_after>use core::prelude::*;
use alloc::boxed::Box;
use collections::string::String;
use core::{ptr, mem, raw, fmt};
use core::ptr::RawMutPtr;
use core::any::{Any, AnyRefExt};
use core::fmt::Show;
use core::iter;
use libc::{c_void, c_char};
use core::borrow::IntoCow;
use collections::vec::Vec;
use collections::str::MaybeOwned;

use jni::{jobject, jclass, jmethodID, jfieldID, JNIEnv, jint, jstring, jvalue, JNINativeMethod, JavaVM};
#[cfg(target_word_size = "64")] use jni::jlong;
use jni_constants::*;

use glinit::GLInit;
use drawevent::Events;
use glcommon::MString;
use libc::types::os::arch::posix88::pid_t;

use std;

extern "C" {
    pub fn gettid() -> pid_t;
}

#[macro_use]
mod macros;
pub mod texturethread;
pub mod android_bitmap;
pub mod gldataclasses;
pub mod motionevent;

#[cfg(not(target_word_size = "64"))]
#[allow(non_camel_case_types)]
pub type jpointer = jint;
#[cfg(target_word_size = "64")]
#[allow(non_camel_case_types)]
pub type jpointer = jlong;

struct CaseClass {
    constructor: jmethodID,
    class: jclass,
}

static mut GL_EXCEPTION: CaseClass = CaseClass { constructor: 0 as jmethodID, class: 0 as jclass };

struct GLInitEvents<'a> {
    glinit: GLInit<'a>,
    events: Events<'a>,
    jni_undo_callback: JNIUndoCallback,
    owning_thread: pid_t,
    //lua: LuaInterpolatorState<LuaCallbackType>,
}

#[deriving(Copy)]
pub struct JNIUndoCallback {
    callback_obj: jobject,
    callback_method: jmethodID,
}

pub struct JNICallbackClosure<'a> {
    undo_callback: &'a JNIUndoCallback,
    env: *mut JNIEnv,
}

impl JNIUndoCallback {
    pub unsafe fn new(env: *mut JNIEnv, obj: jobject) -> JNIUndoCallback {
        let obj = ((**env).NewGlobalRef)(env, obj);
        let objclass = ((**env).GetObjectClass)(env, obj);
        let method = ((**env).GetMethodID)(env, objclass, cstr!("undoBufferChanged"), cstr!("(I)V"));
        JNIUndoCallback { callback_obj: obj, callback_method: method }
    }

    pub unsafe fn call(&self, env: *mut JNIEnv, new_undo_size: i32) {
        ((**env).CallVoidMethod)(env, self.callback_obj, self.callback_method, new_undo_size as jint);
    }

    pub unsafe fn destroy(self, env: *mut JNIEnv) {
        ((**env).DeleteGlobalRef)(env, self.callback_obj);
    }
    pub fn create_closure(&self, env: *mut JNIEnv) -> JNICallbackClosure {
        JNICallbackClosure { undo_callback: self, env: env }
    }
}

impl CaseClass {
    pub unsafe fn new(env: *mut JNIEnv, name: *const c_char, sig: *const c_char) -> CaseClass {
        let class = ((**env).FindClass)(env, name);
        let constructor = ((**env).GetMethodID)(env, class, cstr!("<init>"), sig);
        let globalclass = ((**env).NewGlobalRef)(env, class);

        CaseClass { constructor: constructor, class: globalclass }
    }
    pub unsafe fn construct(&self, env: *mut JNIEnv, arg: &mut [jvalue]) -> jobject {
        ((**env).NewObjectA)(env, self.class, self.constructor, arg.as_mut_ptr())
    }
    pub unsafe fn destroy(&mut self, env: *mut JNIEnv) {
        ((**env).DeleteGlobalRef)(env, self.class);
    }
}

unsafe fn get_string(env: *mut JNIEnv, string: jstring) -> Option<String> {
    let string = try_opt!(string.as_mut());
    let c = try_opt!(((**env).GetStringChars)(env, string, ptr::null_mut()).as_ref());
    let len = ((**env).GetStringLength)(env, string);
    let strslice: &[u16] = mem::transmute(raw::Slice { data: c, len: len as uint });
    let ruststr = String::from_utf16(strslice);
    ((**env).ReleaseStringChars)(env, string as jstring, strslice.as_ptr());
    Some(try_opt!(ruststr))
}

unsafe fn get_mstring(env: *mut JNIEnv, string: jstring) -> Option<MString> {
    match get_string(env, string) {
        Some(s) => Some(s.into_cow()),
        None => None,
    }
}

unsafe fn str_to_jstring(env: *mut JNIEnv, s: &str) -> jstring {
    let u16msg: Vec<u16> = s.utf16_units().collect();
    ((**env).NewString)(env, u16msg.as_ptr(), u16msg.len() as i32)
}

pub unsafe fn register_classmethods(env: *mut JNIEnv, classname: *const i8, methods: &[JNINativeMethod]) {
    let class = ((**env).FindClass)(env, classname);
    ((**env).RegisterNatives)(env, class, methods.as_ptr(), methods.len() as i32);
}

fn get_safe_data<'a>(data: jpointer) -> &'a mut GLInitEvents<'a> {
    unsafe {
        let data: &'a mut GLInitEvents<'a> = mem::transmute(data);
        assert_eq!(gettid(), data.owning_thread);
        data
    }
}

#[cfg(not(target_word_size = "64"))]
#[inline(always)]
unsafe fn get_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    ((**env).GetIntField)(env, obj, field)
}
#[cfg(target_word_size = "64")]
#[inline(always)]
unsafe fn get_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    ((**env).GetLongField)(env, obj, field)
}

//#[cfg(target_word_size = "32")]
//#[inline(always)]
//fn set_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    //((**env).SetIntField)(env, obj, field)
//}
//#[cfg(target_word_size = "64")]
//#[inline(always)]
//fn set_jpointer(env: *mut JNIEnv, obj: jobject, field: jfieldID) -> jpointer {
    //((**env).SetLongField)(env, obj, field)
//}

fn on_unwind(msg: &(Any + Send), file: &'static str, line: uint) {
    use core::fmt::FormatWriter;
    // as far as I know there's no way to identify traits that can be cast to Show at runtime
    if let Some(s) = msg.downcast_ref::<&Show>() {
        loge!("fatal error in {}:{} as &Show: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<Box<Show>>() {
        loge!("fatal error in {}:{} as Box<Show>: {}", file, line, &**s);
    } else if let Some(s) = msg.downcast_ref::<&str>() {
        loge!("fatal error in {}:{} as &str: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<String>() {
        loge!("fatal error in {}:{} as String: {}", file, line, s);
    } else if let Some(s) = msg.downcast_ref::<MaybeOwned<'static>>() {
        loge!("fatal error in {}:{} as MaybeOwned: {}", file, line, s);
    } else {
        loge!("fatal error in {}:{}: unknown error message type {}!", file, line, msg.get_type_id());
        loge!("Printing start:");
        unsafe {
            let mut line = Vec::new();
            // stolen from unwind.rs
            struct VecWriter<'a> { v: &'a mut Vec<u8> }
            impl<'a> ::core::fmt::FormatWriter for VecWriter<'a> {
                fn write(&mut self, buf: &[u8]) -> fmt::Result {
                    self.v.push_all(buf);
                    Ok(())
                }
            }

            let width = 32;
            let raw::TraitObject { data: msgptr, vtable: _ } = mem::transmute(msg);
            let msgslice: &[u8] = mem::transmute(raw::Slice { data: msgptr as *const (), len: 1000 });
            let poscounter = iter::count(msgptr as u32, width as u32);
            for (chunk, pos) in msgslice.chunks(width).zip(poscounter) {
                {
                    let mut writer = VecWriter { v: &mut line };
                    let _ = write!(&mut writer, "{:08x}: ", pos);
                    for byte in chunk.iter() {
                        let _ = write!(&mut writer, "{} ", byte);
                    }
                }
                loge!("{}", ::core::str::from_utf8_unchecked(line.as_slice().init()));
                line.clear();
            }
        }
    }
    // Unwinding always fails, but not before messing up android's crash report backtrace.
    // So, commit suicide before that can happen.
    unsafe {
        let null: *mut u16 = ptr::null_mut();
        *null = 0xdead;
    }
}

#[allow(non_snake_case, unused_variables)]
#[no_mangle]
pub unsafe extern "C" fn JNI_OnLoad(vm: *mut JavaVM, reserved: *mut c_void) -> jint {
    logi!("jni onload!!");
    let mut env: *mut c_void = ptr::null_mut();
    if ((**vm).GetEnv)(vm, (&mut env as *mut *mut c_void), JNI_VERSION_1_6) != JNI_OK {
        return -1;
    }
    let env = env as *mut JNIEnv;
    logi!("got environment!: {}", env);

    texturethread::init(env);
    texturethread::init(env);
    android_bitmap::init(env);
    gldataclasses::init(env);
    motionevent::init(env);

    GL_EXCEPTION = CaseClass::new(env, cstr!("com/github/wartman4404/gldraw/GLException"), cstr!("(Ljava/lang/String;)V"));

    //rustrt::init(1, ["rustjni".as_ptr()].as_ptr());
    std::rt::unwind::register(on_unwind);

    logi!("finished jni_onload");
    JNI_VERSION_1_2
}

#[allow(non_snake_case, unused_variables)]
#[no_mangle]
pub unsafe extern "C" fn JNI_OnUnload(vm: *mut JavaVM, reserved: *mut c_void) {
    logi!("jni onload!!");
    let mut env: *mut c_void = ptr::null_mut();
    if ((**vm).GetEnv)(vm, (&mut env as *mut *mut c_void), JNI_VERSION_1_6) != JNI_OK {
        return;
    }
    let env = env as *mut JNIEnv;
    texturethread::destroy(env);
    texturethread::destroy(env);
    android_bitmap::destroy(env);
    gldataclasses::destroy(env);
    motionevent::destroy(env);
    GL_EXCEPTION.destroy(env);
}
<|endoftext|>


<commit_before>use markup5ever::QualName;

use crate::error::*;

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(String),
}

impl Input {
    pub fn parse(attr: QualName, s: &str) -> Result<Input, NodeError> {
        match s {
            "SourceGraphic" => Ok(Input::SourceGraphic),
            "SourceAlpha" => Ok(Input::SourceAlpha),
            "BackgroundImage" => Ok(Input::BackgroundImage),
            "BackgroundAlpha" => Ok(Input::BackgroundAlpha),
            "FillPaint" => Ok(Input::FillPaint),
            "StrokePaint" => Ok(Input::StrokePaint),
            s if !s.is_empty() => Ok(Input::FilterOutput(s.to_string())),
            _ => Err(ValueErrorKind::parse_error("invalid value")).attribute(attr),
        }
    }
}
<commit_msg>filters/input.rs: Implement the CSS custom-ident type<commit_after>use cssparser::{Parser, Token};
use markup5ever::QualName;

use crate::error::*;
use crate::parsers::Parse;

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(String),
}

/// https://www.w3.org/TR/css-values-4/#custom-idents
#[derive(Debug, PartialEq)]
pub struct CustomIdent(String);

impl Input {
    pub fn parse(attr: QualName, s: &str) -> Result<Input, NodeError> {
        match s {
            "SourceGraphic" => Ok(Input::SourceGraphic),
            "SourceAlpha" => Ok(Input::SourceAlpha),
            "BackgroundImage" => Ok(Input::BackgroundImage),
            "BackgroundAlpha" => Ok(Input::BackgroundAlpha),
            "FillPaint" => Ok(Input::FillPaint),
            "StrokePaint" => Ok(Input::StrokePaint),
            s if !s.is_empty() => Ok(Input::FilterOutput(s.to_string())),
            _ => Err(ValueErrorKind::parse_error("invalid value")).attribute(attr),
        }
    }
}

impl Parse for CustomIdent {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        let loc = parser.current_source_location();
        let token = parser.next()?;

        match token {
            // CSS-wide keywords and "default" are errors here
            // https://www.w3.org/TR/css-values-4/#css-wide-keywords
            Token::Ident(ref cow) => {
                for s in &["initial", "inherit", "unset", "default"] {
                    if cow.eq_ignore_ascii_case(s) {
                        Err(loc.new_basic_unexpected_token_error(token.clone()))?
                    }
                }

                Ok(CustomIdent(cow.as_ref().to_string()))
            }

            _ => Err(loc.new_basic_unexpected_token_error(token.clone()))?,
        }
    }
}

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

    #[test]
    fn parses_custom_ident() {
        assert_eq!(
            CustomIdent::parse_str("hello"),
            Ok(CustomIdent("hello".to_string()))
        );
    }

    #[test]
    fn invalid_custom_ident_yields_error() {
        assert!(CustomIdent::parse_str("initial").is_err());
        assert!(CustomIdent::parse_str("inherit").is_err());
        assert!(CustomIdent::parse_str("unset").is_err());
        assert!(CustomIdent::parse_str("default").is_err());
        assert!(CustomIdent::parse_str("").is_err());
    }
}
<|endoftext|>


<commit_before>use ruma_identifiers::{RoomAliasId, RoomId};

mod empty_response {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            #[ruma_api(path)]
            pub room_alias: &'a RoomAliasId,

            /// The room ID to set.
            pub room_id: &'a RoomId,
        }

        response: {}

    }
}

mod nested_types {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            pub room_alias: &'a [Option<&'a RoomAliasId>],

            /// The room ID to set.
            pub room_id: &'b [Option<Option<&'a ruma_identifiers::DeviceId>>],
        }

        response: {}

    }
}

mod full_request_response {
    #[allow(unused)]
    #[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct OtherThing<'t> {
        some: &'t str,
        t: &'t [u8],
    }

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct IncomingOtherThing {
        some: String,
        t: Vec<u8>,
    }

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: GET,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query)]
            pub abc: &'a str,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod full_request_response_with_query_map {
    #[allow(unused)]
    #[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct OtherThing<'t> {
        some: &'t str,
        t: &'t [u8],
    }

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct IncomingOtherThing {
        some: String,
        t: Vec<u8>,
    }

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: GET,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query_map)]
            // pub abc: &'a [(&'a str, &'a str)],
            pub abc: &'a [(String, String)],
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}
<commit_msg>Add a query_map field to ruma_api! lifetime test<commit_after>use ruma_identifiers::{RoomAliasId, RoomId};

mod empty_response {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            #[ruma_api(path)]
            pub room_alias: &'a RoomAliasId,

            /// The room ID to set.
            pub room_id: &'a RoomId,
        }

        response: {}

    }
}

mod nested_types {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            pub room_alias: &'a [Option<&'a RoomAliasId>],

            /// The room ID to set.
            pub room_id: &'b [Option<Option<&'a ruma_identifiers::DeviceId>>],
        }

        response: {}

    }
}

mod full_request_response {
    #[allow(unused)]
    #[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct OtherThing<'t> {
        some: &'t str,
        t: &'t [u8],
    }

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct IncomingOtherThing {
        some: String,
        t: Vec<u8>,
    }

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: POST,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query)]
            pub abc: &'a str,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
            pub more: OtherThing<'t>,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod full_request_response_with_query_map {
    #[allow(unused)]
    #[derive(Copy, Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct OtherThing<'t> {
        some: &'t str,
        t: &'t [u8],
    }

    #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
    pub struct IncomingOtherThing {
        some: String,
        t: Vec<u8>,
    }

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: GET,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query_map)]
            // pub abc: &'a [(&'a str, &'a str)], // TODO This does not impl Deserialize
            pub abc: Vec<(String, String)>,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicity Copy trait - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);
}
<commit_msg>wow how do I always typo that this way<commit_after>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicit Copy trait - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);
}
<|endoftext|>