<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::ffi::OsString;

use common::ui::UI;
use hcore::crypto::CACHE_KEY_PATH_ENV_VAR;
use hcore::env as henv;
use hcore::fs::CACHE_KEY_PATH;
use hcore::os::users;

use config;
use error::Result;
use VERSION;

pub const DOCKER_IMAGE: &'static str = "habitat-docker-registry.bintray.io/studio";
const DOCKER_CMD: &'static str = "docker";
const DOCKER_CMD_ENVVAR: &'static str = "HAB_DOCKER_BINARY";
const DOCKER_IMAGE_ENVVAR: &'static str = "HAB_DOCKER_STUDIO_IMAGE";

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    // If the `$HAB_ORIGIN` environment variable is not present, then see if a default is set in
    // the CLI config. If so, set it as the `$HAB_ORIGIN` environment variable for the `hab-studio`
    // or `docker` execv call.
    if henv::var("HAB_ORIGIN").is_err() {
        let config = try!(config::load_with_sudo_user());
        if let Some(default_origin) = config.origin {
            debug!("Setting default origin {} via CLI config", &default_origin);
            env::set_var("HAB_ORIGIN", default_origin);
        }
    }

    // If the `$HAB_CACHE_KEY_PATH` environment variable is not present, check if we are running
    // under a `sudo` invocation. If so, determine the non-root user that issued the command in
    // order to set their key cache location in the environment variable. This is done so that the
    // `hab-studio` command will find the correct key cache or so that the correct directory will
    // be volume mounted when used with Docker.
    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        if let Some(sudo_user) = henv::sudo_user() {
            if let Some(home) = users::get_home_for_user(&sudo_user) {
                let cache_key_path = home.join(format!(".{}", CACHE_KEY_PATH));
                debug!("Setting cache_key_path for SUDO_USER={} to: {}",
                       &sudo_user,
                       cache_key_path.display());
                env::set_var(CACHE_KEY_PATH_ENV_VAR, cache_key_path);
                // Prevent any inner `hab` invocations from triggering similar logic: we will be
                // operating in the context `hab-studio` which is running with rootlike privileges.
                env::remove_var("SUDO_USER");
            }
        }
    }

    inner::start(ui, args)
}

/// Retrieves the
pub fn image_identifier() -> String {
    let version: Vec<&str> = VERSION.split("/").collect();
    henv::var(DOCKER_IMAGE_ENVVAR).unwrap_or(format!("{}:{}", DOCKER_IMAGE, version[0]))
}

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

    #[test]
    fn retrieve_image_identifier() {
        assert_eq!(image_identifier(), format!("{}:{}", DOCKER_IMAGE, VERSION));
    }
}

#[cfg(target_os = "linux")]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;

    const STUDIO_CMD: &'static str = "hab-studio";
    const STUDIO_CMD_ENVVAR: &'static str = "HAB_STUDIO_BINARY";
    const STUDIO_PACKAGE_IDENT: &'static str = "core/hab-studio";

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = try!(PackageIdent::from_str(STUDIO_PACKAGE_IDENT));
                try!(exec::command_from_pkg(ui,
                                            STUDIO_CMD,
                                            &ident,
                                            &default_cache_key_path(None),
                                            0))
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            try!(exec::exec_command(cmd, args));
        } else {
            return Err(Error::ExecCommandNotFound(command.to_string_lossy().into_owned()));
        }
        Ok(())
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::process::{Command, exit};

    use common::ui::UI;
    use hcore::crypto::default_cache_key_path;
    use hcore::env as henv;
    use hcore::fs::{CACHE_KEY_PATH, find_command};

    use error::{Error, Result};
    use super::{DOCKER_CMD, DOCKER_CMD_ENVVAR, image_identifier};

    pub fn start(_ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let docker = henv::var(DOCKER_CMD_ENVVAR).unwrap_or(DOCKER_CMD.to_string());

        let cmd = match find_command(&docker) {
            Some(cmd) => cmd,
            None => return Err(Error::ExecCommandNotFound(docker.to_string())),
        };

        let mut command = Command::new(&cmd);
        command.arg("run")
            .arg("--rm")
            .arg("--tty")
            .arg("--interactive")
            .arg("--privileged");

        let env_vars = vec!["HAB_DEPOT_URL", "HAB_ORIGIN", "http_proxy", "https_proxy"];
        for var in env_vars {
            if let Ok(val) = henv::var(var) {
                debug!("Propagating environment variable into container: {}={}",
                       var,
                       val);
                command.arg("--env");
                command.arg(format!("{}={}", var, val));
            }
        }

        command.arg("--volume")
            .arg("/var/run/docker.sock:/var/run/docker.sock")
            .arg("--volume")
            .arg(format!("{}:/{}",
                     default_cache_key_path(None).to_string_lossy(),
                     CACHE_KEY_PATH))
            .arg("--volume")
            .arg(format!("{}:/src", env::current_dir().unwrap().to_string_lossy()))
            .arg(image_identifier());

        for arg in &args {
            command.arg(arg);
        }

        for var in vec!["http_proxy", "https_proxy"] {
            if let Ok(_) = henv::var(var) {
                debug!("Unsetting proxy environment variable '{}' before calling `{}'",
                       var,
                       docker);
                env::remove_var(var);
            }
        }

        let status = command.status().expect(&(format!("{:?} failed to start.", &cmd)));
        // Replace with specific errors based on exit code?
        // https://docs.docker.com/engine/reference/run/#/exit-status
        // this currently just passes the exit code from Docker directly.
        exit(status.code().unwrap())
    }
}
<commit_msg>[hab] Refactor constants to remove unused warns in studio subcmd.<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::ffi::OsString;

use common::ui::UI;
use hcore::crypto::CACHE_KEY_PATH_ENV_VAR;
use hcore::env as henv;
use hcore::fs::CACHE_KEY_PATH;
use hcore::os::users;

use config;
use error::Result;

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    // If the `$HAB_ORIGIN` environment variable is not present, then see if a default is set in
    // the CLI config. If so, set it as the `$HAB_ORIGIN` environment variable for the `hab-studio`
    // or `docker` execv call.
    if henv::var("HAB_ORIGIN").is_err() {
        let config = try!(config::load_with_sudo_user());
        if let Some(default_origin) = config.origin {
            debug!("Setting default origin {} via CLI config", &default_origin);
            env::set_var("HAB_ORIGIN", default_origin);
        }
    }

    // If the `$HAB_CACHE_KEY_PATH` environment variable is not present, check if we are running
    // under a `sudo` invocation. If so, determine the non-root user that issued the command in
    // order to set their key cache location in the environment variable. This is done so that the
    // `hab-studio` command will find the correct key cache or so that the correct directory will
    // be volume mounted when used with Docker.
    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        if let Some(sudo_user) = henv::sudo_user() {
            if let Some(home) = users::get_home_for_user(&sudo_user) {
                let cache_key_path = home.join(format!(".{}", CACHE_KEY_PATH));
                debug!("Setting cache_key_path for SUDO_USER={} to: {}",
                       &sudo_user,
                       cache_key_path.display());
                env::set_var(CACHE_KEY_PATH_ENV_VAR, cache_key_path);
                // Prevent any inner `hab` invocations from triggering similar logic: we will be
                // operating in the context `hab-studio` which is running with rootlike privileges.
                env::remove_var("SUDO_USER");
            }
        }
    }

    inner::start(ui, args)
}

#[cfg(target_os = "linux")]
mod inner {
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::find_command;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;

