<commit_before><commit_msg>Make a new common projects path function<commit_after>use args::Args;
#[cfg(not(test))]
use dirs::home_dir;
use std::path::PathBuf;

pub static MUXED_FOLDER: &str = ".muxed";
static CONFIG_EXTENSION: &str = "yml";

pub struct ProjectPaths {
    pub home_directory: PathBuf,
    pub project_directory: PathBuf,
    pub project_file: PathBuf,
}

impl ProjectPaths {
    pub fn new(home_directory: PathBuf, project_directory: PathBuf, project_file: PathBuf) -> ProjectPaths {
        ProjectPaths {
            home_directory,
            project_directory,
            project_file,
        }
    }

    #[cfg(test)]
    pub fn from_strs(home_directory: &str, project_directory: &str, project_file: &str) -> ProjectPaths {
        let home_directory = PathBuf::from(home_directory);
        let project_directory = home_directory.join(project_directory);
        let project_file = project_directory.join(project_file).with_extension(CONFIG_EXTENSION);

        ProjectPaths {
            home_directory,
            project_directory,
            project_file,
        }
    }
}

/// A common method for returning the project directory and filepath. The method
/// will check for a passed argument set with -p but if it does not exist will
/// map the path for the .muxed directory in the users home directory and return
/// that as the default.
pub fn project_paths(args: &Args) -> ProjectPaths {
    let homedir = homedir().expect("We couldn't find your home directory.");
    let default_dir = homedir.join(MUXED_FOLDER);
    let project_directory = args.flag_p.as_ref().map_or(default_dir, |p| PathBuf::from(p));

    let project_filename = PathBuf::from(&args.arg_project).with_extension(CONFIG_EXTENSION);
    let project_fullpath = project_directory.join(project_filename);

    ProjectPaths::new(homedir, project_directory, project_fullpath)
}

/// A Thin wrapper around the home_dir crate. This is so we can swap the default
/// dir out during testing.
#[cfg(not(test))]
fn homedir() -> Option<PathBuf> {
    home_dir()
}

/// Return the temp dir as the users home dir during testing.
#[cfg(test)]
fn homedir() -> Option<PathBuf> {
    Some(PathBuf::from("/tmp"))
}

#[cfg(test)]
mod test {
    #[test]
    fn

}
<|endoftext|>


<commit_before><commit_msg>need?<commit_after><|endoftext|>


<commit_before><commit_msg>add some threading documentation<commit_after><|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::Command;
use std::env;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use logger::ImagLogger;

use libimagstore::store::Store;

pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;
        use std::error::Error;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");

        Runtime::init_logger(is_debugging, is_verbose);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map(PathBuf::from)
            .unwrap_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            });
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                });

        let cfg = Configuration::new(&rtp);
        let cfg = if cfg.is_err() {
            let e = cfg.err().unwrap();
            if e.kind() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                None
            }
        } else {
            Some(cfg.unwrap())
        };

        let store_config = {
            match &cfg {
                &Some(ref c) => c.store_config().map(|c| c.clone()),
                _ => None
            }
        };

        Store::new(storepath, store_config).map(|store| {
            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err(|e| {
            RuntimeError::new(RuntimeErrorKind::Instantiate, Some(Box::new(e)))
        })
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name("verbosity")
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("debugging")
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("config")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("storepath")
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("editor")
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool) {
        let lvl = if is_debugging {
            LogLevelFilter::Debug
        } else if is_verbose {
            LogLevelFilter::Info
        } else {
            LogLevelFilter::Error
        };

        log::set_logger(|max_log_lvl| {
            max_log_lvl.set(lvl);
            debug!("Init logger with {}", lvl);
            Box::new(ImagLogger::new(lvl.to_log_level().unwrap()))
        })
        .map_err(|_| {
            panic!("Could not setup logger");
        })
        .ok();
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match &self.configuration {
                    &Some(ref c) => c.editor().map(|s| s.clone()),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<commit_msg>Add Runtime::config()<commit_after>use std::path::PathBuf;
use std::process::Command;
use std::env;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use logger::ImagLogger;

use libimagstore::store::Store;

pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;
        use std::error::Error;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");

        Runtime::init_logger(is_debugging, is_verbose);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map(PathBuf::from)
            .unwrap_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            });
        let storepath = matches.value_of("storepath")
                                .map(PathBuf::from)
                                .unwrap_or({
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                });

        let cfg = Configuration::new(&rtp);
        let cfg = if cfg.is_err() {
            let e = cfg.err().unwrap();
            if e.kind() != ConfigErrorKind::NoConfigFileFound {
                let cause : Option<Box<Error>> = Some(Box::new(e));
                return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause));
            } else {
                None
            }
        } else {
            Some(cfg.unwrap())
        };

        let store_config = {
            match &cfg {
                &Some(ref c) => c.store_config().map(|c| c.clone()),
                _ => None
            }
        };

        Store::new(storepath, store_config).map(|store| {
            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err(|e| {
            RuntimeError::new(RuntimeErrorKind::Instantiate, Some(Box::new(e)))
        })
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name("verbosity")
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("debugging")
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name("config")
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("runtimepath")
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("storepath")
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name("editor")
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool) {
        let lvl = if is_debugging {
            LogLevelFilter::Debug
        } else if is_verbose {
            LogLevelFilter::Info
        } else {
            LogLevelFilter::Error
        };

        log::set_logger(|max_log_lvl| {
            max_log_lvl.set(lvl);
            debug!("Init logger with {}", lvl);
            Box::new(ImagLogger::new(lvl.to_log_level().unwrap()))
        })
        .map_err(|_| {
            panic!("Could not setup logger");
        })
        .ok();
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match &self.configuration {
                    &Some(ref c) => c.editor().map(|s| s.clone()),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

<|endoftext|>


<commit_before><commit_msg>GH-ISSUE: #68 Finish making package_manager_command() function<commit_after><|endoftext|>


<commit_before>use std::ptr;
use gl;
use gl::types::*;
use nalgebra::na::{Vec2, Vec3, Mat3, Mat4};
use nalgebra::na;
use resource::Material;
use object::ObjectData;
use light::{Light, Absolute, StickToCamera};
use camera::Camera;
use resource::{Mesh, Shader, ShaderAttribute, ShaderUniform};

#[path = "../error.rs"]
mod error;

/// The default material used to draw objects.
pub struct ObjectMaterial {
    shader:     Shader,
    pos:        ShaderAttribute<Vec3<f32>>,
    normal:     ShaderAttribute<Vec3<f32>>,
    tex_coord:  ShaderAttribute<Vec2<f32>>,
    light:      ShaderUniform<Vec3<f32>>,
    color:      ShaderUniform<Vec3<f32>>,
    transform:  ShaderUniform<Mat4<f32>>,
    scale:      ShaderUniform<Mat3<f32>>,
    ntransform: ShaderUniform<Mat3<f32>>,
    view:       ShaderUniform<Mat4<f32>>,
    tex:        ShaderUniform<GLuint>
}

impl ObjectMaterial {
    /// Creates a new `ObjectMaterial`.
    pub fn new() -> ObjectMaterial {
        // load the shader
        let mut shader = Shader::new_from_str(OBJECT_VERTEX_SRC, OBJECT_FRAGMENT_SRC);

        shader.use_program();

        // get the variables locations
        ObjectMaterial {
            pos:        shader.get_attrib("position").unwrap(),
            normal:     shader.get_attrib("normal").unwrap(),
            tex_coord:  shader.get_attrib("tex_coord_v").unwrap(),
            light:      shader.get_uniform("light_position").unwrap(),
            color:      shader.get_uniform("color").unwrap(),
            transform:  shader.get_uniform("transform").unwrap(),
            scale:      shader.get_uniform("scale").unwrap(),
            ntransform: shader.get_uniform("ntransform").unwrap(),
            view:       shader.get_uniform("view").unwrap(),
            tex:        shader.get_uniform("tex").unwrap(),
            shader:     shader
        }
    }

    fn activate(&mut self) {
        self.shader.use_program();
        self.pos.enable();
        self.normal.enable();
        self.tex_coord.enable();
    }

    fn deactivate(&mut self) {
        self.pos.disable();
        self.normal.disable();
        self.tex_coord.disable();
    }
}

impl Material for ObjectMaterial {
    fn render(&mut self,
              pass:   uint,
              camera: &mut Camera,
              light:  &Light,
              data:   &ObjectData,
              mesh:   &mut Mesh) {
        self.activate();

        /*
         *
         * Setup camera and light.
         *
         */
        camera.upload(pass, &mut self.view);

        let pos = match *light {
            Absolute(ref p) => p.clone(),
            StickToCamera   => camera.eye()
        };

        self.light.upload(&pos);

        /*
         *
         * Setup object-related stuffs.
         *
         */
        let formated_transform:  Mat4<f32> = na::to_homogeneous(data.transform());
        let formated_ntransform: Mat3<f32> = *data.transform().rotation.submat();

        unsafe {
            self.transform.upload(&formated_transform);
            self.ntransform.upload(&formated_ntransform);
            self.scale.upload(data.scale());
            self.color.upload(data.color());

            mesh.bind(&mut self.pos, &mut self.normal, &mut self.tex_coord);

            verify!(gl::ActiveTexture(gl::TEXTURE0));
            verify!(gl::BindTexture(gl::TEXTURE_2D, data.texture().id()));

            verify!(gl::DrawElements(gl::TRIANGLES,
                    mesh.num_pts() as GLint,
                    gl::UNSIGNED_INT,
                    ptr::null()));
        }

        mesh.unbind();
        self.deactivate();
    }
}

/// Vertex shader of the default object material.
pub static OBJECT_VERTEX_SRC:   &'static str = A_VERY_LONG_STRING;
/// Fragment shader of the default object material.
pub static OBJECT_FRAGMENT_SRC: &'static str = ANOTHER_VERY_LONG_STRING;

static A_VERY_LONG_STRING: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec3 color;
    attribute vec2 tex_coord_v;
    varying vec3 ws_normal;
    varying vec3 ws_position;
    varying vec2 tex_coord;
    uniform mat4 view;
    uniform mat4 transform;
    uniform mat3 scale;
    uniform mat3 ntransform;
    void main() {
        mat4 scale4 = mat4(scale);
        vec4 pos4   = transform * scale4 * vec4(position, 1.0);
        tex_coord   = tex_coord_v;
        ws_position = pos4.xyz;
        gl_Position = view * pos4;
        ws_normal   = normalize(ntransform * scale * normal);
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
static ANOTHER_VERY_LONG_STRING: &'static str =
   "#version 120
    uniform vec3      color;
    uniform vec3      light_position;
    uniform sampler2D tex;
    varying vec2      tex_coord;
    varying vec3      ws_normal;
    varying vec3      ws_position;
    void main() {
      vec3 L = normalize(light_position - ws_position);
      vec3 E = normalize(-ws_position);

      //calculate Ambient Term:
      vec4 Iamb = vec4(1.0, 1.0, 1.0, 1.0);

      //calculate Diffuse Term:
      vec4 Idiff1 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(ws_normal,L), 0.0);
      Idiff1 = clamp(Idiff1, 0.0, 1.0);

      // double sided lighting:
      vec4 Idiff2 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(-ws_normal,L), 0.0);
      Idiff2 = clamp(Idiff2, 0.0, 1.0);

      vec4 tex_color = texture2D(tex, tex_coord);
      gl_FragColor   = tex_color * (vec4(color, 1.0) + Iamb + (Idiff1 + Idiff2) / 2) / 3;
    }";
<commit_msg>Sets the ambient lighting to be entirely based on the color of the object, instead of having a white component.<commit_after>use std::ptr;
use gl;
use gl::types::*;
use nalgebra::na::{Vec2, Vec3, Mat3, Mat4};
use nalgebra::na;
use resource::Material;
use object::ObjectData;
use light::{Light, Absolute, StickToCamera};
use camera::Camera;
use resource::{Mesh, Shader, ShaderAttribute, ShaderUniform};

#[path = "../error.rs"]
mod error;

/// The default material used to draw objects.
pub struct ObjectMaterial {
    shader:     Shader,
    pos:        ShaderAttribute<Vec3<f32>>,
    normal:     ShaderAttribute<Vec3<f32>>,
    tex_coord:  ShaderAttribute<Vec2<f32>>,
    light:      ShaderUniform<Vec3<f32>>,
    color:      ShaderUniform<Vec3<f32>>,
    transform:  ShaderUniform<Mat4<f32>>,
    scale:      ShaderUniform<Mat3<f32>>,
    ntransform: ShaderUniform<Mat3<f32>>,
    view:       ShaderUniform<Mat4<f32>>,
    tex:        ShaderUniform<GLuint>
}

impl ObjectMaterial {
    /// Creates a new `ObjectMaterial`.
    pub fn new() -> ObjectMaterial {
        // load the shader
        let mut shader = Shader::new_from_str(OBJECT_VERTEX_SRC, OBJECT_FRAGMENT_SRC);

        shader.use_program();

        // get the variables locations
        ObjectMaterial {
            pos:        shader.get_attrib("position").unwrap(),
            normal:     shader.get_attrib("normal").unwrap(),
            tex_coord:  shader.get_attrib("tex_coord_v").unwrap(),
            light:      shader.get_uniform("light_position").unwrap(),
            color:      shader.get_uniform("color").unwrap(),
            transform:  shader.get_uniform("transform").unwrap(),
            scale:      shader.get_uniform("scale").unwrap(),
            ntransform: shader.get_uniform("ntransform").unwrap(),
            view:       shader.get_uniform("view").unwrap(),
            tex:        shader.get_uniform("tex").unwrap(),
            shader:     shader
        }
    }

    fn activate(&mut self) {
        self.shader.use_program();
        self.pos.enable();
        self.normal.enable();
        self.tex_coord.enable();
    }

    fn deactivate(&mut self) {
        self.pos.disable();
        self.normal.disable();
        self.tex_coord.disable();
    }
}

impl Material for ObjectMaterial {
    fn render(&mut self,
              pass:   uint,
              camera: &mut Camera,
              light:  &Light,
              data:   &ObjectData,
              mesh:   &mut Mesh) {
        self.activate();

        /*
         *
         * Setup camera and light.
         *
         */
        camera.upload(pass, &mut self.view);

        let pos = match *light {
            Absolute(ref p) => p.clone(),
            StickToCamera   => camera.eye()
        };

        self.light.upload(&pos);

        /*
         *
         * Setup object-related stuffs.
         *
         */
        let formated_transform:  Mat4<f32> = na::to_homogeneous(data.transform());
        let formated_ntransform: Mat3<f32> = *data.transform().rotation.submat();

        unsafe {
            self.transform.upload(&formated_transform);
            self.ntransform.upload(&formated_ntransform);
            self.scale.upload(data.scale());
            self.color.upload(data.color());

            mesh.bind(&mut self.pos, &mut self.normal, &mut self.tex_coord);

            verify!(gl::ActiveTexture(gl::TEXTURE0));
            verify!(gl::BindTexture(gl::TEXTURE_2D, data.texture().id()));

            verify!(gl::DrawElements(gl::TRIANGLES,
                    mesh.num_pts() as GLint,
                    gl::UNSIGNED_INT,
                    ptr::null()));
        }

        mesh.unbind();
        self.deactivate();
    }
}

/// Vertex shader of the default object material.
pub static OBJECT_VERTEX_SRC:   &'static str = A_VERY_LONG_STRING;
/// Fragment shader of the default object material.
pub static OBJECT_FRAGMENT_SRC: &'static str = ANOTHER_VERY_LONG_STRING;

static A_VERY_LONG_STRING: &'static str =
   "#version 120
    attribute vec3 position;
    attribute vec3 normal;
    attribute vec3 color;
    attribute vec2 tex_coord_v;
    varying vec3 ws_normal;
    varying vec3 ws_position;
    varying vec2 tex_coord;
    uniform mat4 view;
    uniform mat4 transform;
    uniform mat3 scale;
    uniform mat3 ntransform;
    void main() {
        mat4 scale4 = mat4(scale);
        vec4 pos4   = transform * scale4 * vec4(position, 1.0);
        tex_coord   = tex_coord_v;
        ws_position = pos4.xyz;
        gl_Position = view * pos4;
        ws_normal   = normalize(ntransform * scale * normal);
    }";

// phong lighting (heavily) inspired
// by http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
static ANOTHER_VERY_LONG_STRING: &'static str =
   "#version 120
    uniform vec3      color;
    uniform vec3      light_position;
    uniform sampler2D tex;
    varying vec2      tex_coord;
    varying vec3      ws_normal;
    varying vec3      ws_position;
    void main() {
      vec3 L = normalize(light_position - ws_position);
      vec3 E = normalize(-ws_position);

      //calculate Ambient Term:
      vec4 Iamb = vec4(color, 1.0);

      //calculate Diffuse Term:
      vec4 Idiff1 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(ws_normal,L), 0.0);
      Idiff1 = clamp(Idiff1, 0.0, 1.0);

      // double sided lighting:
      vec4 Idiff2 = vec4(1.0, 1.0, 1.0, 1.0) * max(dot(-ws_normal,L), 0.0);
      Idiff2 = clamp(Idiff2, 0.0, 1.0);

      vec4 tex_color = texture2D(tex, tex_coord);
      gl_FragColor   = tex_color * (Iamb + (Idiff1 + Idiff2) / 2) / 2;
    }";
<|endoftext|>


<commit_before><commit_msg>Added a changelog example<commit_after>extern crate futures;
extern crate tokio_core;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use futures::stream::Stream;
use tokio_core::reactor::Core;
use reql::{Client, Document, Run};

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * r.db('test').table('test').insert({ test: 1 })
 *
 */

#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32
}

