<commit_before>use std::collections::HashMap;
use std::str::from_utf8_unchecked;
use std::cmp::min;
use std::process;

use term_painter::Color::*;
use term_painter::ToStyle;

use config;
use logger;
use request::{Request, Data, FormItems};
use response::Responder;
use router::{Router, Route};
use catcher::{self, Catcher};
use outcome::Outcome;
use error::Error;

use http::{Method, StatusCode};
use http::hyper::{HyperRequest, FreshHyperResponse};
use http::hyper::{HyperServer, HyperHandler, HyperSetCookie, header};

pub struct Rocket {
    address: String,
    port: usize,
    router: Router,
    default_catchers: HashMap<u16, Catcher>,
    catchers: HashMap<u16, Catcher>,
}

#[doc(hidden)]
impl HyperHandler for Rocket {
    fn handle<'h, 'k>(&self,
                      hyp_req: HyperRequest<'h, 'k>,
                      mut res: FreshHyperResponse<'h>) {
        // Get all of the information from Hyper.
        let (_, h_method, h_headers, h_uri, _, h_body) = hyp_req.deconstruct();

        // Get a copy of the URI for later use.
        let uri = h_uri.to_string();

        // Try to create a Rocket request from the hyper request info.
        let mut request = match Request::new(h_method, h_headers, h_uri) {
            Ok(req) => req,
            Err(ref reason) => {
                let mock = Request::mock(Method::Get, uri.as_str());
                error!("{}: bad request ({}).", mock, reason);
                self.handle_error(StatusCode::InternalServerError, &mock, res);
                return;
            }
        };

        // Retrieve the data from the hyper body.
        let data = match Data::from_hyp(h_body) {
            Ok(data) => data,
            Err(reason) => {
                error_!("Bad data in request: {}", reason);
                self.handle_error(StatusCode::InternalServerError, &request, res);
                return;
            }
        };

        // Set the common response headers and preprocess the request.
        res.headers_mut().set(header::Server("rocket".to_string()));
        self.preprocess_request(&mut request, &data);

        // Now that we've Rocket-ized everything, actually dispath the request.
        let mut responder = match self.dispatch(&request, data) {
            Ok(responder) => responder,
            Err(code) => {
                self.handle_error(code, &request, res);
                return;
            }
        };

        // We have a responder. Update the cookies in the header.
        let cookie_delta = request.cookies().delta();
        if cookie_delta.len() > 0 {
            res.headers_mut().set(HyperSetCookie(cookie_delta));
        }

        // Actually call the responder.
        let outcome = responder.respond(res);
        info_!("{} {}", White.paint("Outcome:"), outcome);

        // Check if the responder wants to forward to a catcher. If it doesn't,
        // it's a success or failure, so we can't do any more processing.
        if let Some((code, f_res)) = outcome.forwarded() {
            self.handle_error(code, &request, f_res);
        }
    }
}

impl Rocket {
    #[doc(hidden)]
    pub fn dispatch<'r>(&self, request: &'r Request, mut data: Data)
            -> Result<Box<Responder + 'r>, StatusCode> {
        // Go through the list of matching routes until we fail or succeed.
        info!("{}:", request);
        let matches = self.router.route(&request);
        for route in matches {
            // Retrieve and set the requests parameters.
            info_!("Matched: {}", route);
            request.set_params(route);

            // Dispatch the request to the handler.
            let response = (route.handler)(&request, data);

            // Check if the request processing completed or if the request needs
            // to be forwarded. If it does, continue the loop to try again.
            info_!("{} {}", White.paint("Response:"), response);
            match response {
                Outcome::Success(responder) => return Ok(responder),
                Outcome::Failure(status_code) => return Err(status_code),
                Outcome::Forward(unused_data) => data = unused_data,
            };
        }

        error_!("No matching routes.");
        Err(StatusCode::NotFound)
    }

    /// Preprocess the request for Rocket-specific things. At this time, we're
    /// only checking for _method in forms.
    fn preprocess_request(&self, req: &mut Request, data: &Data) {
        // Check if this is a form and if the form contains the special _method
        // field which we use to reinterpret the request's method.
        let data_len = data.peek().len();
        let (min_len, max_len) = ("_method=get".len(), "_method=delete".len());
        if req.content_type().is_form() && data_len >= min_len {
            let form = unsafe {
                from_utf8_unchecked(&data.peek()[..min(data_len, max_len)])
            };

            let mut form_items = FormItems(form);
            if let Some(("_method", value)) = form_items.next() {
                if let Ok(method) = value.parse() {
                    req.method = method;
                }
            }
        }
    }

    // Call when no route was found. Returns true if there was a response.
    #[doc(hidden)]
    pub fn handle_error<'r>(&self,
                        code: StatusCode,
                        req: &'r Request,
                        response: FreshHyperResponse) -> bool {
        // Find the catcher or use the one for internal server errors.
        let catcher = self.catchers.get(&code.to_u16()).unwrap_or_else(|| {
            error_!("No catcher found for {}.", code);
            warn_!("Using internal server error catcher.");
            self.catchers.get(&500).expect("500 Catcher")
        });

        if let Some(mut responder) = catcher.handle(Error::NoRoute, req).responder() {
            if !responder.respond(response).is_success() {
                error_!("Catcher outcome was unsuccessul; aborting response.");
                return false;
            } else {
                info_!("Responded with {} catcher.", White.paint(code));
            }
        } else {
            error_!("Catcher returned an incomplete response.");
            warn_!("Using default error response.");
            let catcher = self.default_catchers.get(&code.to_u16())
                .unwrap_or(self.default_catchers.get(&500).expect("500 default"));
            let responder = catcher.handle(Error::Internal, req).responder();
            responder.unwrap().respond(response).unwrap()
        }

        true
    }

    pub fn mount(mut self, base: &str, routes: Vec<Route>) -> Self {
        info!("🛰  {} '{}':", Magenta.paint("Mounting"), base);
        for mut route in routes {
            let path = format!("{}/{}", base, route.path.as_str());
            route.set_path(path);

            info_!("{}", route);
            self.router.add(route);
        }

        self
    }

    pub fn catch(mut self, catchers: Vec<Catcher>) -> Self {
        info!("👾  {}:", Magenta.paint("Catchers"));
        for c in catchers {
            if self.catchers.get(&c.code).map_or(false, |e| !e.is_default()) {
                let msg = "(warning: duplicate catcher!)";
                info_!("{} {}", c, Yellow.paint(msg));
            } else {
                info_!("{}", c);
            }

            self.catchers.insert(c.code, c);
        }

        self
    }

    pub fn launch(self) {
        if self.router.has_collisions() {
            warn!("Route collisions detected!");
        }

        let full_addr = format!("{}:{}", self.address, self.port);
        let server = match HyperServer::http(full_addr.as_str()) {
            Ok(hyper_server) => hyper_server,
            Err(e) => {
                error!("failed to start server.");
                error_!("{}", e);
                process::exit(1);
            }
        };

        info!("🚀  {} {}...",
              White.paint("Rocket has launched from"),
              White.bold().paint(&full_addr));

        server.handle(self).unwrap();
    }

    /// Retrieves the configuration parameter named `name` for the current
    /// environment. Returns Some(value) if the paremeter exists. Otherwise,
    /// returns None.
    pub fn config<S: AsRef<str>>(_name: S) -> Option<&'static str> {
        // TODO: Implement me.
        None
    }

    pub fn ignite() -> Rocket {
        // Note: init() will exit the process under config errors.
        let (config, initted) = config::init();
        if initted {
            logger::init(config.log_level);
        }

        info!("🔧  Configured for {}.", config.env);
        info_!("listening: {}:{}",
               White.paint(&config.address),
               White.paint(&config.port));
        info_!("logging: {:?}", White.paint(config.log_level));
        info_!("session key: {}", White.paint(config.take_session_key().is_some()));
        for (name, value) in config.extras() {
            info_!("{} {}: {}", Yellow.paint("[extra]"), name, White.paint(value));
        }

        Rocket {
            address: config.address.clone(),
            port: config.port,
            router: Router::new(),
            default_catchers: catcher::defaults::get(),
            catchers: catcher::defaults::get(),
        }
    }
}
<commit_msg>Remove unused Rocket::config method.<commit_after>use std::collections::HashMap;
use std::str::from_utf8_unchecked;
use std::cmp::min;
use std::process;