    const STUDIO_CMD: &'static str = "hab-studio";
    const STUDIO_CMD_ENVVAR: &'static str = "HAB_STUDIO_BINARY";
    const STUDIO_PACKAGE_IDENT: &'static str = "core/hab-studio";

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = try!(PackageIdent::from_str(STUDIO_PACKAGE_IDENT));
                try!(exec::command_from_pkg(ui,
                                            STUDIO_CMD,
                                            &ident,
                                            &default_cache_key_path(None),
                                            0))
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            try!(exec::exec_command(cmd, args));
        } else {
            return Err(Error::ExecCommandNotFound(command.to_string_lossy().into_owned()));
        }
        Ok(())
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::process::{Command, exit};

    use common::ui::UI;
    use hcore::crypto::default_cache_key_path;
    use hcore::env as henv;
    use hcore::fs::{CACHE_KEY_PATH, find_command};

    use error::{Error, Result};
    use VERSION;

    const DOCKER_CMD: &'static str = "docker";
    const DOCKER_CMD_ENVVAR: &'static str = "HAB_DOCKER_BINARY";
    const DOCKER_IMAGE: &'static str = "habitat-docker-registry.bintray.io/studio";
    const DOCKER_IMAGE_ENVVAR: &'static str = "HAB_DOCKER_STUDIO_IMAGE";

    pub fn start(_ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let docker = henv::var(DOCKER_CMD_ENVVAR).unwrap_or(DOCKER_CMD.to_string());

        let cmd = match find_command(&docker) {
            Some(cmd) => cmd,
            None => return Err(Error::ExecCommandNotFound(docker.to_string())),
        };

        let mut command = Command::new(&cmd);
        command.arg("run")
            .arg("--rm")
            .arg("--tty")
            .arg("--interactive")
            .arg("--privileged");

        let env_vars = vec!["HAB_DEPOT_URL", "HAB_ORIGIN", "http_proxy", "https_proxy"];
        for var in env_vars {
            if let Ok(val) = henv::var(var) {
                debug!("Propagating environment variable into container: {}={}",
                       var,
                       val);
                command.arg("--env");
                command.arg(format!("{}={}", var, val));
            }
        }

        command.arg("--volume")
            .arg("/var/run/docker.sock:/var/run/docker.sock")
            .arg("--volume")
            .arg(format!("{}:/{}",
                         default_cache_key_path(None).to_string_lossy(),
                         CACHE_KEY_PATH))
            .arg("--volume")
            .arg(format!("{}:/src", env::current_dir().unwrap().to_string_lossy()))
            .arg(image_identifier());

        for arg in &args {
            command.arg(arg);
        }

        for var in vec!["http_proxy", "https_proxy"] {
            if let Ok(_) = henv::var(var) {
                debug!("Unsetting proxy environment variable '{}' before calling `{}'",
                       var,
                       docker);
                env::remove_var(var);
            }
        }

        let status = command.status().expect(&(format!("{:?} failed to start.", &cmd)));
        // Replace with specific errors based on exit code?
        // https://docs.docker.com/engine/reference/run/#/exit-status
        // this currently just passes the exit code from Docker directly.
        exit(status.code().unwrap())
    }

    /// Returns the Docker Studio image with tag for the desired version which corresponds to the
    /// same version (minus release) as this program.
    fn image_identifier() -> String {
        let version: Vec<&str> = VERSION.split("/").collect();
        henv::var(DOCKER_IMAGE_ENVVAR).unwrap_or(format!("{}:{}", DOCKER_IMAGE, version[0]))
    }

    #[cfg(test)]
    mod tests {
        use super::{image_identifier, DOCKER_IMAGE};
        use VERSION;

        #[test]
        fn retrieve_image_identifier() {
            assert_eq!(image_identifier(), format!("{}:{}", DOCKER_IMAGE, VERSION));
        }
    }
}
<|endoftext|>


<commit_before>use super::{Open, Sink};
use libc;
use libpulse_sys::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::io;
use std::mem;
use std::ptr::{null, null_mut};

pub struct PulseAudioSink {
    s: *mut pa_simple,
    ss: pa_sample_spec,
    name: CString,
    desc: CString,
}

fn call_pulseaudio<T, F, FailCheck>(
    f: F,
    fail_check: FailCheck,
    kind: io::ErrorKind,
) -> io::Result<T>
where
    T: Copy,
    F: Fn(*mut libc::c_int) -> T,
    FailCheck: Fn(T) -> bool,
{
    let mut error: libc::c_int = 0;
    let ret = f(&mut error);
    if fail_check(ret) {
        let err_cstr = unsafe { CStr::from_ptr(pa_strerror(error)) };
        let errstr = err_cstr.to_string_lossy().into_owned();
        Err(io::Error::new(kind, errstr))
    } else {
        Ok(ret)
    }
}

impl PulseAudioSink {
    fn free_connection(&mut self) {
        if self.s != null_mut() {
            unsafe {
                pa_simple_free(self.s);
            }
            self.s = null_mut();
        }
    }
}

impl Drop for PulseAudioSink {
    fn drop(&mut self) {
        self.free_connection();
    }
}

impl Open for PulseAudioSink {
    fn open(device: Option<String>) -> PulseAudioSink {
        debug!("Using PulseAudio sink");

        if device.is_some() {
            panic!("pulseaudio sink does not support specifying a device name");
        }

        let ss = pa_sample_spec {
            format: PA_SAMPLE_S16LE,
            channels: 2, // stereo
            rate: 44100,
        };

        let name = CString::new("librespot").unwrap();
        let description = CString::new("Spotify endpoint").unwrap();

        PulseAudioSink {
            s: null_mut(),
            ss: ss,
            name: name,
            desc: description,
        }
    }
}