#[derive(Debug, Serialize, Deserialize)]
struct Change {
    // Upon deserialisation:
    // We'll change the rethinkdb change "type" to avoid  naming issues
    #[serde(rename(deserialize = "type"))]
    action: String,
    new_val: TestItem,
    old_val: TestItem,
}

fn main()
{
    // Create a new ReQL client
    let r = Client::new();

    // Create an even loop
    let core = Core::new().unwrap();

    // Create a connection pool
    let conn = r.connect(&core.handle()).unwrap();

    // Run the query
    let query = r.db("test")
        .table("test")
        .changes()

    // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {
                // Extract the change type
                print!("{} action received\n\t=> ", change.action);

                // Match the change type
                match change.action.as_ref() {
                    "add" => println!("{:?}", change.new_val),
                    "remove" => println!("{:?}", change.old_val),
                    "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),

                    _ => println!("{:?}", change)
                }
            }
            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("{}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
        .or_else(|error| {
            println!("{:?}", error);
            Err(())
        });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<|endoftext|>


<commit_before><commit_msg>Just let String grow on its own<commit_after><|endoftext|>


<commit_before>// Copyright 2014 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 module provides a simplified abstraction for working with
//! code blocks identified by their integer node-id.  In particular,
//! it captures a common set of attributes that all "function-like
//! things" (represented by `FnLike` instances) share.  For example,
//! all `FnLike` instances have a type signature (be it explicit or
//! inferred).  And all `FnLike` instances have a body, i.e. the code
//! that is run when the function-like thing it represents is invoked.
//!
//! With the above abstraction in place, one can treat the program
//! text as a collection of blocks of code (and most such blocks are
//! nested within a uniquely determined `FnLike`), and users can ask
//! for the `Code` associated with a particular NodeId.

use hir as ast;
use hir::map::{self, Node};
use hir::{Expr, FnDecl};
use hir::intravisit::FnKind;
use syntax::ast::{Attribute, Ident, Name, NodeId};
use syntax_pos::Span;

/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc).
///
/// More specifically, it is one of either:
///
///   - A function item,
///   - A closure expr (i.e. an ExprKind::Closure), or
///   - The default implementation for a trait method.
///
/// To construct one, use the `Code::from_node` function.
#[derive(Copy, Clone, Debug)]
pub struct FnLikeNode<'a> { node: map::Node<'a> }