use term_painter::Color::*;
use term_painter::ToStyle;

use config;
use logger;
use request::{Request, Data, FormItems};
use response::Responder;
use router::{Router, Route};
use catcher::{self, Catcher};
use outcome::Outcome;
use error::Error;

use http::{Method, StatusCode};
use http::hyper::{HyperRequest, FreshHyperResponse};
use http::hyper::{HyperServer, HyperHandler, HyperSetCookie, header};

pub struct Rocket {
    address: String,
    port: usize,
    router: Router,
    default_catchers: HashMap<u16, Catcher>,
    catchers: HashMap<u16, Catcher>,
}

#[doc(hidden)]
impl HyperHandler for Rocket {
    fn handle<'h, 'k>(&self,
                      hyp_req: HyperRequest<'h, 'k>,
                      mut res: FreshHyperResponse<'h>) {
        // Get all of the information from Hyper.
        let (_, h_method, h_headers, h_uri, _, h_body) = hyp_req.deconstruct();

        // Get a copy of the URI for later use.
        let uri = h_uri.to_string();

        // Try to create a Rocket request from the hyper request info.
        let mut request = match Request::new(h_method, h_headers, h_uri) {
            Ok(req) => req,
            Err(ref reason) => {
                let mock = Request::mock(Method::Get, uri.as_str());
                error!("{}: bad request ({}).", mock, reason);
                self.handle_error(StatusCode::InternalServerError, &mock, res);
                return;
            }
        };

        // Retrieve the data from the hyper body.
        let data = match Data::from_hyp(h_body) {
            Ok(data) => data,
            Err(reason) => {
                error_!("Bad data in request: {}", reason);
                self.handle_error(StatusCode::InternalServerError, &request, res);
                return;
            }
        };

        // Set the common response headers and preprocess the request.
        res.headers_mut().set(header::Server("rocket".to_string()));
        self.preprocess_request(&mut request, &data);

        // Now that we've Rocket-ized everything, actually dispath the request.
        let mut responder = match self.dispatch(&request, data) {
            Ok(responder) => responder,
            Err(code) => {
                self.handle_error(code, &request, res);
                return;
            }
        };

        // We have a responder. Update the cookies in the header.
        let cookie_delta = request.cookies().delta();
        if cookie_delta.len() > 0 {
            res.headers_mut().set(HyperSetCookie(cookie_delta));
        }

        // Actually call the responder.
        let outcome = responder.respond(res);
        info_!("{} {}", White.paint("Outcome:"), outcome);

        // Check if the responder wants to forward to a catcher. If it doesn't,
        // it's a success or failure, so we can't do any more processing.
        if let Some((code, f_res)) = outcome.forwarded() {
            self.handle_error(code, &request, f_res);
        }
    }
}

impl Rocket {
    /// Preprocess the request for Rocket-specific things. At this time, we're
    /// only checking for _method in forms.
    fn preprocess_request(&self, req: &mut Request, data: &Data) {
        // Check if this is a form and if the form contains the special _method
        // field which we use to reinterpret the request's method.
        let data_len = data.peek().len();
        let (min_len, max_len) = ("_method=get".len(), "_method=delete".len());
        if req.content_type().is_form() && data_len >= min_len {
            let form = unsafe {
                from_utf8_unchecked(&data.peek()[..min(data_len, max_len)])
            };

            let mut form_items = FormItems(form);
            if let Some(("_method", value)) = form_items.next() {
                if let Ok(method) = value.parse() {
                    req.method = method;
                }
            }
        }
    }

    #[doc(hidden)]
    pub fn dispatch<'r>(&self, request: &'r Request, mut data: Data)
            -> Result<Box<Responder + 'r>, StatusCode> {
        // Go through the list of matching routes until we fail or succeed.
        info!("{}:", request);
        let matches = self.router.route(&request);
        for route in matches {
            // Retrieve and set the requests parameters.
            info_!("Matched: {}", route);
            request.set_params(route);

            // Dispatch the request to the handler.
            let response = (route.handler)(&request, data);

            // Check if the request processing completed or if the request needs
            // to be forwarded. If it does, continue the loop to try again.
            info_!("{} {}", White.paint("Response:"), response);
            match response {
                Outcome::Success(responder) => return Ok(responder),
                Outcome::Failure(status_code) => return Err(status_code),
                Outcome::Forward(unused_data) => data = unused_data,
            };
        }

        error_!("No matching routes.");
        Err(StatusCode::NotFound)
    }

    // Call when no route was found. Returns true if there was a response.
    #[doc(hidden)]
    pub fn handle_error<'r>(&self,
                        code: StatusCode,
                        req: &'r Request,
                        response: FreshHyperResponse) -> bool {
        // Find the catcher or use the one for internal server errors.
        let catcher = self.catchers.get(&code.to_u16()).unwrap_or_else(|| {
            error_!("No catcher found for {}.", code);
            warn_!("Using internal server error catcher.");
            self.catchers.get(&500).expect("500 Catcher")
        });

        if let Some(mut responder) = catcher.handle(Error::NoRoute, req).responder() {
            if !responder.respond(response).is_success() {
                error_!("Catcher outcome was unsuccessul; aborting response.");
                return false;
            } else {
                info_!("Responded with {} catcher.", White.paint(code));
            }
        } else {
            error_!("Catcher returned an incomplete response.");
            warn_!("Using default error response.");
            let catcher = self.default_catchers.get(&code.to_u16())
                .unwrap_or(self.default_catchers.get(&500).expect("500 default"));
            let responder = catcher.handle(Error::Internal, req).responder();
            responder.unwrap().respond(response).unwrap()
        }

        true
    }

    pub fn mount(mut self, base: &str, routes: Vec<Route>) -> Self {
        info!("🛰  {} '{}':", Magenta.paint("Mounting"), base);
        for mut route in routes {
            let path = format!("{}/{}", base, route.path.as_str());
            route.set_path(path);

            info_!("{}", route);
            self.router.add(route);
        }

        self
    }

    pub fn catch(mut self, catchers: Vec<Catcher>) -> Self {
        info!("👾  {}:", Magenta.paint("Catchers"));
        for c in catchers {
            if self.catchers.get(&c.code).map_or(false, |e| !e.is_default()) {
                let msg = "(warning: duplicate catcher!)";
                info_!("{} {}", c, Yellow.paint(msg));
            } else {
                info_!("{}", c);
            }

            self.catchers.insert(c.code, c);
        }

        self
    }

    pub fn launch(self) {
        if self.router.has_collisions() {
            warn!("Route collisions detected!");
        }

        let full_addr = format!("{}:{}", self.address, self.port);
        let server = match HyperServer::http(full_addr.as_str()) {
            Ok(hyper_server) => hyper_server,
            Err(e) => {
                error!("failed to start server.");
                error_!("{}", e);
                process::exit(1);
            }
        };

        info!("🚀  {} {}...",
              White.paint("Rocket has launched from"),
              White.bold().paint(&full_addr));

        server.handle(self).unwrap();
    }

    pub fn ignite() -> Rocket {
        // Note: init() will exit the process under config errors.
        let (config, initted) = config::init();
        if initted {
            logger::init(config.log_level);
        }

        info!("🔧  Configured for {}.", config.env);
        info_!("listening: {}:{}",
               White.paint(&config.address),
               White.paint(&config.port));
        info_!("logging: {:?}", White.paint(config.log_level));
        info_!("session key: {}", White.paint(config.take_session_key().is_some()));
        for (name, value) in config.extras() {
            info_!("{} {}: {}", Yellow.paint("[extra]"), name, White.paint(value));
        }

        Rocket {
            address: config.address.clone(),
            port: config.port,
            router: Router::new(),
            default_catchers: catcher::defaults::get(),
            catchers: catcher::defaults::get(),
        }
    }
}
<|endoftext|>