impl Sink for PulseAudioSink {
    fn start(&mut self) -> io::Result<()> {
        if self.s == null_mut() {
            self.s = call_pulseaudio(
                |err| unsafe {
                    pa_simple_new(
                        null(),             // Use the default server.
                        self.name.as_ptr(), // Our application's name.
                        PA_STREAM_PLAYBACK,
                        null(),             // Use the default device.
                        self.desc.as_ptr(), // desc of our stream.
                        &self.ss,           // Our sample format.
                        null(),             // Use default channel map
                        null(),             // Use default buffering attributes.
                        err,
                    )
                },
                |ptr| ptr == null_mut(),
                io::ErrorKind::ConnectionRefused,
            )?;
        }
        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        self.free_connection();
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        if self.s == null_mut() {
            Err(io::Error::new(
                io::ErrorKind::NotConnected,
                "Not connected to pulseaudio",
            ))
        } else {
            let ptr = data.as_ptr() as *const libc::c_void;
            let len = data.len() as usize * mem::size_of::<i16>();
            assert!(len > 0);
            call_pulseaudio(
                |err| unsafe { pa_simple_write(self.s, ptr, len, err) },
                |ret| ret < 0,
                io::ErrorKind::BrokenPipe,
            )?;
            Ok(())
        }
    }
}
<commit_msg>Enable pulseaudio device names (#450)<commit_after>use super::{Open, Sink};
use libc;
use libpulse_sys::*;
use std::ffi::CStr;
use std::ffi::CString;
use std::io;
use std::mem;
use std::ptr::{null, null_mut};

pub struct PulseAudioSink {
    s: *mut pa_simple,
    ss: pa_sample_spec,
    name: CString,
    desc: CString,
    device: Option<CString>,
}

fn call_pulseaudio<T, F, FailCheck>(
    f: F,
    fail_check: FailCheck,
    kind: io::ErrorKind,
) -> io::Result<T>
where
    T: Copy,
    F: Fn(*mut libc::c_int) -> T,
    FailCheck: Fn(T) -> bool,
{
    let mut error: libc::c_int = 0;
    let ret = f(&mut error);
    if fail_check(ret) {
        let err_cstr = unsafe { CStr::from_ptr(pa_strerror(error)) };
        let errstr = err_cstr.to_string_lossy().into_owned();
        Err(io::Error::new(kind, errstr))
    } else {
        Ok(ret)
    }
}

impl PulseAudioSink {
    fn free_connection(&mut self) {
        if self.s != null_mut() {
            unsafe {
                pa_simple_free(self.s);
            }
            self.s = null_mut();
        }
    }
}

impl Drop for PulseAudioSink {
    fn drop(&mut self) {
        self.free_connection();
    }
}

impl Open for PulseAudioSink {
    fn open(device: Option<String>) -> PulseAudioSink {
        debug!("Using PulseAudio sink");

        let ss = pa_sample_spec {
            format: PA_SAMPLE_S16LE,
            channels: 2, // stereo
            rate: 44100,
        };

        let name = CString::new("librespot").unwrap();
        let description = CString::new("Spotify endpoint").unwrap();

        PulseAudioSink {
            s: null_mut(),
            ss: ss,
            name: name,
            desc: description,
            device: device.and_then(|s| CString::new(s).ok()),
        }
    }
}

impl Sink for PulseAudioSink {
    fn start(&mut self) -> io::Result<()> {
        if self.s == null_mut() {
            let device = match &self.device {
                None => null(),
                Some(device) => device.as_ptr(),
            };
            self.s = call_pulseaudio(
                |err| unsafe {
                    pa_simple_new(
                        null(),             // Use the default server.
                        self.name.as_ptr(), // Our application's name.
                        PA_STREAM_PLAYBACK,
                        device,
                        self.desc.as_ptr(), // desc of our stream.
                        &self.ss,           // Our sample format.
                        null(),             // Use default channel map
                        null(),             // Use default buffering attributes.
                        err,
                    )
                },
                |ptr| ptr == null_mut(),
                io::ErrorKind::ConnectionRefused,
            )?;
        }
        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        self.free_connection();
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        if self.s == null_mut() {
            Err(io::Error::new(
                io::ErrorKind::NotConnected,
                "Not connected to pulseaudio",
            ))
        } else {
            let ptr = data.as_ptr() as *const libc::c_void;
            let len = data.len() as usize * mem::size_of::<i16>();
            assert!(len > 0);
            call_pulseaudio(
                |err| unsafe { pa_simple_write(self.s, ptr, len, err) },
                |ret| ret < 0,
                io::ErrorKind::BrokenPipe,
            )?;
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>#[link(name = "glgen",
       author = "Brendan Zabarauskas",
       vers = "0.1")];
#[comment = "OpenGL function loader generator."];

//! Requires libxml2
//!
//! This will be used to generate the loader from the [registry xml files]
//! (https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/):
//!
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml`
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/glx.xml`
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/wgl.xml`

extern mod extra;

use std::io;
use std::os;

use registry::Registry;

pub mod registry;
pub mod ty_conv;

fn main() {
    let args = os::real_args();
    let path_str = args[1].as_slice();

    // Parse the XML registry.
    let reg = Registry::from_xml(
        io::file_reader(&Path(path_str))
            .expect(fmt!("Could not read %s", path_str))
            .read_c_str()
    );

    // Debug output
    if args.len() > 2 {
        match args[2].as_slice() {
            "--reg" => {
                // Print out the registry data for debugging.
                printfln!("%?", reg);
            }
            "--ctys" => {
                // Print out a list of all the types used in the registry.
                let tys = reg.get_tys();
                for ty in tys.iter() {
                    printfln!("\"%s\"", *ty);
                }
            }
            "--rtys" => {
                // Print out a list of all the types used in the registry,
                // converted to their Rust form.
                let tys = reg.get_tys();
                for ty in tys.iter() {
                    printfln!("\"%s\"", ty_conv::from_cty(*ty));
                }
            }
            _ => {}
        }
    }

    // TODO: Use registry data to generate function loader.
}
<commit_msg>Improve command line argument parsing<commit_after>#[link(name = "glgen",
       author = "Brendan Zabarauskas",
       vers = "0.1")];
#[comment = "OpenGL function loader generator."];

//! Requires libxml2
//!
//! This will be used to generate the loader from the [registry xml files]
//! (https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/):
//!
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml`
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/glx.xml`
//! - `$ wget --no-check-certificate https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/wgl.xml`

extern mod extra;

use std::io;
use std::os;
use std::util;

use registry::Registry;

pub mod registry;
pub mod ty_conv;

fn main() {
    match os::real_args() {
        [_, ref path, ..args] => {
            // Parse the XML registry.
            let reg = Registry::from_xml(
                io::file_reader(&Path(path.as_slice()))
                    .expect(fmt!("Could not read %s", *path))
                    .read_c_str()
            );
            parse_args(args, &reg);
        }
        [_] => println("Error: expected a path to an XML file."),
        [] => util::unreachable(),
    }
    // TODO: Use registry data to generate function loader.
}

fn parse_args(args: &[~str], reg: &Registry) {
    match args {
        [~"--reg", ..tl] => {
            print_registry(reg);
            parse_args(tl, reg);
        }
        [~"--ctys", ..tl] => {
            print_ctys(reg);
            parse_args(tl, reg);
        }
        [~"--rtys", ..tl] => {
            print_rtys(reg);
            parse_args(tl, reg);
        }
        [ref flag] => printfln!("Error: unexpected argument `%s`.", *flag),
        [] => (),
    }
}

/// Print out the registry data for debugging.
fn print_registry(reg: &Registry) {
    printfln!("%?", reg);
}

/// Print out a list of all the types used in the registry.
fn print_ctys(reg: &Registry) {
    let tys = reg.get_tys();
    for ty in tys.iter() {
        printfln!("\"%s\"", *ty);
    }
}

/// Print out a list of all the types used in the registry, converted to their
/// Rust declaration syntax.
fn print_rtys(reg: &Registry) {
    let tys = reg.get_tys();
    for ty in tys.iter() {
        printfln!("\"%s\"", ty_conv::from_cty(*ty));
    }
}
<|endoftext|>


<commit_before>table! {
    event_entry (id) {
        id -> Uuid,
        ledger_id -> Uuid,
        name -> Text,
        timestamp -> Timestamptz,
        created_at -> Timestamptz,
        updated_at -> Timestamptz,
    }
}

table! {
    ledger (id) {
        id -> Uuid,
        name -> Text,
        created_at -> Timestamptz,
        updated_at -> Timestamptz,
    }
}

joinable!(event_entry -> ledger (ledger_id));

allow_tables_to_appear_in_same_query!(
    event_entry,
    ledger,
);
<commit_msg>Update database schema<commit_after>table! {
    event_entry (id) {
        id -> Uuid,
        created_at -> Timestamptz,
        updated_at -> Timestamptz,
        ledger_id -> Uuid,
        name -> Text,
        timestamp -> Timestamptz,
    }
}

table! {
    ledger (id) {
        id -> Uuid,
        created_at -> Timestamptz,
        updated_at -> Timestamptz,
        name -> Text,
    }
}

table! {
    project (id) {
        id -> Uuid,
        created_at -> Timestamptz,
        updated_at -> Timestamptz,
        name -> Text,
    }
}

joinable!(event_entry -> ledger (ledger_id));

allow_tables_to_appear_in_same_query!(
    event_entry,
    ledger,
    project,
);
<|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/. */

// Servo, the mighty web browser engine from the future.
//
// This is a very simple library that wires all of Servo's components
// together as type `Browser`, along with a generic client
// implementing the `WindowMethods` trait, to create a working web
// browser.
//
// The `Browser` type is responsible for configuring a
// `Constellation`, which does the heavy lifting of coordinating all
// of Servo's internal subsystems, including the `ScriptTask` and the
// `LayoutTask`, as well maintains the navigation context.
//
// The `Browser` is fed events from a generic type that implements the
// `WindowMethods` trait.
#![feature(thread_local)]

extern crate compositing;
extern crate devtools;
extern crate devtools_traits;
extern crate net;
extern crate net_traits;
extern crate msg;
extern crate profile;
extern crate profile_traits;
#[macro_use]
extern crate util;
extern crate script;
extern crate layout;
extern crate gfx;
extern crate libc;
extern crate url;
extern crate webdriver_server;

use compositing::CompositorEventListener;
use compositing::windowing::WindowEvent;

use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorTask, Constellation};

use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::ConstellationChan;

use script::dom::bindings::codegen::RegisterBindings;

use net::image_cache_task::new_image_cache_task;
use net::storage_task::StorageTaskFactory;
use net::resource_task::new_resource_task;
use net_traits::storage_task::StorageTask;

use gfx::font_cache_task::FontCacheTask;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use util::opts;

use std::rc::Rc;
use std::sync::mpsc::Sender;

pub struct Browser {
    compositor: Box<CompositorEventListener + 'static>,
}

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
impl Browser  {
    pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
    where Window: WindowMethods + 'static {
        ::util::opts::set_experimental_enabled(opts::get().enable_experimental);

        // Global configuration options, parsed from the command line.
        let opts = opts::get();

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

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            WindowMethods::create_compositor_channel(&window);
        let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      devtools_chan,
                                                      mem_profiler_chan.clone());

        if let Some(port) = opts.webdriver_port {
            webdriver_server::start_server(port, constellation_chan.clone());
        };

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = CompositorTask::create(window,
                                                compositor_proxy,
                                                compositor_receiver,
                                                constellation_chan.clone(),
                                                time_profiler_chan,
                                                mem_profiler_chan);

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_event(&mut self, event: WindowEvent) -> bool {
        self.compositor.handle_event(event)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn get_title_for_main_frame(&self) {
        self.compositor.get_title_for_main_frame()
    }

    pub fn shutdown(mut self) {
        self.compositor.shutdown();
    }
}
fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy+Send>,
                        time_profiler_chan: time::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        mem_profiler_chan: mem::ProfilerChan) -> ConstellationChan {
    use std::env;

    let resource_task = new_resource_task(opts.user_agent.clone(), devtools_chan.clone());

    let image_cache_task = new_image_cache_task(resource_task.clone());
    let font_cache_task = FontCacheTask::new(resource_task.clone());
    let storage_task: StorageTask = StorageTaskFactory::new();

    let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
    script::script_task::ScriptTask>::start(
        compositor_proxy.clone_compositor_proxy(),
        resource_task,
        image_cache_task,
        font_cache_task,
        time_profiler_chan.clone(),
        mem_profiler_chan.clone(),
        devtools_chan,
        storage_task);

    // Send the URL command to the constellation.
    let cwd = env::current_dir().unwrap();
    let url = match url::Url::parse(&opts.url) {
        Ok(url) => url,
        Err(url::ParseError::RelativeUrlWithoutBase)
        => url::Url::from_file_path(&*cwd.join(&opts.url)).unwrap(),
        Err(_) => panic!("URL parsing failed"),
    };

    {
        let ConstellationChan(ref chan) = constellation_chan;
        chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
    }

    constellation_chan
}
<commit_msg>Whitespace<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/. */

// Servo, the mighty web browser engine from the future.
//
// This is a very simple library that wires all of Servo's components
// together as type `Browser`, along with a generic client
// implementing the `WindowMethods` trait, to create a working web
// browser.
//
// The `Browser` type is responsible for configuring a
// `Constellation`, which does the heavy lifting of coordinating all
// of Servo's internal subsystems, including the `ScriptTask` and the
// `LayoutTask`, as well maintains the navigation context.
//
// The `Browser` is fed events from a generic type that implements the
// `WindowMethods` trait.
#![feature(thread_local)]

extern crate compositing;
extern crate devtools;
extern crate devtools_traits;
extern crate net;
extern crate net_traits;
extern crate msg;
extern crate profile;
extern crate profile_traits;
#[macro_use]
extern crate util;
extern crate script;
extern crate layout;
extern crate gfx;
extern crate libc;
extern crate url;
extern crate webdriver_server;

use compositing::CompositorEventListener;
use compositing::windowing::WindowEvent;

use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorTask, Constellation};

use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::ConstellationChan;

use script::dom::bindings::codegen::RegisterBindings;

use net::image_cache_task::new_image_cache_task;
use net::storage_task::StorageTaskFactory;
use net::resource_task::new_resource_task;
use net_traits::storage_task::StorageTask;

use gfx::font_cache_task::FontCacheTask;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use util::opts;

use std::rc::Rc;
use std::sync::mpsc::Sender;

pub struct Browser {
    compositor: Box<CompositorEventListener + 'static>,
}

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
impl Browser  {
    pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
    where Window: WindowMethods + 'static {
        ::util::opts::set_experimental_enabled(opts::get().enable_experimental);

        // Global configuration options, parsed from the command line.
        let opts = opts::get();

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

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            WindowMethods::create_compositor_channel(&window);
        let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      devtools_chan,
                                                      mem_profiler_chan.clone());

        if let Some(port) = opts.webdriver_port {
            webdriver_server::start_server(port, constellation_chan.clone());
        };

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = CompositorTask::create(window,
                                                compositor_proxy,
                                                compositor_receiver,
                                                constellation_chan.clone(),
                                                time_profiler_chan,
                                                mem_profiler_chan);

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_event(&mut self, event: WindowEvent) -> bool {
        self.compositor.handle_event(event)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn get_title_for_main_frame(&self) {
        self.compositor.get_title_for_main_frame()
    }

    pub fn shutdown(mut self) {
        self.compositor.shutdown();
    }
}

fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy+Send>,
                        time_profiler_chan: time::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        mem_profiler_chan: mem::ProfilerChan) -> ConstellationChan {
    use std::env;

    let resource_task = new_resource_task(opts.user_agent.clone(), devtools_chan.clone());

    let image_cache_task = new_image_cache_task(resource_task.clone());
    let font_cache_task = FontCacheTask::new(resource_task.clone());
    let storage_task: StorageTask = StorageTaskFactory::new();

    let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
    script::script_task::ScriptTask>::start(
        compositor_proxy.clone_compositor_proxy(),
        resource_task,
        image_cache_task,
        font_cache_task,
        time_profiler_chan.clone(),
        mem_profiler_chan.clone(),
        devtools_chan,
        storage_task);

    // Send the URL command to the constellation.
    let cwd = env::current_dir().unwrap();
    let url = match url::Url::parse(&opts.url) {
        Ok(url) => url,
        Err(url::ParseError::RelativeUrlWithoutBase)
        => url::Url::from_file_path(&*cwd.join(&opts.url)).unwrap(),
        Err(_) => panic!("URL parsing failed"),
    };

    {
        let ConstellationChan(ref chan) = constellation_chan;
        chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
    }

    constellation_chan
}
<|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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![deny(warnings)]
#![deny(missing_docs)]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
extern crate arrayvec;
extern crate atomic_refcell;
extern crate bit_vec;
#[macro_use]
extern crate bitflags;
#[allow(unused_extern_crates)] extern crate byteorder;
#[cfg(feature = "gecko")] #[macro_use] #[no_link] extern crate cfg_if;
#[macro_use] extern crate cssparser;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
#[cfg(feature = "servo")] extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
extern crate itoa;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")]
#[macro_use]
pub extern crate nsstring_vendor as nsstring;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate num_integer;
extern crate num_traits;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate pdqsort;
#[cfg(feature = "gecko")] extern crate precomputed_hash;
extern crate rayon;
extern crate selectors;
#[cfg(feature = "servo")] #[macro_use] extern crate serde;
pub extern crate servo_arc;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
#[cfg(feature = "servo")] extern crate servo_config;
#[cfg(feature = "servo")] extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_derive;
#[macro_use]
extern crate style_traits;
extern crate time;
extern crate unicode_bidi;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

#[macro_use]
mod macros;

pub mod animation;
pub mod applicable_declarations;
#[allow(missing_docs)] // TODO.
#[cfg(feature = "servo")] pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod counter_style;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
#[cfg(feature = "servo")] mod encoding_support;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod invalidation;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
pub mod media_queries;
pub mod parallel;
pub mod parser;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_map;
pub mod selector_parser;
pub mod shared_lock;
pub mod sharing;
pub mod style_resolver;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod str;
pub mod style_adjuster;
pub mod stylesheet_set;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;

// Compat shim for the old name when it lived in the style crate.
// FIXME(bholley) Remove this.
pub use servo_arc as stylearc;

use std::fmt;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever::Prefix;
#[cfg(feature = "servo")] pub use html5ever::LocalName;
#[cfg(feature = "servo")] pub use html5ever::Namespace;

/// The CSS properties supported by the style system.
/// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code, missing_docs)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    list[0].to_css(dest)?;

    for item in list.iter().skip(1) {
        write!(dest, ", ")?;
        item.to_css(dest)?;
    }

    Ok(())
}

#[cfg(feature = "gecko")] use gecko_string_cache::WeakAtom;
#[cfg(feature = "servo")] use servo_atoms::Atom as WeakAtom;

/// Extension methods for selectors::attr::CaseSensitivity
pub trait CaseSensitivityExt {
    /// Return whether two atoms compare equal according to this case sensitivity.
    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool;
}

impl CaseSensitivityExt for selectors::attr::CaseSensitivity {
    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool {
        match self {
            selectors::attr::CaseSensitivity::CaseSensitive => a == b,
            selectors::attr::CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
        }
    }
}
<commit_msg>Remove last vestiges of stylearc<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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![deny(warnings)]
#![deny(missing_docs)]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
extern crate arrayvec;
extern crate atomic_refcell;
extern crate bit_vec;
#[macro_use]
extern crate bitflags;
#[allow(unused_extern_crates)] extern crate byteorder;
#[cfg(feature = "gecko")] #[macro_use] #[no_link] extern crate cfg_if;
#[macro_use] extern crate cssparser;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
#[cfg(feature = "servo")] extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
extern crate itoa;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")]
#[macro_use]
pub extern crate nsstring_vendor as nsstring;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate num_integer;
extern crate num_traits;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate pdqsort;
#[cfg(feature = "gecko")] extern crate precomputed_hash;
extern crate rayon;
extern crate selectors;
#[cfg(feature = "servo")] #[macro_use] extern crate serde;
pub extern crate servo_arc;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
#[cfg(feature = "servo")] extern crate servo_config;
#[cfg(feature = "servo")] extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_derive;
#[macro_use]
extern crate style_traits;
extern crate time;
extern crate unicode_bidi;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

#[macro_use]
mod macros;

pub mod animation;
pub mod applicable_declarations;
#[allow(missing_docs)] // TODO.
#[cfg(feature = "servo")] pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod counter_style;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
#[cfg(feature = "servo")] mod encoding_support;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod invalidation;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
pub mod media_queries;
pub mod parallel;
pub mod parser;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_map;
pub mod selector_parser;
pub mod shared_lock;
pub mod sharing;
pub mod style_resolver;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod str;
pub mod style_adjuster;
pub mod stylesheet_set;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;

use std::fmt;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever::Prefix;
#[cfg(feature = "servo")] pub use html5ever::LocalName;
#[cfg(feature = "servo")] pub use html5ever::Namespace;

/// The CSS properties supported by the style system.
/// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code, missing_docs)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    list[0].to_css(dest)?;

    for item in list.iter().skip(1) {
        write!(dest, ", ")?;
        item.to_css(dest)?;
    }

    Ok(())
}

#[cfg(feature = "gecko")] use gecko_string_cache::WeakAtom;
#[cfg(feature = "servo")] use servo_atoms::Atom as WeakAtom;

/// Extension methods for selectors::attr::CaseSensitivity
pub trait CaseSensitivityExt {
    /// Return whether two atoms compare equal according to this case sensitivity.
    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool;
}

impl CaseSensitivityExt for selectors::attr::CaseSensitivity {
    fn eq_atom(self, a: &WeakAtom, b: &WeakAtom) -> bool {
        match self {
            selectors::attr::CaseSensitivity::CaseSensitive => a == b,
            selectors::attr::CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Grin Developers
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The Grin leaf_set implementation.
//! Compact (roaring) bitmap representing the set of leaf positions
//! that exist and are not currently pruned in the MMR.

use std::path::{Path, PathBuf};

use croaring::Bitmap;

use crate::core::core::hash::Hashed;
use crate::core::core::pmmr;
use crate::core::core::BlockHeader;
use crate::prune_list::PruneList;
use crate::{read_bitmap, save_via_temp_file};

use std::fs::File;
use std::io::{self, BufWriter, Write};

/// Compact (roaring) bitmap representing the set of positions of
/// leaves that are currently unpruned in the MMR.
pub struct LeafSet {
	path: PathBuf,
	bitmap: Bitmap,
	bitmap_bak: Bitmap,
}

impl LeafSet {
	/// Open the remove log file.
	/// The content of the file will be read in memory for fast checking.
	pub fn open<P: AsRef<Path>>(path: P) -> io::Result<LeafSet> {
		let file_path = path.as_ref();
		let bitmap = if file_path.exists() {
			read_bitmap(&file_path)?
		} else {
			Bitmap::create()
		};

		if !bitmap.is_empty() {
			debug!(
				"bitmap {} pos ({} bytes)",
				bitmap.cardinality(),
				bitmap.get_serialized_size_in_bytes(),
			);
		}

		Ok(LeafSet {
			path: file_path.to_path_buf(),
			bitmap_bak: bitmap.clone(),
			bitmap,
		})
	}

	/// Copies a snapshot of the utxo file into the primary utxo file.
	pub fn copy_snapshot<P: AsRef<Path>>(path: P, cp_path: P) -> io::Result<()> {
		let cp_file_path = cp_path.as_ref();

		if !cp_file_path.exists() {
			debug!(
				"leaf_set: rewound leaf file not found: {}",
				cp_file_path.display()
			);
			return Ok(());
		}

		let bitmap = read_bitmap(&cp_file_path)?;
		debug!(
			"leaf_set: copying rewound file {} to {}",
			cp_file_path.display(),
			path.as_ref().display()
		);

		let mut leaf_set = LeafSet {
			path: path.as_ref().to_path_buf(),
			bitmap_bak: bitmap.clone(),
			bitmap,
		};

		leaf_set.flush()?;
		Ok(())
	}

	/// Calculate the set of unpruned leaves
	/// up to and including the cutoff_pos.
	/// Only applicable for the output MMR.
	fn unpruned_pre_cutoff(&self, cutoff_pos: u64, prune_list: &PruneList) -> Bitmap {
		(1..=cutoff_pos)
			.filter(|&x| pmmr::is_leaf(x))
			.filter(|&x| !prune_list.is_pruned(x))
			.map(|x| x as u32)
			.collect()
	}

	/// Calculate the set of pruned positions
	/// up to and including the cutoff_pos.
	/// Uses both the leaf_set and the prune_list to determine prunedness.
	pub fn removed_pre_cutoff(
		&self,
		cutoff_pos: u64,
		rewind_rm_pos: &Bitmap,
		prune_list: &PruneList,
	) -> Bitmap {
		let mut bitmap = self.bitmap.clone();

		// First remove pos from leaf_set that were
		// added after the point we are rewinding to.
		let marker_from = cutoff_pos;
		let marker_to = self.bitmap.maximum() as u64;
		let rewind_add_pos: Bitmap = ((marker_from + 1)..=marker_to).map(|x| x as u32).collect();
		bitmap.andnot_inplace(&rewind_add_pos);

		// Then add back output pos to the leaf_set
		// that were removed.
		bitmap.or_inplace(&rewind_rm_pos);

		// Invert bitmap for the leaf pos and return the resulting bitmap.
		bitmap
			.flip(1..(cutoff_pos + 1))
			.and(&self.unpruned_pre_cutoff(cutoff_pos, prune_list))
	}

	/// Rewinds the leaf_set back to a previous state.
	/// Removes all pos after the cutoff.
	/// Adds back all pos in rewind_rm_pos.
	pub fn rewind(&mut self, cutoff_pos: u64, rewind_rm_pos: &Bitmap) {
		// First remove pos from leaf_set that were
		// added after the point we are rewinding to.
		let marker_from = cutoff_pos;
		let marker_to = self.bitmap.maximum() as u64;
		let rewind_add_pos: Bitmap = ((marker_from + 1)..=marker_to).map(|x| x as u32).collect();
		self.bitmap.andnot_inplace(&rewind_add_pos);

		// Then add back output pos to the leaf_set
		// that were removed.
		self.bitmap.or_inplace(&rewind_rm_pos);
	}

	/// Append a new position to the leaf_set.
	pub fn add(&mut self, pos: u64) {
		self.bitmap.add(pos as u32);
	}

	/// Remove the provided position from the leaf_set.
	pub fn remove(&mut self, pos: u64) {
		self.bitmap.remove(pos as u32);
	}

	/// Saves the utxo file tagged with block hash as filename suffix.
	/// Needed during fast-sync as the receiving node cannot rewind
	/// after receiving the txhashset zip file.
	pub fn snapshot(&self, header: &BlockHeader) -> io::Result<()> {
		let mut cp_bitmap = self.bitmap.clone();
		cp_bitmap.run_optimize();

		let cp_path = format!("{}.{}", self.path.to_str().unwrap(), header.hash());
		let mut file = BufWriter::new(File::create(cp_path)?);
		file.write_all(&cp_bitmap.serialize())?;
		file.flush()?;
		Ok(())
	}

	/// Flush the leaf_set to file.
	pub fn flush(&mut self) -> io::Result<()> {
		// First run the optimization step on the bitmap.
		self.bitmap.run_optimize();

		// Write the updated bitmap file to disk.
		save_via_temp_file(&self.path, ".tmp", |w| {
			let mut w = BufWriter::new(w);
			w.write_all(&self.bitmap.serialize())?;
			w.flush()
		})?;

		// Make sure our backup in memory is up to date.
		self.bitmap_bak = self.bitmap.clone();

		Ok(())
	}

	/// Discard any pending changes.
	pub fn discard(&mut self) {
		self.bitmap = self.bitmap_bak.clone();
	}

	/// Whether the leaf_set includes the provided position.
	pub fn includes(&self, pos: u64) -> bool {
		self.bitmap.contains(pos as u32)
	}

	/// Number of positions stored in the leaf_set.
	pub fn len(&self) -> usize {
		self.bitmap.cardinality() as usize
	}

	/// Is the leaf_set empty.
	pub fn is_empty(&self) -> bool {
		self.len() == 0
	}

	/// Iterator over positionns in the leaf_set (all leaf positions).
	pub fn iter(&self) -> impl Iterator<Item = u64> + '_ {
		self.bitmap.iter().map(|x| x as u64)
	}
}
<commit_msg>use remove_range_closed for clarity (#3088)<commit_after>// Copyright 2019 The Grin Developers
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The Grin leaf_set implementation.
//! Compact (roaring) bitmap representing the set of leaf positions
//! that exist and are not currently pruned in the MMR.

use std::path::{Path, PathBuf};

use croaring::Bitmap;

use crate::core::core::hash::Hashed;
use crate::core::core::pmmr;
use crate::core::core::BlockHeader;
use crate::prune_list::PruneList;
use crate::{read_bitmap, save_via_temp_file};

use std::fs::File;
use std::io::{self, BufWriter, Write};

/// Compact (roaring) bitmap representing the set of positions of
/// leaves that are currently unpruned in the MMR.
pub struct LeafSet {
	path: PathBuf,
	bitmap: Bitmap,
	bitmap_bak: Bitmap,
}

impl LeafSet {
	/// Open the remove log file.
	/// The content of the file will be read in memory for fast checking.
	pub fn open<P: AsRef<Path>>(path: P) -> io::Result<LeafSet> {
		let file_path = path.as_ref();
		let bitmap = if file_path.exists() {
			read_bitmap(&file_path)?
		} else {
			Bitmap::create()
		};

		if !bitmap.is_empty() {
			debug!(
				"bitmap {} pos ({} bytes)",
				bitmap.cardinality(),
				bitmap.get_serialized_size_in_bytes(),
			);
		}

		Ok(LeafSet {
			path: file_path.to_path_buf(),
			bitmap_bak: bitmap.clone(),
			bitmap,
		})
	}

	/// Copies a snapshot of the utxo file into the primary utxo file.
	pub fn copy_snapshot<P: AsRef<Path>>(path: P, cp_path: P) -> io::Result<()> {
		let cp_file_path = cp_path.as_ref();

		if !cp_file_path.exists() {
			debug!(
				"leaf_set: rewound leaf file not found: {}",
				cp_file_path.display()
			);
			return Ok(());
		}

		let bitmap = read_bitmap(&cp_file_path)?;
		debug!(
			"leaf_set: copying rewound file {} to {}",
			cp_file_path.display(),
			path.as_ref().display()
		);

		let mut leaf_set = LeafSet {
			path: path.as_ref().to_path_buf(),
			bitmap_bak: bitmap.clone(),
			bitmap,
		};

		leaf_set.flush()?;
		Ok(())
	}

	/// Calculate the set of unpruned leaves
	/// up to and including the cutoff_pos.
	/// Only applicable for the output MMR.
	fn unpruned_pre_cutoff(&self, cutoff_pos: u64, prune_list: &PruneList) -> Bitmap {
		(1..=cutoff_pos)
			.filter(|&x| pmmr::is_leaf(x))
			.filter(|&x| !prune_list.is_pruned(x))
			.map(|x| x as u32)
			.collect()
	}

	/// Calculate the set of pruned positions
	/// up to and including the cutoff_pos.
	/// Uses both the leaf_set and the prune_list to determine prunedness.
	pub fn removed_pre_cutoff(
		&self,
		cutoff_pos: u64,
		rewind_rm_pos: &Bitmap,
		prune_list: &PruneList,
	) -> Bitmap {
		let mut bitmap = self.bitmap.clone();

		// First remove pos from leaf_set that were
		// added after the point we are rewinding to.
		let to_remove = ((cutoff_pos + 1) as u32)..bitmap.maximum();
		bitmap.remove_range_closed(to_remove);

		// Then add back output pos to the leaf_set
		// that were removed.
		bitmap.or_inplace(&rewind_rm_pos);

		// Invert bitmap for the leaf pos and return the resulting bitmap.
		bitmap
			.flip(1..(cutoff_pos + 1))
			.and(&self.unpruned_pre_cutoff(cutoff_pos, prune_list))
	}

	/// Rewinds the leaf_set back to a previous state.
	/// Removes all pos after the cutoff.
	/// Adds back all pos in rewind_rm_pos.
	pub fn rewind(&mut self, cutoff_pos: u64, rewind_rm_pos: &Bitmap) {
		// First remove pos from leaf_set that were
		// added after the point we are rewinding to.
		let to_remove = ((cutoff_pos + 1) as u32)..self.bitmap.maximum();
		self.bitmap.remove_range_closed(to_remove);

		// Then add back output pos to the leaf_set
		// that were removed.
		self.bitmap.or_inplace(&rewind_rm_pos);
	}

	/// Append a new position to the leaf_set.
	pub fn add(&mut self, pos: u64) {
		self.bitmap.add(pos as u32);
	}

	/// Remove the provided position from the leaf_set.
	pub fn remove(&mut self, pos: u64) {
		self.bitmap.remove(pos as u32);
	}

	/// Saves the utxo file tagged with block hash as filename suffix.
	/// Needed during fast-sync as the receiving node cannot rewind
	/// after receiving the txhashset zip file.
	pub fn snapshot(&self, header: &BlockHeader) -> io::Result<()> {
		let mut cp_bitmap = self.bitmap.clone();
		cp_bitmap.run_optimize();

		let cp_path = format!("{}.{}", self.path.to_str().unwrap(), header.hash());
		let mut file = BufWriter::new(File::create(cp_path)?);
		file.write_all(&cp_bitmap.serialize())?;
		file.flush()?;
		Ok(())
	}

	/// Flush the leaf_set to file.
	pub fn flush(&mut self) -> io::Result<()> {
		// First run the optimization step on the bitmap.
		self.bitmap.run_optimize();

		// Write the updated bitmap file to disk.
		save_via_temp_file(&self.path, ".tmp", |w| {
			let mut w = BufWriter::new(w);
			w.write_all(&self.bitmap.serialize())?;
			w.flush()
		})?;

		// Make sure our backup in memory is up to date.
		self.bitmap_bak = self.bitmap.clone();

		Ok(())
	}

	/// Discard any pending changes.
	pub fn discard(&mut self) {
		self.bitmap = self.bitmap_bak.clone();
	}

	/// Whether the leaf_set includes the provided position.
	pub fn includes(&self, pos: u64) -> bool {
		self.bitmap.contains(pos as u32)
	}

	/// Number of positions stored in the leaf_set.
	pub fn len(&self) -> usize {
		self.bitmap.cardinality() as usize
	}

	/// Is the leaf_set empty.
	pub fn is_empty(&self) -> bool {
		self.len() == 0
	}

	/// Iterator over positionns in the leaf_set (all leaf positions).
	pub fn iter(&self) -> impl Iterator<Item = u64> + '_ {
		self.bitmap.iter().map(|x| x as u64)
	}
}
<|endoftext|>


<commit_before>use genetic::helpers::Range;
use genetic::helpers::binary_vector_to_decimal;

pub trait HasFitness<T> {
    fn fitness(&self, f: &fn(&Vec<T>, &Range<T>) -> f32, range: &Range<T>)  -> f32;
}

impl <T> HasFitness<T> for Vec<T> {
    fn fitness(&self, f: &fn(&Vec<T>, &Range<T>) -> f32, range: &Range<T>) -> f32 {
        f(&self, range)
    }
}

///////////////////////
// Fitness functions //
///////////////////////

pub fn max_alternating_bits(genome: &Vec<u8>, range: &Range<u8>) -> f32 {
    let mut was_zero = genome[0] == 0;
    let mut fitness = 0;

    for gene in genome {
        let is_zero = *gene == 0;
        if was_zero != is_zero {
            fitness += 1;
        }
        was_zero = is_zero;
    }

    fitness as f32
}

pub fn max_alternating_even_odd(genome: &Vec<i32>, range: &Range<i32>) -> f32 {
    let mut was_even = genome[0] == 0;
    let mut fitness = 0;

    for gene in genome {
        let is_even = *gene % 2 == 0;
        if was_even != is_even {
            fitness += 1;
        }
        was_even = is_even;
    }

    fitness as f32
}

pub fn min_dejong_function(genome: &Vec<f32>, range: &Range<f32>) -> f32 {
    let mut fitness = 0.0;

    for gene in genome {
        fitness += gene * gene;
    }

    fitness
}

// Parps Fitness
fn parps_function(x: f32) -> f32 {
    (x * 20.0).cos() - x.abs() / 2.0 + (x * x * x) / 4.0
}

pub fn parps_fitness(binary_genome: &Vec<u8>, range: &Range<f32>) -> f32 {
    let decimal: i32 = binary_vector_to_decimal(binary_genome);
    let limit = (2i32.pow(16) - 1) as f32;
    let f = -2.0 + (4.0 / limit) * (decimal as f32);
    let fitness = parps_function(f) + 4.0;
    fitness
}
<commit_msg>Fixed De Jong minimization fitness<commit_after>use genetic::helpers::Range;
use genetic::helpers::binary_vector_to_decimal;

pub trait HasFitness<T> {
    fn fitness(&self, f: &fn(&Vec<T>, &Range<T>) -> f32, range: &Range<T>)  -> f32;
}

impl <T> HasFitness<T> for Vec<T> {
    fn fitness(&self, f: &fn(&Vec<T>, &Range<T>) -> f32, range: &Range<T>) -> f32 {
        f(&self, range)
    }
}

///////////////////////
// Fitness functions //
///////////////////////

pub fn max_alternating_bits(genome: &Vec<u8>, range: &Range<u8>) -> f32 {
    let mut was_zero = genome[0] == 0;
    let mut fitness = 0;

    for gene in genome {
        let is_zero = *gene == 0;
        if was_zero != is_zero {
            fitness += 1;
        }
        was_zero = is_zero;
    }

    fitness as f32
}

pub fn max_alternating_even_odd(genome: &Vec<i32>, range: &Range<i32>) -> f32 {
    let mut was_even = genome[0] == 0;
    let mut fitness = 0;

    for gene in genome {
        let is_even = *gene % 2 == 0;
        if was_even != is_even {
            fitness += 1;
        }
        was_even = is_even;
    }

    fitness as f32
}

pub fn min_dejong(genome: &Vec<f32>, range: &Range<f32>) -> f32 {
    let mut fitness = 0.0;
    let maximum_value = range.end * range.end;

    for gene in genome {
        fitness += gene * gene;
    }

    (fitness / maximum_value) - 1.0
}

// Parps Fitness
fn parps_function(x: f32) -> f32 {
    (x * 20.0).cos() - x.abs() / 2.0 + (x * x * x) / 4.0
}

pub fn parps_fitness(binary_genome: &Vec<u8>, range: &Range<f32>) -> f32 {
    let decimal: i32 = binary_vector_to_decimal(binary_genome);
    let limit = (2i32.pow(16) - 1) as f32;
    let f = -2.0 + (4.0 / limit) * (decimal as f32);
    let fitness = parps_function(f) + 4.0;
    fitness
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(reflect_marker)]
#![feature(unboxed_closures)]

extern crate lua52_sys as ffi;
extern crate libc;

use std::ffi::{CStr, CString};
use std::io::Read;
use std::io::Error as IoError;
use std::borrow::Borrow;
use std::marker::PhantomData;

pub use functions_read::LuaFunction;
pub use functions_write::{function, InsideCallback};
pub use lua_tables::LuaTable;

pub mod any;
pub mod functions_read;
pub mod lua_tables;
pub mod userdata;

mod functions_write;
mod macros;
mod rust_tables;
mod values;
mod tuples;

/// Main object of the library.
///
/// The lifetime parameter corresponds to the lifetime of the content of the Lua context.
pub struct Lua<'lua> {
    lua: LuaContext,
    must_be_closed: bool,
    marker: PhantomData<&'lua ()>,
}

/// RAII guard for a value pushed on the stack.
pub struct PushGuard<L> where L: AsMutLua {
    lua: L,
    size: i32,
}

impl<L> PushGuard<L> where L: AsMutLua {
    /// Prevents the value from being poped when the `PushGuard` is destroyed, and returns the
    /// number of elements on the stack.
    fn forget(mut self) -> i32 {
        let size = self.size;
        self.size = 0;
        size
    }
}

/// Trait for objects that have access to a Lua context. When using a context returned by a
/// `AsLua`, you are not allowed to modify the stack.
pub unsafe trait AsLua {
    fn as_lua(&self) -> LuaContext;
}

/// Trait for objects that have access to a Lua context. You are allowed to modify the stack, but
/// it must be in the same state as it was when you started.
pub unsafe trait AsMutLua: AsLua {
    fn as_mut_lua(&mut self) -> LuaContext;
}

/// Opaque type that contains the raw Lua context.
#[derive(Copy, Clone)]
#[allow(raw_pointer_derive)]
pub struct LuaContext(*mut ffi::lua_State);
unsafe impl Send for LuaContext {}

unsafe impl<'a, 'lua> AsLua for &'a Lua<'lua> {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a, 'lua> AsLua for &'a mut Lua<'lua> {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a, 'lua> AsMutLua for &'a mut Lua<'lua> {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua
    }
}

unsafe impl<L> AsLua for PushGuard<L> where L: AsMutLua {
    fn as_lua(&self) -> LuaContext {
        self.lua.as_lua()
    }
}

unsafe impl<L> AsMutLua for PushGuard<L> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua.as_mut_lua()
    }
}

unsafe impl<'a, L> AsLua for &'a L where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        (**self).as_lua()
    }
}

unsafe impl<'a, L> AsLua for &'a mut L where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        (**self).as_lua()
    }
}

unsafe impl<'a, L> AsMutLua for &'a mut L where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        (**self).as_mut_lua()
    }
}

/// Types that can be given to a Lua context, for example with `lua.set()` or as a return value
/// of a function.
pub trait Push<L> where L: AsMutLua {
    /// Pushes the value on the top of the stack.
    ///
    /// Must return a guard representing the elements that have been pushed.
    ///
    /// You can implement this for any type you want by redirecting to call to
    /// another implementation (for example `5.push_to_lua`) or by calling
    /// `userdata::push_userdata`.
    fn push_to_lua(self, lua: L) -> PushGuard<L>;
}

/// Types that can be obtained from a Lua context.
///
/// Most types that implement `Push` also implement `LuaRead`, but this is not always the case
/// (for example `&'static str` implements `Push` but not `LuaRead`).
pub trait LuaRead<L>: Sized where L: AsLua {
    /// Reads the data from Lua.
    fn lua_read(lua: L) -> Result<Self, L> {
        LuaRead::lua_read_at_position(lua, -1)
    }

    /// Reads the data from Lua at a given position.
    fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L>;
}

/// Error that can happen when executing Lua code.
#[derive(Debug)]
pub enum LuaError {
    /// There was a syntax error when parsing the Lua code.
    SyntaxError(String),

    /// There was an error during execution of the Lua code
    /// (for example not enough parameters for a function call).
    ExecutionError(String),

    /// There was an IoError while reading the source code to execute.
    ReadError(IoError),

    /// The call to `execute` has requested the wrong type of data.
    WrongType,
}

impl<'lua> Lua<'lua> {
    /// Builds a new Lua context.
    ///
    /// # Panic
    ///
    /// The function panics if the underlying call to `lua_newstate` fails
    /// (which indicates lack of memory).
    pub fn new() -> Lua<'lua> {
        let lua = unsafe { ffi::lua_newstate(alloc, std::ptr::null_mut()) };
        if lua.is_null() {
            panic!("lua_newstate failed");
        }

        // this alloc function is required to create a lua state.
        extern "C" fn alloc(_ud: *mut libc::c_void, ptr: *mut libc::c_void, _osize: libc::size_t,
                            nsize: libc::size_t) -> *mut libc::c_void
        {
            unsafe {
                if nsize == 0 {
                    libc::free(ptr as *mut libc::c_void);
                    std::ptr::null_mut()
                } else {
                    libc::realloc(ptr, nsize)
                }
            }
        }

        // called whenever lua encounters an unexpected error.
        extern "C" fn panic(lua: *mut ffi::lua_State) -> libc::c_int {
            let err = unsafe { ffi::lua_tostring(lua, -1) };
            let err = unsafe { CStr::from_ptr(err) };
            let err = String::from_utf8(err.to_bytes().to_vec()).unwrap();
            panic!("PANIC: unprotected error in call to Lua API ({})\n", err);
        }

        unsafe { ffi::lua_atpanic(lua, panic) };

        Lua {
            lua: LuaContext(lua),
            must_be_closed: true,
            marker: PhantomData,
        }
    }

    /// Takes an existing `lua_State` and build a Lua object from it.
    ///
    /// # Arguments
    ///
    ///  * `close_at_the_end`: if true, lua_close will be called on the lua_State on the destructor
    pub unsafe fn from_existing_state<T>(lua: *mut T, close_at_the_end: bool) -> Lua<'lua> {
        Lua {
            lua: std::mem::transmute(lua),
            must_be_closed: close_at_the_end,
            marker: PhantomData,
        }
    }

    /// Opens all standard Lua libraries.
    /// This is done by calling `luaL_openlibs`.
    pub fn openlibs(&mut self) {
        unsafe { ffi::luaL_openlibs(self.lua.0) }
    }

    /// Executes some Lua code on the context.
    pub fn execute<'a, T>(&'a mut self, code: &str) -> Result<T, LuaError>
                          where T: for<'g> LuaRead<&'g mut PushGuard<&'a mut Lua<'lua>>> +
                                   for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>
    {
        let mut f = try!(functions_read::LuaFunction::load(self, code));
        f.call()
    }

    /// Executes some Lua code on the context.
    pub fn execute_from_reader<'a, T, R>(&'a mut self, code: R) -> Result<T, LuaError>
            where T: for<'g> LuaRead<&'g mut PushGuard<&'a mut Lua<'lua>>> +
                     for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>,
                  R: Read
    {
        let mut f = try!(functions_read::LuaFunction::load_from_reader(self, code));
        f.call()
    }

    /// Reads the value of a global variable.
    pub fn get<'l, V, I>(&'l mut self, index: I) -> Option<V>
                         where I: Borrow<str>, V: LuaRead<PushGuard<&'l mut Lua<'lua>>>
    {
        let index = CString::new(index.borrow()).unwrap();
        unsafe { ffi::lua_getglobal(self.lua.0, index.as_ptr()); }
        let guard = PushGuard { lua: self, size: 1 };
        LuaRead::lua_read(guard).ok()
    }

    /// Modifies the value of a global variable.
    pub fn set<'a, I, V>(&'a mut self, index: I, value: V)
                         where I: Borrow<str>, V: Push<&'a mut Lua<'lua>>
    {
        let index = CString::new(index.borrow()).unwrap();
        value.push_to_lua(self).forget();
        unsafe { ffi::lua_setglobal(self.lua.0, index.as_ptr()); }
    }

    /// Inserts an empty array, then loads it.
    pub fn empty_array<'a, I>(&'a mut self, index: I) -> LuaTable<PushGuard<&'a mut Lua<'lua>>>
                              where I: Borrow<str>
    {
        // TODO: cleaner implementation
        let mut me = self;
        let index2 = CString::new(index.borrow()).unwrap();
        Vec::<u8>::with_capacity(0).push_to_lua(&mut me).forget();
        unsafe { ffi::lua_setglobal(me.lua.0, index2.as_ptr()); }

        me.get(index).unwrap()
    }
}