/// MaybeFnLike wraps a method that indicates if an object
/// corresponds to some FnLikeNode.
pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }

impl MaybeFnLike for ast::Item {
    fn is_fn_like(&self) -> bool {
        match self.node { ast::ItemKind::Fn(..) => true, _ => false, }
    }
}

impl MaybeFnLike for ast::TraitItem {
    fn is_fn_like(&self) -> bool {
        match self.node {
            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
            _ => false,
        }
    }
}

impl MaybeFnLike for ast::Expr {
    fn is_fn_like(&self) -> bool {
        match self.node {
            ast::ExprKind::Closure(..) => true,
            _ => false,
        }
    }
}

/// Carries either an FnLikeNode or a Expr, as these are the two
/// constructs that correspond to "code" (as in, something from which
/// we can construct a control-flow graph).
#[derive(Copy, Clone)]
pub enum Code<'a> {
    FnLike(FnLikeNode<'a>),
    Expr(&'a Expr),
}

impl<'a> Code<'a> {
    pub fn id(&self) -> NodeId {
        match *self {
            Code::FnLike(node) => node.id(),
            Code::Expr(block) => block.id,
        }
    }

    /// Attempts to construct a Code from presumed FnLike or Expr node input.
    pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option<Code<'a>> {
        match map.get(id) {
            map::NodeBlock(_) => {
                //  Use the parent, hopefully an expression node.
                Code::from_node(map, map.get_parent_node(id))
            }
            map::NodeExpr(expr) => Some(Code::Expr(expr)),
            node => FnLikeNode::from_node(node).map(Code::FnLike)
        }
    }
}

/// These are all the components one can extract from a fn item for
/// use when implementing FnLikeNode operations.
struct ItemFnParts<'a> {
    name:     Name,
    decl:     &'a ast::FnDecl,
    header:   ast::FnHeader,
    vis:      &'a ast::Visibility,
    generics: &'a ast::Generics,
    body:     ast::BodyId,
    id:       NodeId,
    span:     Span,
    attrs:    &'a [Attribute],
}

/// These are all the components one can extract from a closure expr
/// for use when implementing FnLikeNode operations.
struct ClosureParts<'a> {
    decl: &'a FnDecl,
    body: ast::BodyId,
    id: NodeId,
    span: Span,
    attrs: &'a [Attribute],
}

impl<'a> ClosureParts<'a> {
    fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
        ClosureParts {
            decl: d,
            body: b,
            id,
            span: s,
            attrs,
        }
    }
}