<commit_before>//! Enviroment data

use alloc::boxed::Box;

use core_collections::borrow::ToOwned;

use ffi::{OsString, OsStr};
use fs::{self, File};
use path::{Path, PathBuf};
use string::{String, ToString};
use sys_common::AsInner;
use vec::Vec;

use system::error::ENOENT;
use system::syscall::sys_chdir;

use io::{Error, Result, Read, Write};

static mut _args: *mut Vec<&'static str> = 0 as *mut Vec<&'static str>;

pub struct Args {
    i: usize
}

impl Iterator for Args {
    //Yes, this is supposed to be String, do not change it!
    //Only change it if https://doc.rust-lang.org/std/env/struct.Args.html changes from String
    type Item = String;
    fn next(&mut self) -> Option<String> {
        if let Some(arg) = unsafe { (*_args).get(self.i) } {
            self.i += 1;
            Some(arg.to_string())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = if self.i <= unsafe { (*_args).len() } {
            unsafe { (*_args).len() - self.i }
        } else {
            0
        };
        (len, Some(len))
    }
}

impl ExactSizeIterator for Args {}

/// Arguments
pub fn args() -> Args {
    Args {
        i: 0
    }
}

/// Initialize arguments
pub unsafe fn args_init(args: Vec<&'static str>) {
    _args = Box::into_raw(box args);
}

/// Destroy arguments
pub unsafe fn args_destroy() {
    if _args as usize > 0 {
        drop(Box::from_raw(_args));
    }
}

/// Private function to get the path from a custom location
/// If the custom directory cannot be found, None will be returned
fn get_path_from(location : &str) -> Result<PathBuf> {
    match File::open(location) {
        Ok(file) => {
            match file.path() {
                Ok(path) => Ok(path),
                Err(err) => Err(err),
            }
        }
        Err(err) => Err(err),
    }
}

/// Method to return the current directory
pub fn current_dir() -> Result<PathBuf> {
    // Return the current path
    get_path_from("./")
}

/// Method to return the home directory
pub fn home_dir() -> Option<PathBuf> {
    get_path_from("/home/").ok()
}

pub fn temp_dir() -> Option<PathBuf> {
    get_path_from("/tmp/").ok()
}

/// Set the current directory
pub fn set_current_dir<P: AsRef<Path>>(path: P) -> Result<()> {
    let path_str = path.as_ref().as_os_str().as_inner();
    let file_result = if path_str.is_empty() || path_str.ends_with('/') {
        File::open(path_str)
    } else {
        let mut path_string = path_str.to_owned();
        path_string.push_str("/");
        File::open(path_string)
    };

    match file_result {
        Ok(file) => {
            match file.path() {
                Ok(path) => {
                    if let Some(path_str) = path.to_str() {
                        let mut path_c = path_str.to_owned();
                        path_c.push_str("\0");
                        unsafe {
                            sys_chdir(path_c.as_ptr()).and(Ok(()))
                        }.map_err(|x| Error::from_sys(x))
                    } else {
                        Err(Error::new_sys(ENOENT))
                    }
                }
                Err(err) => Err(err),
            }
        }
        Err(err) => Err(err),
    }
}

pub enum VarError {
    NotPresent,
    NotUnicode(OsString),
}

/// Returns the environment variable `key` from the current process. If `key` is not valid Unicode
/// or if the variable is not present then `Err` is returned
pub fn var<K: AsRef<OsStr>>(key: K) -> ::core::result::Result<String, VarError> {
    if let Some(key_str) = key.as_ref().to_str() {
        let mut file = try!(File::open(&("env:".to_owned() + key_str)).or(Err(VarError::NotPresent)));
        let mut string = String::new();
        try!(file.read_to_string(&mut string).or(Err(VarError::NotPresent)));
        Ok(string)
    } else {
        Err(VarError::NotUnicode(key.as_ref().to_owned()))
    }
}

pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
    if let Ok(value) = var(key) {
        Some((value.as_ref() as &OsStr).to_owned())
    } else {
        None
    }
}

/// Sets the environment variable `key` to the value `value` for the current process
pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
    if let (Some(key_str), Some(value_str)) = (key.as_ref().to_str(), value.as_ref().to_str()) {
        if let Ok(mut file) = File::open(&("env:".to_owned() + key_str)) {
            let _ = file.write_all(value_str.as_bytes());
        }
    }
}

/// Removes an environment variable from the environment of the current process
pub fn remove_var<K: AsRef<OsStr>>(key: K) {
    if let Some(key_str) = key.as_ref().to_str() {
        let _ = fs::remove_file(&("env:".to_owned() + key_str));
    }
}

pub struct Vars {
    vars: Vec<(String, String)>,
    pos: usize
}

impl Iterator for Vars {
    type Item = (String, String);

    fn next(&mut self) -> Option<Self::Item> {
        let variable = self.vars.get(self.pos);
        self.pos += 1;
        variable.cloned()
    }
}