impl<'lua> Drop for Lua<'lua> {
    fn drop(&mut self) {
        if self.must_be_closed {
            unsafe { ffi::lua_close(self.lua.0) }
        }
    }
}

impl<L> Drop for PushGuard<L> where L: AsMutLua {
    fn drop(&mut self) {
        if self.size != 0 {
            unsafe { ffi::lua_pop(self.lua.as_mut_lua().0, self.size); }
        }
    }
}
<commit_msg>Changed signature of set to put lifetime param on V<commit_after>#![feature(core)]
#![feature(reflect_marker)]
#![feature(unboxed_closures)]

extern crate lua52_sys as ffi;
extern crate libc;

use std::ffi::{CStr, CString};
use std::io::Read;
use std::io::Error as IoError;
use std::borrow::Borrow;
use std::marker::PhantomData;

pub use functions_read::LuaFunction;
pub use functions_write::{function, InsideCallback};
pub use lua_tables::LuaTable;

pub mod any;
pub mod functions_read;
pub mod lua_tables;
pub mod userdata;

mod functions_write;
mod macros;
mod rust_tables;
mod values;
mod tuples;

/// Main object of the library.
///
/// The lifetime parameter corresponds to the lifetime of the content of the Lua context.
pub struct Lua<'lua> {
    lua: LuaContext,
    must_be_closed: bool,
    marker: PhantomData<&'lua ()>,
}