impl<'a> FnLikeNode<'a> {
    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
    pub fn from_node(node: Node) -> Option<FnLikeNode> {
        let fn_like = match node {
            map::NodeItem(item) => item.is_fn_like(),
            map::NodeTraitItem(tm) => tm.is_fn_like(),
            map::NodeImplItem(_) => true,
            map::NodeExpr(e) => e.is_fn_like(),
            _ => false
        };
        if fn_like {
            Some(FnLikeNode {
                node,
            })
        } else {
            None
        }
    }

    pub fn body(self) -> ast::BodyId {
        self.handle(|i: ItemFnParts<'a>|  i.body,
                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _|  body,
                    |c: ClosureParts<'a>| c.body)
    }

    pub fn decl(self) -> &'a FnDecl {
        self.handle(|i: ItemFnParts<'a>|  &*i.decl,
                    |_, _, sig: &'a ast::MethodSig, _, _, _, _|  &sig.decl,
                    |c: ClosureParts<'a>| c.decl)
    }

    pub fn span(self) -> Span {
        self.handle(|i: ItemFnParts|     i.span,
                    |_, _, _: &'a ast::MethodSig, _, _, span, _| span,
                    |c: ClosureParts|    c.span)
    }

    pub fn id(self) -> NodeId {
        self.handle(|i: ItemFnParts|     i.id,
                    |id, _, _: &'a ast::MethodSig, _, _, _, _| id,
                    |c: ClosureParts|    c.id)
    }

    pub fn constness(self) -> ast::Constness {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.constness,
            FnKind::Method(_, m, ..) => m.header.constness,
            _ => ast::Constness::NotConst
        }
    }

    pub fn asyncness(self) -> ast::IsAsync {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.asyncness,
            FnKind::Method(_, m, ..) => m.header.asyncness,
            _ => ast::IsAsync::NotAsync
        }
    }

    pub fn unsafety(self) -> ast::Unsafety {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.unsafety,
            FnKind::Method(_, m, ..) => m.header.unsafety,
            _ => ast::Unsafety::Normal
        }
    }

    pub fn kind(self) -> FnKind<'a> {
        let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
            FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
        };
        let closure = |c: ClosureParts<'a>| {
            FnKind::Closure(c.attrs)
        };
        let method = |_, ident: Ident, sig: &'a ast::MethodSig, vis, _, _, attrs| {
            FnKind::Method(ident, sig, vis, attrs)
        };
        self.handle(item, method, closure)
    }

    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
        I: FnOnce(ItemFnParts<'a>) -> A,
        M: FnOnce(NodeId,
                  Ident,
                  &'a ast::MethodSig,
                  Option<&'a ast::Visibility>,
                  ast::BodyId,
                  Span,
                  &'a [Attribute])
                  -> A,
        C: FnOnce(ClosureParts<'a>) -> A,
    {
        match self.node {
            map::NodeItem(i) => match i.node {
                ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
                    item_fn(ItemFnParts {
                        id: i.id,
                        name: i.name,
                        decl: &decl,
                        body: block,
                        vis: &i.vis,
                        span: i.span,
                        attrs: &i.attrs,
                        header,
                        generics,
                    }),
                _ => bug!("item FnLikeNode that is not fn-like"),
            },
            map::NodeTraitItem(ti) => match ti.node {
                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
                    method(ti.id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                }
                _ => bug!("trait method FnLikeNode that is not fn-like"),
            },
            map::NodeImplItem(ii) => {
                match ii.node {
                    ast::ImplItemKind::Method(ref sig, body) => {
                        method(ii.id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                    }
                    _ => {
                        bug!("impl method FnLikeNode that is not fn-like")
                    }
                }
            },
            map::NodeExpr(e) => match e.node {
                ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) =>
                    closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)),
                _ => bug!("expr FnLikeNode that is not fn-like"),
            },
            _ => bug!("other FnLikeNode that is not fn-like"),
        }
    }
}
<commit_msg>Only methods are fn-like, not other associated items<commit_after>// Copyright 2014 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 module provides a simplified abstraction for working with
//! code blocks identified by their integer node-id.  In particular,
//! it captures a common set of attributes that all "function-like
//! things" (represented by `FnLike` instances) share.  For example,
//! all `FnLike` instances have a type signature (be it explicit or
//! inferred).  And all `FnLike` instances have a body, i.e. the code
//! that is run when the function-like thing it represents is invoked.
//!
//! With the above abstraction in place, one can treat the program
//! text as a collection of blocks of code (and most such blocks are
//! nested within a uniquely determined `FnLike`), and users can ask
//! for the `Code` associated with a particular NodeId.

use hir as ast;
use hir::map::{self, Node};
use hir::{Expr, FnDecl};
use hir::intravisit::FnKind;
use syntax::ast::{Attribute, Ident, Name, NodeId};
use syntax_pos::Span;

/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// and a body (as well as a NodeId, a span, etc).
///
/// More specifically, it is one of either:
///
///   - A function item,
///   - A closure expr (i.e. an ExprKind::Closure), or
///   - The default implementation for a trait method.
///
/// To construct one, use the `Code::from_node` function.
#[derive(Copy, Clone, Debug)]
pub struct FnLikeNode<'a> { node: map::Node<'a> }

/// MaybeFnLike wraps a method that indicates if an object
/// corresponds to some FnLikeNode.
pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }

impl MaybeFnLike for ast::Item {
    fn is_fn_like(&self) -> bool {
        match self.node { ast::ItemKind::Fn(..) => true, _ => false, }
    }
}

impl MaybeFnLike for ast::ImplItem {
    fn is_fn_like(&self) -> bool {
        match self.node { ast::ImplItemKind::Method(..) => true, _ => false, }
    }
}

impl MaybeFnLike for ast::TraitItem {
    fn is_fn_like(&self) -> bool {
        match self.node {
            ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true,
            _ => false,
        }
    }
}

impl MaybeFnLike for ast::Expr {
    fn is_fn_like(&self) -> bool {
        match self.node {
            ast::ExprKind::Closure(..) => true,
            _ => false,
        }
    }
}