/// Returns an iterator over the environment variables of the current process
pub fn vars() -> Vars {
    let mut variables: Vec<(String, String)> = Vec::new();
    if let Ok(mut file) = File::open("env:") {
        let mut string = String::new();
        if file.read_to_string(&mut string).is_ok() {
            for line in string.lines() {
                if let Some(equal_sign) = line.chars().position(|c| c == '=') {
                    let name = line.chars().take(equal_sign).collect::<String>();
                    let value = line.chars().skip(equal_sign+1).collect::<String>();
                    variables.push((name, value));
                }
            }
            return Vars { vars: variables, pos: 0 };
        }
    }
    Vars { vars: Vec::new(), pos: 0 }
}
<commit_msg>Add some documentation to std::env<commit_after>//! Enviroment data

use alloc::boxed::Box;

use core_collections::borrow::ToOwned;

use ffi::{OsString, OsStr};
use fs::{self, File};
use path::{Path, PathBuf};
use string::{String, ToString};
use sys_common::AsInner;
use vec::Vec;
use error;
use fmt;

use system::error::ENOENT;
use system::syscall::sys_chdir;

use io::{Error, Result, Read, Write};

static mut _args: *mut Vec<&'static str> = 0 as *mut Vec<&'static str>;

/// An iterator over the arguments of a process, yielding a `String` value for each argument.
pub struct Args {
    i: usize
}

impl Iterator for Args {
    //Yes, this is supposed to be String, do not change it!
    //Only change it if https://doc.rust-lang.org/std/env/struct.Args.html changes from String
    type Item = String;
    fn next(&mut self) -> Option<String> {
        if let Some(arg) = unsafe { (*_args).get(self.i) } {
            self.i += 1;
            Some(arg.to_string())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = if self.i <= unsafe { (*_args).len() } {
            unsafe { (*_args).len() - self.i }
        } else {
            0
        };
        (len, Some(len))
    }
}

impl ExactSizeIterator for Args {}

/// Arguments
pub fn args() -> Args {
    Args {
        i: 0
    }
}

/// Initialize arguments
pub unsafe fn args_init(args: Vec<&'static str>) {
    _args = Box::into_raw(box args);
}

/// Destroy arguments
pub unsafe fn args_destroy() {
    if _args as usize > 0 {
        drop(Box::from_raw(_args));
    }
}

/// Private function to get the path from a custom location
/// If the custom directory cannot be found, None will be returned
fn get_path_from(location : &str) -> Result<PathBuf> {
    match File::open(location) {
        Ok(file) => {
            match file.path() {
                Ok(path) => Ok(path),
                Err(err) => Err(err),
            }
        }
        Err(err) => Err(err),
    }
}

/// Method to return the current directory
pub fn current_dir() -> Result<PathBuf> {
    // Return the current path
    get_path_from("./")
}

/// Method to return the home directory
pub fn home_dir() -> Option<PathBuf> {
    get_path_from("/home/").ok()
}

pub fn temp_dir() -> Option<PathBuf> {
    get_path_from("/tmp/").ok()
}

/// Set the current directory
pub fn set_current_dir<P: AsRef<Path>>(path: P) -> Result<()> {
    let path_str = path.as_ref().as_os_str().as_inner();
    let file_result = if path_str.is_empty() || path_str.ends_with('/') {
        File::open(path_str)
    } else {
        let mut path_string = path_str.to_owned();
        path_string.push_str("/");
        File::open(path_string)
    };

    match file_result {
        Ok(file) => {
            match file.path() {
                Ok(path) => {
                    if let Some(path_str) = path.to_str() {
                        let mut path_c = path_str.to_owned();
                        path_c.push_str("\0");
                        unsafe {
                            sys_chdir(path_c.as_ptr()).and(Ok(()))
                        }.map_err(|x| Error::from_sys(x))
                    } else {
                        Err(Error::new_sys(ENOENT))
                    }
                }
                Err(err) => Err(err),
            }
        }
        Err(err) => Err(err),
    }
}

/// Possible errors from the `env::var` method.
#[derive(Debug)]
pub enum VarError {
    /// The specified environment variable was not set.
    NotPresent,
    /// The key or the value of the specified environment variable did not contain valid Unicode
    /// data.
    NotUnicode(OsString),
}

impl fmt::Display for VarError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            VarError::NotPresent => write!(f, "environment variable not found"),
            VarError::NotUnicode(ref s) => write!(f, "environment variable was not valid unicode: {:?}", s)
        }
    }
}

impl error::Error for VarError {
    fn description(&self) -> &str {
        match *self {
            VarError::NotPresent => "environment variable not found",
            VarError::NotUnicode(_) => "environment variable was not valid unicode"
        }
    }
}

/// Returns the environment variable `key` from the current process. If `key` is not valid Unicode
/// or if the variable is not present then `Err` is returned
pub fn var<K: AsRef<OsStr>>(key: K) -> ::core::result::Result<String, VarError> {
    if let Some(key_str) = key.as_ref().to_str() {
        let mut file = try!(File::open(&("env:".to_owned() + key_str)).or(Err(VarError::NotPresent)));
        let mut string = String::new();
        try!(file.read_to_string(&mut string).or(Err(VarError::NotPresent)));
        Ok(string)
    } else {
        Err(VarError::NotUnicode(key.as_ref().to_owned()))
    }
}

/// Fetches the environment variable `key` from the current process, returning `None` if the
/// variable isn't set.
pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
    if let Ok(value) = var(key) {
        Some((value.as_ref() as &OsStr).to_owned())
    } else {
        None
    }
}

/// Sets the environment variable `key` to the value `value` for the current process
pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
    if let (Some(key_str), Some(value_str)) = (key.as_ref().to_str(), value.as_ref().to_str()) {
        if let Ok(mut file) = File::open(&("env:".to_owned() + key_str)) {
            let _ = file.write_all(value_str.as_bytes());
        }
    }
}

/// Removes an environment variable from the environment of the current process
pub fn remove_var<K: AsRef<OsStr>>(key: K) {
    if let Some(key_str) = key.as_ref().to_str() {
        let _ = fs::remove_file(&("env:".to_owned() + key_str));
    }
}

/// An iterator over the snapshot of the environment variables of this process.
/// This iterator is created through `std::env::vars() and yields (String, String) pairs.`
pub struct Vars {
    vars: Vec<(String, String)>,
    pos: usize
}

impl Iterator for Vars {
    type Item = (String, String);

    fn next(&mut self) -> Option<Self::Item> {
        let variable = self.vars.get(self.pos);
        self.pos += 1;
        variable.cloned()
    }
}

/// Returns an iterator over the environment variables of the current process
pub fn vars() -> Vars {
    let mut variables: Vec<(String, String)> = Vec::new();
    if let Ok(mut file) = File::open("env:") {
        let mut string = String::new();
        if file.read_to_string(&mut string).is_ok() {
            for line in string.lines() {
                if let Some(equal_sign) = line.chars().position(|c| c == '=') {
                    let name = line.chars().take(equal_sign).collect::<String>();
                    let value = line.chars().skip(equal_sign+1).collect::<String>();
                    variables.push((name, value));
                }
            }
            return Vars { vars: variables, pos: 0 };
        }
    }
    Vars { vars: Vec::new(), pos: 0 }
}
<|endoftext|>