/// RAII guard for a value pushed on the stack.
pub struct PushGuard<L> where L: AsMutLua {
    lua: L,
    size: i32,
}

impl<L> PushGuard<L> where L: AsMutLua {
    /// Prevents the value from being poped when the `PushGuard` is destroyed, and returns the
    /// number of elements on the stack.
    fn forget(mut self) -> i32 {
        let size = self.size;
        self.size = 0;
        size
    }
}

/// Trait for objects that have access to a Lua context. When using a context returned by a
/// `AsLua`, you are not allowed to modify the stack.
pub unsafe trait AsLua {
    fn as_lua(&self) -> LuaContext;
}

/// Trait for objects that have access to a Lua context. You are allowed to modify the stack, but
/// it must be in the same state as it was when you started.
pub unsafe trait AsMutLua: AsLua {
    fn as_mut_lua(&mut self) -> LuaContext;
}

/// Opaque type that contains the raw Lua context.
#[derive(Copy, Clone)]
#[allow(raw_pointer_derive)]
pub struct LuaContext(*mut ffi::lua_State);
unsafe impl Send for LuaContext {}

unsafe impl<'a, 'lua> AsLua for &'a Lua<'lua> {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a, 'lua> AsLua for &'a mut Lua<'lua> {
    fn as_lua(&self) -> LuaContext {
        self.lua
    }
}