/// Carries either an FnLikeNode or a Expr, as these are the two
/// constructs that correspond to "code" (as in, something from which
/// we can construct a control-flow graph).
#[derive(Copy, Clone)]
pub enum Code<'a> {
    FnLike(FnLikeNode<'a>),
    Expr(&'a Expr),
}

impl<'a> Code<'a> {
    pub fn id(&self) -> NodeId {
        match *self {
            Code::FnLike(node) => node.id(),
            Code::Expr(block) => block.id,
        }
    }

    /// Attempts to construct a Code from presumed FnLike or Expr node input.
    pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option<Code<'a>> {
        match map.get(id) {
            map::NodeBlock(_) => {
                //  Use the parent, hopefully an expression node.
                Code::from_node(map, map.get_parent_node(id))
            }
            map::NodeExpr(expr) => Some(Code::Expr(expr)),
            node => FnLikeNode::from_node(node).map(Code::FnLike)
        }
    }
}

/// These are all the components one can extract from a fn item for
/// use when implementing FnLikeNode operations.
struct ItemFnParts<'a> {
    name:     Name,
    decl:     &'a ast::FnDecl,
    header:   ast::FnHeader,
    vis:      &'a ast::Visibility,
    generics: &'a ast::Generics,
    body:     ast::BodyId,
    id:       NodeId,
    span:     Span,
    attrs:    &'a [Attribute],
}

/// These are all the components one can extract from a closure expr
/// for use when implementing FnLikeNode operations.
struct ClosureParts<'a> {
    decl: &'a FnDecl,
    body: ast::BodyId,
    id: NodeId,
    span: Span,
    attrs: &'a [Attribute],
}

impl<'a> ClosureParts<'a> {
    fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
        ClosureParts {
            decl: d,
            body: b,
            id,
            span: s,
            attrs,
        }
    }
}

impl<'a> FnLikeNode<'a> {
    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
    pub fn from_node(node: Node) -> Option<FnLikeNode> {
        let fn_like = match node {
            map::NodeItem(item) => item.is_fn_like(),
            map::NodeTraitItem(tm) => tm.is_fn_like(),
            map::NodeImplItem(it) => it.is_fn_like(),
            map::NodeExpr(e) => e.is_fn_like(),
            _ => false
        };
        if fn_like {
            Some(FnLikeNode {
                node,
            })
        } else {
            None
        }
    }

    pub fn body(self) -> ast::BodyId {
        self.handle(|i: ItemFnParts<'a>|  i.body,
                    |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _|  body,
                    |c: ClosureParts<'a>| c.body)
    }

    pub fn decl(self) -> &'a FnDecl {
        self.handle(|i: ItemFnParts<'a>|  &*i.decl,
                    |_, _, sig: &'a ast::MethodSig, _, _, _, _|  &sig.decl,
                    |c: ClosureParts<'a>| c.decl)
    }

    pub fn span(self) -> Span {
        self.handle(|i: ItemFnParts|     i.span,
                    |_, _, _: &'a ast::MethodSig, _, _, span, _| span,
                    |c: ClosureParts|    c.span)
    }

    pub fn id(self) -> NodeId {
        self.handle(|i: ItemFnParts|     i.id,
                    |id, _, _: &'a ast::MethodSig, _, _, _, _| id,
                    |c: ClosureParts|    c.id)
    }

    pub fn constness(self) -> ast::Constness {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.constness,
            FnKind::Method(_, m, ..) => m.header.constness,
            _ => ast::Constness::NotConst
        }
    }