<commit_before>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use std::sync::Arc;

use futures::channel::mpsc;
use futures::executor::block_on;
use futures::join;
use futures::prelude::*;
use futures::sink::SinkExt;
use futures_timer::Delay;
use grpcio::{
    ChannelBuilder, ClientStreamingSink, DuplexSink, EnvBuilder, RequestStream, RpcContext,
    ServerBuilder, ServerStreamingSink, UnarySink, WriteFlags,
};
use grpcio_proto::example::route_guide::*;

const MESSAGE_NUM: i32 = 2000;

#[derive(Clone)]
struct RouteGuideService {}

impl RouteGuide for RouteGuideService {
    fn get_feature(&mut self, _: RpcContext<'_>, _: Point, _: UnarySink<Feature>) {
        unimplemented!()
    }
    fn list_features(&mut self, _: RpcContext<'_>, _: Rectangle, _: ServerStreamingSink<Feature>) {
        unimplemented!()
    }
    fn record_route(
        &mut self,
        ctx: RpcContext<'_>,
        mut points: RequestStream<Point>,
        resp: ClientStreamingSink<RouteSummary>,
    ) {
        let f = async move {
            let mut summary = RouteSummary::default();
            let mut current_num = 0;
            while let Some(point) = points.try_next().await? {
                assert_eq!(
                    point.get_longitude(),
                    current_num,
                    "messages sequence is wrong"
                );
                current_num += 1;
                summary.point_count += 1;
                // Send a reply message after receiving a limited number of messages, which
                // can be used to test the correctness under different buffer strategies.
                if current_num >= MESSAGE_NUM {
                    break;
                }
            }
            // Sleep a while to avoid the possibility that the client will receive
            // remotestopped error.
            std::thread::sleep(std::time::Duration::from_millis(100));
            resp.success(summary).await?;
            Ok(())
        }
        .map_err(|e: grpcio::Error| panic!("server got error: {:?}", e))
        .map(|_| ());
        ctx.spawn(f)
    }

    fn route_chat(
        &mut self,
        _: RpcContext<'_>,
        _: RequestStream<RouteNote>,
        _: DuplexSink<RouteNote>,
    ) {
        unimplemented!()
    }
}

#[test]
fn test_client_send_all() {
    let env = Arc::new(EnvBuilder::new().build());
    let service = create_route_guide(RouteGuideService {});
    let mut server = ServerBuilder::new(env.clone())
        .register_service(service)
        .bind("127.0.0.1", 0)
        .build()
        .unwrap();
    server.start();
    let port = server.bind_addrs().next().unwrap().1;
    let ch = ChannelBuilder::new(env).connect(&format!("127.0.0.1:{}", port));
    let client = RouteGuideClient::new(ch);

    let exec_test_f = async move {
        // Test for send all disable batch
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        sink.send_all(&mut send_stream.map(move |item| Ok((item, WriteFlags::default()))))
            .await
            .unwrap();
        let summary = receiver.await.unwrap();
        assert_eq!(summary.get_point_count(), MESSAGE_NUM);

        // Test for send all enable batch
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        sink.enhance_batch(true);
        sink.send_all(&mut send_stream.map(move |item| Ok((item, WriteFlags::default()))))
            .await
            .unwrap();
        let summary = receiver.await.unwrap();
        assert_eq!(summary.get_point_count(), MESSAGE_NUM);

        // Test for send all and all buffer hints are true
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        sink.enhance_batch(false);
        sink.send_all(
            &mut send_stream.map(move |item| Ok((item, WriteFlags::default().buffer_hint(true)))),
        )
        .await
        .unwrap();
        // The following code is to test that when all msgs are set to be buffered, the msgs
        // should be stored in the buffer until `sink.close()` is called.
        let (mut tx, mut rx) = mpsc::channel(1);
        let close_sink_task = async move {
            Delay::new(std::time::Duration::from_secs(1)).await;
            rx.try_next().unwrap_err();
            sink.close().await.unwrap();
            Delay::new(std::time::Duration::from_secs(1)).await;
            rx.try_next().unwrap();
        };
        let recv_msg_task = async move {
            let summary = receiver.await.unwrap();
            tx.send(()).await.unwrap();
            assert_eq!(summary.get_point_count(), MESSAGE_NUM);
        };
        join!(recv_msg_task, close_sink_task);
    };
    block_on(exec_test_f);
}
<commit_msg>tests: fix flaky client_send_all case (#547)<commit_after>// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.

use std::sync::Arc;

use futures::channel::mpsc;
use futures::executor::block_on;
use futures::join;
use futures::prelude::*;
use futures::sink::SinkExt;
use futures_timer::Delay;
use grpcio::{
    ChannelBuilder, ClientStreamingSink, DuplexSink, EnvBuilder, RequestStream, RpcContext,
    ServerBuilder, ServerStreamingSink, UnarySink, WriteFlags,
};
use grpcio_proto::example::route_guide::*;

const MESSAGE_NUM: i32 = 2000;

#[derive(Clone)]
struct RouteGuideService {}

impl RouteGuide for RouteGuideService {
    fn get_feature(&mut self, _: RpcContext<'_>, _: Point, _: UnarySink<Feature>) {
        unimplemented!()
    }
    fn list_features(&mut self, _: RpcContext<'_>, _: Rectangle, _: ServerStreamingSink<Feature>) {
        unimplemented!()
    }
    fn record_route(
        &mut self,
        ctx: RpcContext<'_>,
        mut points: RequestStream<Point>,
        resp: ClientStreamingSink<RouteSummary>,
    ) {
        let f = async move {
            let mut summary = RouteSummary::default();
            let mut current_num = 0;
            while let Some(point) = points.try_next().await? {
                assert_eq!(
                    point.get_longitude(),
                    current_num,
                    "messages sequence is wrong"
                );
                current_num += 1;
                summary.point_count += 1;
                // Send a reply message after receiving a limited number of messages, which
                // can be used to test the correctness under different buffer strategies.
                if current_num >= MESSAGE_NUM {
                    break;
                }
            }
            resp.success(summary).await?;
            Ok(())
        }
        .map_err(|e: grpcio::Error| panic!("server got error: {:?}", e))
        .map(|_| ());
        ctx.spawn(f)
    }

    fn route_chat(
        &mut self,
        _: RpcContext<'_>,
        _: RequestStream<RouteNote>,
        _: DuplexSink<RouteNote>,
    ) {
        unimplemented!()
    }
}

macro_rules! assert_finish {
    ($res:expr) => {
        match $res {
            // RouteGuide returns early, so `RpcFinished` is possible returned.
            Ok(()) | Err(grpcio::Error::RpcFinished(None)) => (),
            Err(e) => panic!("unexpected error {:?}", e),
        }
    };
}

#[test]
fn test_client_send_all() {
    let env = Arc::new(EnvBuilder::new().build());
    let service = create_route_guide(RouteGuideService {});
    let mut server = ServerBuilder::new(env.clone())
        .register_service(service)
        .bind("127.0.0.1", 0)
        .build()
        .unwrap();
    server.start();
    let port = server.bind_addrs().next().unwrap().1;
    let ch = ChannelBuilder::new(env).connect(&format!("127.0.0.1:{}", port));
    let client = RouteGuideClient::new(ch);

    let exec_test_f = async move {
        // Test for send all disable batch
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        assert_finish!(
            sink.send_all(&mut send_stream.map(move |item| Ok((item, WriteFlags::default()))))
                .await
        );
        let summary = receiver.await.unwrap();
        assert_eq!(summary.get_point_count(), MESSAGE_NUM);

        // Test for send all enable batch
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        sink.enhance_batch(true);
        assert_finish!(
            sink.send_all(&mut send_stream.map(move |item| Ok((item, WriteFlags::default()))))
                .await
        );
        let summary = receiver.await.unwrap();
        assert_eq!(summary.get_point_count(), MESSAGE_NUM);

        // Test for send all and all buffer hints are true
        let (mut sink, receiver) = client.record_route().unwrap();
        let mut send_data = vec![];
        for i in 0..MESSAGE_NUM {
            let mut p = Point::default();
            p.set_longitude(i);
            send_data.push(p);
        }
        let send_stream = futures::stream::iter(send_data);
        sink.enhance_batch(false);
        sink.send_all(
            &mut send_stream.map(move |item| Ok((item, WriteFlags::default().buffer_hint(true)))),
        )
        .await
        .unwrap();
        // The following code is to test that when all msgs are set to be buffered, the msgs
        // should be stored in the buffer until `sink.close()` is called.
        let (mut tx, mut rx) = mpsc::channel(1);
        let close_sink_task = async move {
            Delay::new(std::time::Duration::from_secs(1)).await;
            rx.try_next().unwrap_err();
            sink.close().await.unwrap();
            Delay::new(std::time::Duration::from_secs(1)).await;
            rx.try_next().unwrap();
        };
        let recv_msg_task = async move {
            let summary = receiver.await.unwrap();
            tx.send(()).await.unwrap();
            assert_eq!(summary.get_point_count(), MESSAGE_NUM);
        };
        join!(recv_msg_task, close_sink_task);
    };
    block_on(exec_test_f);
}
<|endoftext|>


<commit_before>use crate::utils::span_lint;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use std::f64::consts as f64;
use syntax::ast::{FloatTy, Lit, LitKind};
use syntax::symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for floating point literals that approximate
    /// constants which are defined in
    /// [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants)
    /// or
    /// [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants),
    /// respectively, suggesting to use the predefined constant.
    ///
    /// **Why is this bad?** Usually, the definition in the standard library is more
    /// precise than what people come up with. If you find that your definition is
    /// actually more precise, please [file a Rust
    /// issue](https://github.com/rust-lang/rust/issues).
    ///
    /// **Known problems:** If you happen to have a value that is within 1/8192 of a
    /// known constant, but is not *and should not* be the same, this lint will
    /// report your value anyway. We have not yet noticed any false positives in
    /// code we tested clippy with (this includes servo), but YMMV.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 3.14;
    /// ```
    pub APPROX_CONSTANT,
    correctness,
    "the approximate of a known float constant (in `std::fXX::consts`)"
}