unsafe impl<'a, 'lua> AsMutLua for &'a mut Lua<'lua> {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua
    }
}

unsafe impl<L> AsLua for PushGuard<L> where L: AsMutLua {
    fn as_lua(&self) -> LuaContext {
        self.lua.as_lua()
    }
}

unsafe impl<L> AsMutLua for PushGuard<L> where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        self.lua.as_mut_lua()
    }
}

unsafe impl<'a, L> AsLua for &'a L where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        (**self).as_lua()
    }
}

unsafe impl<'a, L> AsLua for &'a mut L where L: AsLua {
    fn as_lua(&self) -> LuaContext {
        (**self).as_lua()
    }
}

unsafe impl<'a, L> AsMutLua for &'a mut L where L: AsMutLua {
    fn as_mut_lua(&mut self) -> LuaContext {
        (**self).as_mut_lua()
    }
}

/// Types that can be given to a Lua context, for example with `lua.set()` or as a return value
/// of a function.
pub trait Push<L> where L: AsMutLua {
    /// Pushes the value on the top of the stack.
    ///
    /// Must return a guard representing the elements that have been pushed.
    ///
    /// You can implement this for any type you want by redirecting to call to
    /// another implementation (for example `5.push_to_lua`) or by calling
    /// `userdata::push_userdata`.
    fn push_to_lua(self, lua: L) -> PushGuard<L>;
}