    pub fn asyncness(self) -> ast::IsAsync {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.asyncness,
            FnKind::Method(_, m, ..) => m.header.asyncness,
            _ => ast::IsAsync::NotAsync
        }
    }

    pub fn unsafety(self) -> ast::Unsafety {
        match self.kind() {
            FnKind::ItemFn(_, _, header, ..) => header.unsafety,
            FnKind::Method(_, m, ..) => m.header.unsafety,
            _ => ast::Unsafety::Normal
        }
    }

    pub fn kind(self) -> FnKind<'a> {
        let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
            FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
        };
        let closure = |c: ClosureParts<'a>| {
            FnKind::Closure(c.attrs)
        };
        let method = |_, ident: Ident, sig: &'a ast::MethodSig, vis, _, _, attrs| {
            FnKind::Method(ident, sig, vis, attrs)
        };
        self.handle(item, method, closure)
    }

    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
        I: FnOnce(ItemFnParts<'a>) -> A,
        M: FnOnce(NodeId,
                  Ident,
                  &'a ast::MethodSig,
                  Option<&'a ast::Visibility>,
                  ast::BodyId,
                  Span,
                  &'a [Attribute])
                  -> A,
        C: FnOnce(ClosureParts<'a>) -> A,
    {
        match self.node {
            map::NodeItem(i) => match i.node {
                ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
                    item_fn(ItemFnParts {
                        id: i.id,
                        name: i.name,
                        decl: &decl,
                        body: block,
                        vis: &i.vis,
                        span: i.span,
                        attrs: &i.attrs,
                        header,
                        generics,
                    }),
                _ => bug!("item FnLikeNode that is not fn-like"),
            },
            map::NodeTraitItem(ti) => match ti.node {
                ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => {
                    method(ti.id, ti.ident, sig, None, body, ti.span, &ti.attrs)
                }
                _ => bug!("trait method FnLikeNode that is not fn-like"),
            },
            map::NodeImplItem(ii) => {
                match ii.node {
                    ast::ImplItemKind::Method(ref sig, body) => {
                        method(ii.id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs)
                    }
                    _ => {
                        bug!("impl method FnLikeNode that is not fn-like")
                    }
                }
            },
            map::NodeExpr(e) => match e.node {
                ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) =>
                    closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)),
                _ => bug!("expr FnLikeNode that is not fn-like"),
            },
            _ => bug!("other FnLikeNode that is not fn-like"),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Use `new_all_targets` in cargo-fix when no target selection exists<commit_after><|endoftext|>


<commit_before><commit_msg>Reworking on print command<commit_after><|endoftext|>


<commit_before>// Copyright 2015 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.

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(PartialEq)]
enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

struct Feature {
    level: Status,
    since: String,
    has_gate_test: bool,
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs"));
    assert!(!features.is_empty());
    let mut lib_features = HashMap::<String, Feature>::new();

    let mut contents = String::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => {
                    err("malformed stability attribute");
                    continue;
                }
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err("malformed stability attribute");
                    continue;
                }
                None => "None",
            };

            if features.contains_key(feature_name) {
                err("duplicating a lang feature");
            }
            if let Some(ref s) = lib_features.get(feature_name) {
                if s.level != level {
                    err("different stability level than before");
                }
                if s.since != since {
                    err("different `since` than before");
                }
                continue;
            }
            lib_features.insert(feature_name.to_owned(),
                                Feature {
                                    level: level,
                                    since: since.to_owned(),
                                    has_gate_test: false,
                                });
        }
    });

    super::walk_many(&[&path.join("test/compile-fail"),
                       &path.join("test/compile-fail-fulldeps"),
                       &path.join("test/parse-fail"),],
                     &mut |path| super::filter_dirs(path),
                     &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            let found_feature = features.get_mut(feature_name)
                                        .map(|v| { v.has_gate_test = true; () })
                                        .is_some();

            let found_lib_feature = features.get_mut(feature_name)
                                            .map(|v| { v.has_gate_test = true; () })
                                            .is_some();

            if !(found_feature || found_lib_feature) {
                err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                             feature_name));
            }
        }
    });

    // FIXME get this whitelist empty.
    let whitelist = vec![
    ];

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .filter(|&(n, _)| !whitelist.contains(&n.as_str()))
                                .collect::<Vec<_>>();

    for &(name, _) in gate_untested.iter() {
        println!("Expected a gate test for the feature '{}'.", name);
        println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\
                \n      test suite, with its failures due to missing usage of\
                \n      #![feature({})].", name, name);
        println!("Hint: If you already have such a test and don't want to rename it,\
                \n      you can also add a // gate-test-{} line to the test file.",
                 name);
    }

    if gate_untested.len() > 0 {
        println!("Found {} features without a gate test.", gate_untested.len());
        *bad = true;
    }

    if *bad {
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features.iter() {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str,
                   features: &mut HashMap<String, Feature>) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            Some((name.to_owned(),
                Feature {
                    level: level,
                    since: since.to_owned(),
                    has_gate_test: false,
                }))
        })
        .collect()
}
<commit_msg>Remove the compile-fail feature gates whitelist<commit_after>// Copyright 2015 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.

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(PartialEq)]
enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

struct Feature {
    level: Status,
    since: String,
    has_gate_test: bool,
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs"));
    assert!(!features.is_empty());
    let mut lib_features = HashMap::<String, Feature>::new();

    let mut contents = String::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => {
                    err("malformed stability attribute");
                    continue;
                }
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err("malformed stability attribute");
                    continue;
                }
                None => "None",
            };

            if features.contains_key(feature_name) {
                err("duplicating a lang feature");
            }
            if let Some(ref s) = lib_features.get(feature_name) {
                if s.level != level {
                    err("different stability level than before");
                }
                if s.since != since {
                    err("different `since` than before");
                }
                continue;
            }
            lib_features.insert(feature_name.to_owned(),
                                Feature {
                                    level: level,
                                    since: since.to_owned(),
                                    has_gate_test: false,
                                });
        }
    });

    super::walk_many(&[&path.join("test/compile-fail"),
                       &path.join("test/compile-fail-fulldeps"),
                       &path.join("test/parse-fail"),],
                     &mut |path| super::filter_dirs(path),
                     &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            let found_feature = features.get_mut(feature_name)
                                        .map(|v| { v.has_gate_test = true; () })
                                        .is_some();

            let found_lib_feature = features.get_mut(feature_name)
                                            .map(|v| { v.has_gate_test = true; () })
                                            .is_some();

            if !(found_feature || found_lib_feature) {
                err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                             feature_name));
            }
        }
    });

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .collect::<Vec<_>>();

    for &(name, _) in gate_untested.iter() {
        println!("Expected a gate test for the feature '{}'.", name);
        println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\
                \n      test suite, with its failures due to missing usage of\
                \n      #![feature({})].", name, name);
        println!("Hint: If you already have such a test and don't want to rename it,\
                \n      you can also add a // gate-test-{} line to the test file.",
                 name);
    }

    if gate_untested.len() > 0 {
        println!("Found {} features without a gate test.", gate_untested.len());
        *bad = true;
    }

    if *bad {
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features.iter() {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str,
                   features: &mut HashMap<String, Feature>) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            Some((name.to_owned(),
                Feature {
                    level: level,
                    since: since.to_owned(),
                    has_gate_test: false,
                }))
        })
        .collect()
}
<|endoftext|>


<commit_before><commit_msg>and again, forgot the real file..; other was cleanup & mysql testing<commit_after>extern crate mysql;

use mysql::conn::pool::MyPool;
use mysql::conn::pool::MyPooledConn;
use mysql::conn::Stmt;

use std::process::{Command, Stdio};
use std::error::Error;
use std::io::prelude::*;
use std::io::BufReader;

#[derive(Debug)]
pub enum DownloadError {
	ConsoleError,
	RadError,
	DMCAError,
	InternalError,
}