// Tuples are of the form (constant, name, min_digits)
const KNOWN_CONSTS: &[(f64, &str, usize)] = &[
    (f64::E, "E", 4),
    (f64::FRAC_1_PI, "FRAC_1_PI", 4),
    (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),
    (f64::FRAC_2_PI, "FRAC_2_PI", 5),
    (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5),
    (f64::FRAC_PI_2, "FRAC_PI_2", 5),
    (f64::FRAC_PI_3, "FRAC_PI_3", 5),
    (f64::FRAC_PI_4, "FRAC_PI_4", 5),
    (f64::FRAC_PI_6, "FRAC_PI_6", 5),
    (f64::FRAC_PI_8, "FRAC_PI_8", 5),
    (f64::LN_10, "LN_10", 5),
    (f64::LN_2, "LN_2", 5),
    (f64::LOG10_E, "LOG10_E", 5),
    (f64::LOG2_E, "LOG2_E", 5),
    (f64::PI, "PI", 3),
    (f64::SQRT_2, "SQRT_2", 5),
];

declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ApproxConstant {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprKind::Lit(lit) = &e.node {
            check_lit(cx, lit, e);
        }
    }
}

fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) {
    match lit.node {
        LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"),
        LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"),
        LitKind::FloatUnsuffixed(s) => check_known_consts(cx, e, s, "f{32, 64}"),
        _ => (),
    }
}

fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) {
    let s = s.as_str();
    if s.parse::<f64>().is_ok() {
        for &(constant, name, min_digits) in KNOWN_CONSTS {
            if is_approx_const(constant, &s, min_digits) {
                span_lint(
                    cx,
                    APPROX_CONSTANT,
                    e.span,
                    &format!(
                        "approximate value of `{}::consts::{}` found. \
                         Consider using it directly",
                        module, &name
                    ),
                );
                return;
            }
        }
    }
}

/// Returns `false` if the number of significant figures in `value` are
/// less than `min_digits`; otherwise, returns true if `value` is equal
/// to `constant`, rounded to the number of digits present in `value`.
fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
    if value.len() <= min_digits {
        false
    } else {
        let round_const = format!("{:.*}", value.len() - 2, constant);

        let mut trunc_const = constant.to_string();
        if trunc_const.len() > value.len() {
            trunc_const.truncate(value.len());
        }

        (value == round_const) || (value == trunc_const)
    }
}
<commit_msg>Auto merge of #4027 - kraai:remove-approx_constant-known-problems, r=phansch<commit_after>use crate::utils::span_lint;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use std::f64::consts as f64;
use syntax::ast::{FloatTy, Lit, LitKind};
use syntax::symbol;

declare_clippy_lint! {
    /// **What it does:** Checks for floating point literals that approximate
    /// constants which are defined in
    /// [`std::f32::consts`](https://doc.rust-lang.org/stable/std/f32/consts/#constants)
    /// or
    /// [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants),
    /// respectively, suggesting to use the predefined constant.
    ///
    /// **Why is this bad?** Usually, the definition in the standard library is more
    /// precise than what people come up with. If you find that your definition is
    /// actually more precise, please [file a Rust
    /// issue](https://github.com/rust-lang/rust/issues).
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// let x = 3.14;
    /// ```
    pub APPROX_CONSTANT,
    correctness,
    "the approximate of a known float constant (in `std::fXX::consts`)"
}

// Tuples are of the form (constant, name, min_digits)
const KNOWN_CONSTS: &[(f64, &str, usize)] = &[
    (f64::E, "E", 4),
    (f64::FRAC_1_PI, "FRAC_1_PI", 4),
    (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),
    (f64::FRAC_2_PI, "FRAC_2_PI", 5),
    (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5),
    (f64::FRAC_PI_2, "FRAC_PI_2", 5),
    (f64::FRAC_PI_3, "FRAC_PI_3", 5),
    (f64::FRAC_PI_4, "FRAC_PI_4", 5),
    (f64::FRAC_PI_6, "FRAC_PI_6", 5),
    (f64::FRAC_PI_8, "FRAC_PI_8", 5),
    (f64::LN_10, "LN_10", 5),
    (f64::LN_2, "LN_2", 5),
    (f64::LOG10_E, "LOG10_E", 5),
    (f64::LOG2_E, "LOG2_E", 5),
    (f64::PI, "PI", 3),
    (f64::SQRT_2, "SQRT_2", 5),
];

declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ApproxConstant {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprKind::Lit(lit) = &e.node {
            check_lit(cx, lit, e);
        }
    }
}

fn check_lit(cx: &LateContext<'_, '_>, lit: &Lit, e: &Expr) {
    match lit.node {
        LitKind::Float(s, FloatTy::F32) => check_known_consts(cx, e, s, "f32"),
        LitKind::Float(s, FloatTy::F64) => check_known_consts(cx, e, s, "f64"),
        LitKind::FloatUnsuffixed(s) => check_known_consts(cx, e, s, "f{32, 64}"),
        _ => (),
    }
}

fn check_known_consts(cx: &LateContext<'_, '_>, e: &Expr, s: symbol::Symbol, module: &str) {
    let s = s.as_str();
    if s.parse::<f64>().is_ok() {
        for &(constant, name, min_digits) in KNOWN_CONSTS {
            if is_approx_const(constant, &s, min_digits) {
                span_lint(
                    cx,
                    APPROX_CONSTANT,
                    e.span,
                    &format!(
                        "approximate value of `{}::consts::{}` found. \
                         Consider using it directly",
                        module, &name
                    ),
                );
                return;
            }
        }
    }
}

/// Returns `false` if the number of significant figures in `value` are
/// less than `min_digits`; otherwise, returns true if `value` is equal
/// to `constant`, rounded to the number of digits present in `value`.
fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
    if value.len() <= min_digits {
        false
    } else {
        let round_const = format!("{:.*}", value.len() - 2, constant);

        let mut trunc_const = constant.to_string();
        if trunc_const.len() > value.len() {
            trunc_const.truncate(value.len());
        }

        (value == round_const) || (value == trunc_const)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Brendan Zabarauskas and the gl-rs 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.

// This build script is used to discover all of the accepted extensions
// described in the Khronos WebGL repository, and construct a static slice
// containing the XML specifications for all of them.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::*;

fn main() {
    // Create and open a file in the output directory to contain our generated rust code
    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("webgl_exts.rs")).unwrap();

    // Find the absolute path to the folder containing the WebGL extensions.
    // The absolute path is needed, because we don't know where the output
    // directory will be, and `include_bytes!(..)` resolves paths relative to the
    // containing file.
    let root = env::current_dir().unwrap().join("api_webgl/extensions");

    // Generate a slice literal, looking like this:
    // `&[&*include_bytes!(..), &*include_bytes!(..), ..]`
    writeln!(file, "&[").unwrap();

    // The slice will have one entry for each WebGL extension. To find the
    // extensions we mirror the behaviour of the `api_webgl/extensions/find-exts`
    // shell script.
    for entry in root.read_dir().unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        let ext_name = path.file_name().unwrap().to_str().unwrap();

        // Each item which is a directory, and is not named `template`, may be
        // an extension.
        if path.is_dir() && ext_name != "template" {
            // If the directory contains a file named `extension.xml`, then this
            // really is an extension.
            let ext_path = path.join("extension.xml");
            if ext_path.is_file() {
                // Include the XML file, making sure to use an absolute path.
                writeln!(file, "&*include_bytes!({:?}),", ext_path.to_str().unwrap()).unwrap();
            }
        }
    }

    // Close the slice
    writeln!(file, "]").unwrap();
}
<commit_msg>Ensure webgl_exts.rs is always ordered the same way<commit_after>// Copyright 2015 Brendan Zabarauskas and the gl-rs 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.

// This build script is used to discover all of the accepted extensions
// described in the Khronos WebGL repository, and construct a static slice
// containing the XML specifications for all of them.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::*;

fn main() {
    // Create and open a file in the output directory to contain our generated rust code
    let dest = env::var("OUT_DIR").unwrap();
    let mut file = File::create(&Path::new(&dest).join("webgl_exts.rs")).unwrap();

    // Find the absolute path to the folder containing the WebGL extensions.
    // The absolute path is needed, because we don't know where the output
    // directory will be, and `include_bytes!(..)` resolves paths relative to the
    // containing file.
    let root = env::current_dir().unwrap().join("api_webgl/extensions");

    // Generate a slice literal, looking like this:
    // `&[&*include_bytes!(..), &*include_bytes!(..), ..]`
    writeln!(file, "&[").unwrap();

    // The slice will have one entry for each WebGL extension. To find the
    // extensions we mirror the behaviour of the `api_webgl/extensions/find-exts`
    // shell script.
    let mut paths: Vec<_> = root.read_dir().unwrap().map(|e| e.unwrap().path()).collect();
    // Sort the list of paths in order for the webgl_exts.rs file to be created
    // deterministically.
    paths.sort();
    for path in paths {
        let ext_name = path.file_name().unwrap().to_str().unwrap();

        // Each item which is a directory, and is not named `template`, may be
        // an extension.
        if path.is_dir() && ext_name != "template" {
            // If the directory contains a file named `extension.xml`, then this
            // really is an extension.
            let ext_path = path.join("extension.xml");
            if ext_path.is_file() {
                // Include the XML file, making sure to use an absolute path.
                writeln!(file, "&*include_bytes!({:?}),", ext_path.to_str().unwrap()).unwrap();
            }
        }
    }

    // Close the slice
    writeln!(file, "]").unwrap();
}
<|endoftext|>


<commit_before>// Copyright 2015 Brendan Zabarauskas and the gl-rs 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.

extern crate gl_generator;
extern crate khronos_api;

use gl_generator::*;
use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::*;
use std::io::BufWriter;