/// Types that can be obtained from a Lua context.
///
/// Most types that implement `Push` also implement `LuaRead`, but this is not always the case
/// (for example `&'static str` implements `Push` but not `LuaRead`).
pub trait LuaRead<L>: Sized where L: AsLua {
    /// Reads the data from Lua.
    fn lua_read(lua: L) -> Result<Self, L> {
        LuaRead::lua_read_at_position(lua, -1)
    }

    /// Reads the data from Lua at a given position.
    fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L>;
}

/// Error that can happen when executing Lua code.
#[derive(Debug)]
pub enum LuaError {
    /// There was a syntax error when parsing the Lua code.
    SyntaxError(String),

    /// There was an error during execution of the Lua code
    /// (for example not enough parameters for a function call).
    ExecutionError(String),

    /// There was an IoError while reading the source code to execute.
    ReadError(IoError),

    /// The call to `execute` has requested the wrong type of data.
    WrongType,
}

impl<'lua> Lua<'lua> {
    /// Builds a new Lua context.
    ///
    /// # Panic
    ///
    /// The function panics if the underlying call to `lua_newstate` fails
    /// (which indicates lack of memory).
    pub fn new() -> Lua<'lua> {
        let lua = unsafe { ffi::lua_newstate(alloc, std::ptr::null_mut()) };
        if lua.is_null() {
            panic!("lua_newstate failed");
        }