///Downloads a video, updates the DB
///TODO: get the sql statements out of the class
///TODO: wrap errors
///Doesn't care about DMCAs, will emit errors on them
pub fn download_video(url: &str, quality: i32, qid: i64, folderFormat: &str, pool: MyPool) -> Result<bool,DownloadError> {
	let process = match Command::new("youtube-dl")
								.arg("--newline")
								.arg(format!("-o {}",folderFormat))
								.arg(url)
								.stdin(Stdio::null())
                                .stdout(Stdio::piped())
                                .spawn() {
        Err(why) => panic!("couldn't spawn cmd: {}", Error::description(&why)),
        Ok(process) => process,
    };
	let mut s = String::new(); //buffer prep
	let mut stdout = BufReader::new(process.stdout.unwrap());

	let mut conn = pool.get_conn().unwrap();
	let statement = prepare_progress_updater(&mut conn);

	for line in &mut stdout.lines(){
		match line{
			Err(why) => panic!("couldn't read cmd stdout: {}", Error::description(&why)),
			Ok(text) => println!("{}",text),
		}
	}

	Ok(true)
}

fn prepare_progress_updater<'a>(conn: &'a mut MyPooledConn) -> Stmt<'a> {
	conn.prepare("UPDATE querydetails SET status = ? WHERE qid = ?").unwrap()
}

fn update_progress(stmt: &mut Stmt, progress: i32, qid: i64){
	stmt.execute(&[&progress,&qid]);
}<|endoftext|>


<commit_before>// Copyright 2015 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.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e., if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e., they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a `CString` out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut u8` that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const u8` that you got from
//! a C function. A `CStr` is guaranteed to be a nul-terminated array
//! of bytes. Once you have a `CStr`, you can convert it to a Rust
//! `&str` if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between `OsString`,
//! `OsStr` and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use `OsString` instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an `Option<OsString>`. If the environment variable exists
//! you will get a `Some(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! `OsString`.
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an `OsString` which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

#[stable(feature = "raw_os", since = "1.1.0")]
pub use core::ffi::c_void;

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
pub use core::ffi::VaList;

mod c_str;
mod os_str;
<commit_msg>Rollup merge of #56731 - GuillaumeGomez:ffi-doc-urls, r=Centril<commit_after>// Copyright 2015 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.

//! Utilities related to FFI bindings.
//!
//! This module provides utilities to handle data across non-Rust
//! interfaces, like other programming languages and the underlying
//! operating system. It is mainly of use for FFI (Foreign Function
//! Interface) bindings and code that needs to exchange C-like strings
//! with other languages.
//!
//! # Overview
//!
//! Rust represents owned strings with the [`String`] type, and
//! borrowed slices of strings with the [`str`] primitive. Both are
//! always in UTF-8 encoding, and may contain nul bytes in the middle,
//! i.e., if you look at the bytes that make up the string, there may
//! be a `\0` among them. Both `String` and `str` store their length
//! explicitly; there are no nul terminators at the end of strings
//! like in C.
//!
//! C strings are different from Rust strings:
//!
//! * **Encodings** - Rust strings are UTF-8, but C strings may use
//! other encodings. If you are using a string from C, you should
//! check its encoding explicitly, rather than just assuming that it
//! is UTF-8 like you can do in Rust.
//!
//! * **Character size** - C strings may use `char` or `wchar_t`-sized
//! characters; please **note** that C's `char` is different from Rust's.
//! The C standard leaves the actual sizes of those types open to
//! interpretation, but defines different APIs for strings made up of
//! each character type. Rust strings are always UTF-8, so different
//! Unicode characters will be encoded in a variable number of bytes
//! each. The Rust type [`char`] represents a '[Unicode scalar
//! value]', which is similar to, but not the same as, a '[Unicode
//! code point]'.
//!
//! * **Nul terminators and implicit string lengths** - Often, C
//! strings are nul-terminated, i.e., they have a `\0` character at the
//! end. The length of a string buffer is not stored, but has to be
//! calculated; to compute the length of a string, C code must
//! manually call a function like `strlen()` for `char`-based strings,
//! or `wcslen()` for `wchar_t`-based ones. Those functions return
//! the number of characters in the string excluding the nul
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
//! accessing a string's length is a O(1) operation (because the
//! length is stored); in C it is an O(length) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! * **Internal nul characters** - When C strings have a nul
//! terminator character, this usually means that they cannot have nul
//! characters in the middle — a nul character would essentially
//! truncate the string. Rust strings *can* have nul characters in
//! the middle, because nul does not have to mark the end of the
//! string in Rust.
//!
//! # Representations of non-Rust strings
//!
//! [`CString`] and [`CStr`] are useful when you need to transfer
//! UTF-8 strings to and from languages with a C ABI, like Python.
//!
//! * **From Rust to C:** [`CString`] represents an owned, C-friendly
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a [`CString`] out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
//! then use a variety of methods to obtain a raw `*mut `[`u8`] that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
//! is what you would use to wrap a raw `*const `[`u8`] that you got from
//! a C function. A [`CStr`] is guaranteed to be a nul-terminated array
//! of bytes. Once you have a [`CStr`], you can convert it to a Rust
//! [`&str`][`str`] if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! strings to and from the operating system itself, or when capturing
//! the output of external commands. Conversions between [`OsString`],
//! [`OsStr`] and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! system use [`OsString`] instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into an UTF-8 Rust string slice in a similar way to
//! [`OsString`].
//!
//! # Conversions
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an [`OsString`] which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
//! [`Option`]: ../option/enum.Option.html
//! [`Some`]: ../option/enum.Option.html#variant.Some

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

#[stable(feature = "raw_os", since = "1.1.0")]
pub use core::ffi::c_void;

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "27745")]
pub use core::ffi::VaList;

mod c_str;
mod os_str;
<|endoftext|>