fn main() {
    let dest = env::var("OUT_DIR").unwrap();

    let mut file = BufWriter::new(File::create(&Path::new(&dest).join("bindings.rs")).unwrap());
    gl_generator::generate_bindings(GlobalGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();

    // writing tests files
    // FIXME (https://github.com/rust-lang/cargo/issues/1058): only build the tests file if
    //                                                         we run "cargo test"
    //if os::getenv("PROFILE").unwrap() == "test" {
        write_test_gen_symbols(&Path::new(&dest));
        write_test_no_warnings(&Path::new(&dest));
    //}
}

fn write_test_gen_symbols(dest: &Path) {
    let mut file = BufWriter::new(File::create(&dest.join("test_gen_symbols.rs")).unwrap());

    (writeln!(&mut file, "mod gl {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod glx {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod wgl {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod egl {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();
}

fn write_test_no_warnings(dest: &Path) {
    let mut file = BufWriter::new(File::create(&dest.join("test_no_warnings.rs")).unwrap());

    // Gl

    (writeln!(&mut file, "mod gl_global {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gl_static {{")).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gl_struct {{")).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gl_static_struct {{")).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gl_debug_struct {{")).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Gl, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "4.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    // Glx

    (writeln!(&mut file, "mod glx_global {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod glx_static {{")).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod glx_struct {{")).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod glx_static_struct {{")).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod glx_debug_struct {{")).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Glx, Fallbacks::All,
                                    khronos_api::GLX_XML, vec![], "1.4", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    // Wgl

    (writeln!(&mut file, "mod wgl_global {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod wgl_static {{")).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod wgl_struct {{")).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod wgl_static_struct {{")).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod wgl_debug_struct {{")).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Wgl, Fallbacks::All,
                                    khronos_api::WGL_XML, vec![], "1.0", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    // Gles1

    (writeln!(&mut file, "mod gles1_global {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Gles1, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "1.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles1_static {{")).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Gles1, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "1.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles1_struct {{")).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Gles1, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "1.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles1_static_struct {{")).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Gles1, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "1.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles1_debug_struct {{")).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Gles1, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "1.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    // Gles2

    (writeln!(&mut file, "mod gles2_global {{")).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles2_static {{")).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles2_struct {{")).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles2_static_struct {{")).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod gles2_debug_struct {{")).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Gles2, Fallbacks::All,
                                    khronos_api::GL_XML, vec![], "3.1", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    // Egl

    (writeln!(&mut file, "mod egl_global {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(GlobalGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod egl_static {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(StaticGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod egl_struct {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(StructGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod egl_static_struct {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(StaticStructGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();

    (writeln!(&mut file, "mod egl_debug_struct {{ {}", build_egl_symbols())).unwrap();
    gl_generator::generate_bindings(DebugStructGenerator, Api::Egl, Fallbacks::All,
                                    khronos_api::EGL_XML, vec![], "1.5", "core",
                                    &mut file).unwrap();
    (writeln!(&mut file, "}}")).unwrap();
}

fn build_egl_symbols() -> &'static str {
    "
        #![allow(non_camel_case_types)]

        use std::os::raw;

        pub type khronos_utime_nanoseconds_t = raw::c_int;
        pub type khronos_uint64_t = u64;
        pub type khronos_ssize_t = isize;
        pub type EGLNativeDisplayType = *const raw::c_void;
        pub type EGLNativePixmapType = *const raw::c_void;
        pub type EGLNativeWindowType = *const raw::c_void;
        pub type EGLint = raw::c_int;
        pub type NativeDisplayType = *const raw::c_void;
        pub type NativePixmapType = *const raw::c_void;
        pub type NativeWindowType = *const raw::c_void;
    "
}
<commit_msg>Remove stray build.rs file<commit_after><|endoftext|>


<commit_before>/**
 * http://static.rust-lang.org/doc/master/collections/hashmap/struct.HashMap.html
 * https://github.com/mozilla/rust/blob/master/src/test/run-pass/hashmap-memory.rs#L70
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
extern crate collections;
use collections::hashmap::HashMap;

fn main() {
	println!("Using borrowed pointers as keys.");
	let mut h: HashMap<&str, int>;
	h = HashMap::new();
	h.insert("foo", 42);
	println!("Is there a key foo?  => {}", h.contains_key(&("foo"))); // => true
	println!("Is there a key baz?  => {}", h.contains_key(&("baz"))); // => false
	println!("The value for foo is => {:?}", h.find(&("foo"))); // => Some(&42)
	let key = "baz";
	h.insert(key, 1);
	println!("Is there a key baz?  => {}", h.contains_key(&("baz"))); // => false

	// You don't actually need the HashMap to own the keys (but
	// unless all keys are static, this will be likely to lead
	// to problems, so I don't suggest you do it in reality)

	println!("Using owned pointers as keys.");
	let mut h: HashMap<~str, int> = HashMap::new();
	h.insert("foo".to_owned(), 42);
	println!("Is there a key foo?  => {}", h.contains_key(&"foo".to_owned())); // => true
	println!("Is there a key baz?  => {}", h.contains_key(&"baz".to_owned())); // => false
	println!("The value for foo is => {:?}", h.find(&"foo".to_owned())); // => Some(&42)
	h.insert(key.to_owned(), 1);
	println!("Is there a key baz?  => {}", h.contains_key(&"baz".to_owned())); // => true

	// List keys of the HashMap
	let mut keys: Vec<~str> = Vec::new();
	for (k, _) in h.iter() {
		keys.push(k.to_owned());
	}
	println!("These are the keys: {}.", keys);
}
<commit_msg>Add some code<commit_after>/**
 * http://static.rust-lang.org/doc/master/collections/hashmap/struct.HashMap.html
 * https://github.com/mozilla/rust/blob/master/src/test/run-pass/hashmap-memory.rs#L70
 * https://github.com/mozilla/rust/blob/master/src/libcollections/hashmap.rs
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
extern crate collections;
use collections::hashmap::HashMap;

fn main() {
	println!("Using borrowed pointers as keys.");
	let mut h: HashMap<&str, int>;
	h = HashMap::new();
	h.insert("foo", 42);
	println!("Is there a key foo?  => {}", h.contains_key(&("foo"))); // => true
	println!("Is there a key baz?  => {}", h.contains_key(&("baz"))); // => false
	println!("The value for foo is => {:?}", h.find(&("foo"))); // => Some(&42)
	let key = "baz";
	h.insert(key, 1);
	println!("Is there a key baz?  => {}", h.contains_key(&("baz"))); // => false

	// Doing a find, inserting with a `proc()`, using the key to construct the value
	let mut map = HashMap::<~str, ~str>::new();
	map.find_or_insert_with("foo".to_owned(), |k| *k + "bar".to_owned());
	println!("The value for foo is => {:?}", map.find(&("foo".to_owned()))); // => Some(&~"foobar")
	// running this for the first time, will add "foo" with the value 1
	// running the same for the second time, will add +1 to "foo"
	h.insert_or_update_with("foo", 1, |_k, v| *v += 1);
	println!("foo={}", h.get(&("foo")));
	assert_eq!(*h.get(&("foo")), 43);

	// You don't actually need the HashMap to own the keys (but
	// unless all keys are static, this will be likely to lead
	// to problems, so I don't suggest you do it in reality)

	println!("Using owned pointers as keys.");
	let mut h: HashMap<~str, int> = HashMap::new();
	h.insert("foo".to_owned(), 42);
	println!("Is there a key foo?  => {}", h.contains_key(&"foo".to_owned())); // => true
	println!("Is there a key baz?  => {}", h.contains_key(&"baz".to_owned())); // => false
	println!("The value for foo is => {:?}", h.find(&"foo".to_owned())); // => Some(&42)
	h.insert(key.to_owned(), 1);
	println!("Is there a key baz?  => {}", h.contains_key(&"baz".to_owned())); // => true

	// List keys of the HashMap
	let mut keys: Vec<~str> = Vec::new();
	for (k, _) in h.iter() {
		keys.push(k.to_owned());
	}
	println!("These are the keys: {}.", keys);
	let keys = h.keys().map(|v| v.clone()).collect::<Vec<~str>>();
	println!("These are the keys: {}.", keys);

	// List values of the HashMap
	let values = h.values().map(|v| v.clone()).collect::<Vec<int>>();
	println!("These are the values: {}.", values);
}
<|endoftext|>