        // this alloc function is required to create a lua state.
        extern "C" fn alloc(_ud: *mut libc::c_void, ptr: *mut libc::c_void, _osize: libc::size_t,
                            nsize: libc::size_t) -> *mut libc::c_void
        {
            unsafe {
                if nsize == 0 {
                    libc::free(ptr as *mut libc::c_void);
                    std::ptr::null_mut()
                } else {
                    libc::realloc(ptr, nsize)
                }
            }
        }

        // called whenever lua encounters an unexpected error.
        extern "C" fn panic(lua: *mut ffi::lua_State) -> libc::c_int {
            let err = unsafe { ffi::lua_tostring(lua, -1) };
            let err = unsafe { CStr::from_ptr(err) };
            let err = String::from_utf8(err.to_bytes().to_vec()).unwrap();
            panic!("PANIC: unprotected error in call to Lua API ({})\n", err);
        }

        unsafe { ffi::lua_atpanic(lua, panic) };

        Lua {
            lua: LuaContext(lua),
            must_be_closed: true,
            marker: PhantomData,
        }
    }

    /// Takes an existing `lua_State` and build a Lua object from it.
    ///
    /// # Arguments
    ///
    ///  * `close_at_the_end`: if true, lua_close will be called on the lua_State on the destructor
    pub unsafe fn from_existing_state<T>(lua: *mut T, close_at_the_end: bool) -> Lua<'lua> {
        Lua {
            lua: std::mem::transmute(lua),
            must_be_closed: close_at_the_end,
            marker: PhantomData,
        }
    }

    /// Opens all standard Lua libraries.
    /// This is done by calling `luaL_openlibs`.
    pub fn openlibs(&mut self) {
        unsafe { ffi::luaL_openlibs(self.lua.0) }
    }

    /// Executes some Lua code on the context.
    pub fn execute<'a, T>(&'a mut self, code: &str) -> Result<T, LuaError>
                          where T: for<'g> LuaRead<&'g mut PushGuard<&'a mut Lua<'lua>>> +
                                   for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>
    {
        let mut f = try!(functions_read::LuaFunction::load(self, code));
        f.call()
    }

    /// Executes some Lua code on the context.
    pub fn execute_from_reader<'a, T, R>(&'a mut self, code: R) -> Result<T, LuaError>
            where T: for<'g> LuaRead<&'g mut PushGuard<&'a mut Lua<'lua>>> +
                     for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>,
                  R: Read
    {
        let mut f = try!(functions_read::LuaFunction::load_from_reader(self, code));
        f.call()
    }

    /// Reads the value of a global variable.
    pub fn get<'l, V, I>(&'l mut self, index: I) -> Option<V>
                         where I: Borrow<str>, V: LuaRead<PushGuard<&'l mut Lua<'lua>>>
    {
        let index = CString::new(index.borrow()).unwrap();
        unsafe { ffi::lua_getglobal(self.lua.0, index.as_ptr()); }
        let guard = PushGuard { lua: self, size: 1 };
        LuaRead::lua_read(guard).ok()
    }

    /// Modifies the value of a global variable.
    pub fn set<I, V>(& mut self, index: I, value: V)
                         where I: Borrow<str>, for <'a> V: Push<&'a mut Lua<'lua>>
    {
        let index = CString::new(index.borrow()).unwrap();
        value.push_to_lua(self).forget();
        unsafe { ffi::lua_setglobal(self.lua.0, index.as_ptr()); }
    }

    /// Inserts an empty array, then loads it.
    pub fn empty_array<'a, I>(&'a mut self, index: I) -> LuaTable<PushGuard<&'a mut Lua<'lua>>>
                              where I: Borrow<str>
    {
        // TODO: cleaner implementation
        let mut me = self;
        let index2 = CString::new(index.borrow()).unwrap();
        Vec::<u8>::with_capacity(0).push_to_lua(&mut me).forget();
        unsafe { ffi::lua_setglobal(me.lua.0, index2.as_ptr()); }

        me.get(index).unwrap()
    }
}

impl<'lua> Drop for Lua<'lua> {
    fn drop(&mut self) {
        if self.must_be_closed {
            unsafe { ffi::lua_close(self.lua.0) }
        }
    }
}

impl<L> Drop for PushGuard<L> where L: AsMutLua {
    fn drop(&mut self) {
        if self.size != 0 {
            unsafe { ffi::lua_pop(self.lua.as_mut_lua().0, self.size); }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Update codecs/resize/src/lib.rs<commit_after><|endoftext|>