<commit_before>//! Contains the binary logic of Ion.
mod designators;
mod prompt;
mod readln;
mod terminate;

use self::{
    prompt::{prompt, prompt_fn}, readln::readln,
    terminate::{terminate_quotes, terminate_script_quotes},
};
use super::{flow_control::Statement, status::*, FlowLogic, Shell, ShellHistory};
use liner::{Buffer, Context};
use std::{env, fs::File, io::ErrorKind, iter, path::Path, process};

pub const MAN_ION: &'static str = r#"NAME
    ion - ion shell

SYNOPSIS
    ion [ -h | --help ] [-c] [-n] [-v]

DESCRIPTION
    ion is a commandline shell created to be a faster and easier to use alternative to the
    currently available shells. It is not POSIX compliant.

OPTIONS
    -c
        evaulates given commands instead of reading from the commandline.

    -n or --no-execute
        do not execute any commands, just do syntax checking.

    -v or --version
        prints the version, platform and revision of ion then exits.
"#;

pub trait Binary {
    /// Parses and executes the arguments that were supplied to the shell.
    fn execute_arguments<A: Iterator<Item = String>>(&mut self, args: A);
    /// Creates an interactive session that reads from a prompt provided by
    /// Liner.
    fn execute_interactive(self);
    /// Ensures that read statements from a script are terminated.
    fn terminate_script_quotes<I: Iterator<Item = String>>(&mut self, lines: I) -> i32;
    /// Ensures that read statements from the interactive prompt is terminated.
    fn terminate_quotes(&mut self, command: String) -> Result<String, ()>;
    /// Ion's interface to Liner's `read_line` method, which handles everything related to
    /// rendering, controlling, and getting input from the prompt.
    fn readln(&mut self) -> Option<String>;
    /// Generates the prompt that will be used by Liner.
    fn prompt(&mut self) -> String;
    /// Display version information and exit
    fn display_version(&self);
    // Executes the PROMPT function, if it exists, and returns the output.
    fn prompt_fn(&mut self) -> Option<String>;
    // Handles commands given by the REPL, and saves them to history.
    fn save_command(&mut self, command: &str);
    // Resets the flow control fields to their default values.
    fn reset_flow(&mut self);
}

impl Binary for Shell {
    fn display_version(&self) {
        println!("{}", include!(concat!(env!("OUT_DIR"), "/version_string")));
        process::exit(0);
    }

    fn save_command(&mut self, cmd: &str) {
        if cmd.starts_with('~') {
            if !cmd.ends_with('/')
                && self
                    .variables
                    .tilde_expansion(cmd, &self.directory_stack)
                    .map_or(false, |path| Path::new(&path).is_dir())
            {
                self.save_command_in_history(&[cmd, "/"].concat());
            } else {
                self.save_command_in_history(cmd);
            }
            return;
        }

        if Path::new(cmd).is_dir() & !cmd.ends_with('/') {
            self.save_command_in_history(&[cmd, "/"].concat());
        } else {
            self.save_command_in_history(cmd);
        }
    }

    fn reset_flow(&mut self) {
        self.flow_control.level = 0;
        self.flow_control.current_if_mode = 0;
        self.flow_control.current_statement = Statement::Default;
    }

    fn execute_interactive(mut self) {
        self.context = Some({
            let mut context = Context::new();
            context.word_divider_fn = Box::new(word_divide);
            if "1" == self.get_var_or_empty("HISTFILE_ENABLED") {
                let path = self.get_var("HISTFILE").expect("shell didn't set HISTFILE");
                context.history.set_file_name(Some(path.clone()));
                if !Path::new(path.as_str()).exists() {
                    eprintln!("ion: creating history file at \"{}\"", path);
                    if let Err(why) = File::create(path) {
                        eprintln!("ion: could not create history file: {}", why);
                    }
                }
                match context.history.load_history() {
                    Ok(()) => {
                        // pass
                    }
                    Err(ref err) if err.kind() == ErrorKind::NotFound => {
                        let history_filename = self.get_var_or_empty("HISTFILE");
                        eprintln!(
                            "ion: failed to find history file {}: {}",
                            history_filename, err
                        );
                    }
                    Err(err) => {
                        eprintln!("ion: failed to load history: {}", err);
                    }
                }
            }
            context
        });

        self.evaluate_init_file();

        self.variables
            .set_array("args", iter::once(env::args().next().unwrap()).collect());

        loop {
            if let Some(command) = self.readln() {
                if !command.is_empty() {
                    if let Ok(command) = self.terminate_quotes(command.replace("\\\n", "")) {
                        let cmd: &str = &designators::expand_designators(&self, command.trim());
                        self.on_command(&cmd);
                        self.save_command(&cmd);
                    } else {
                        self.reset_flow();
                    }
                }
            } else {
                self.reset_flow();
            }
        }
    }

    fn execute_arguments<A: Iterator<Item = String>>(&mut self, mut args: A) {
        if let Some(mut arg) = args.next() {
            for argument in args {
                arg.push(' ');
                if argument == "" {
                    arg.push_str("''");
                } else {
                    arg.push_str(&argument);
                }
            }
            self.on_command(&arg);
        } else {
            eprintln!("ion: -c requires an argument");
            self.exit(FAILURE);
        }

        if self.flow_control.level != 0 {
            eprintln!(
                "ion: unexpected end of arguments: expected end block for `{}`",
                self.flow_control.current_statement.short()
            );
            self.exit(FAILURE);
        }
    }

    fn terminate_quotes(&mut self, command: String) -> Result<String, ()> {
        terminate_quotes(self, command)
    }

    fn terminate_script_quotes<I: Iterator<Item = String>>(&mut self, lines: I) -> i32 {
        terminate_script_quotes(self, lines)
    }

    fn readln(&mut self) -> Option<String> { readln(self) }

    fn prompt_fn(&mut self) -> Option<String> { prompt_fn(self) }

    fn prompt(&mut self) -> String { prompt(self) }
}

struct WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    iter:       I,
    count:      usize,
    word_start: Option<usize>,
}
impl<I> WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    #[inline]
    fn check_boundary(&mut self, c: char, index: usize, escaped: bool) -> Option<(usize, usize)> {
        if let Some(start) = self.word_start {
            if c == ' ' && !escaped {
                self.word_start = None;
                Some((start, index))
            } else {
                self.next()
            }
        } else {
            if c != ' ' {
                self.word_start = Some(index);
            }
            self.next()
        }
    }
}
impl<I> Iterator for WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    type Item = (usize, usize);

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        match self.iter.next() {
            Some((i, '\\')) => {
                if let Some((_, cnext)) = self.iter.next() {
                    // We use `i` in order to include the backslash as part of the word
                    self.check_boundary(cnext, i, true)
                } else {
                    self.next()
                }
            }
            Some((i, c)) => self.check_boundary(c, i, false),
            None => {
                // When start has been set, that means we have encountered a full word.
                self.word_start.take().map(|start| (start, self.count - 1))
            }
        }
    }
}

fn word_divide<'a>(buf: &'a Buffer) -> Vec<(usize, usize)> {
    // -> impl Iterator<Item = (usize, usize)> + 'a
    WordDivide {
        iter:       buf.chars().cloned().enumerate(),
        count:      0,
        word_start: None,
    }.collect() // TODO: return iterator directly :D
}
<commit_msg>Fix typo in --help output<commit_after>//! Contains the binary logic of Ion.
mod designators;
mod prompt;
mod readln;
mod terminate;

use self::{
    prompt::{prompt, prompt_fn}, readln::readln,
    terminate::{terminate_quotes, terminate_script_quotes},
};
use super::{flow_control::Statement, status::*, FlowLogic, Shell, ShellHistory};
use liner::{Buffer, Context};
use std::{env, fs::File, io::ErrorKind, iter, path::Path, process};

pub const MAN_ION: &'static str = r#"NAME
    ion - ion shell

SYNOPSIS
    ion [ -h | --help ] [-c] [-n] [-v]

DESCRIPTION
    ion is a commandline shell created to be a faster and easier to use alternative to the
    currently available shells. It is not POSIX compliant.

OPTIONS
    -c
        evaluates given commands instead of reading from the commandline.

    -n or --no-execute
        do not execute any commands, just do syntax checking.

    -v or --version
        prints the version, platform and revision of ion then exits.
"#;

pub trait Binary {
    /// Parses and executes the arguments that were supplied to the shell.
    fn execute_arguments<A: Iterator<Item = String>>(&mut self, args: A);
    /// Creates an interactive session that reads from a prompt provided by
    /// Liner.
    fn execute_interactive(self);
    /// Ensures that read statements from a script are terminated.
    fn terminate_script_quotes<I: Iterator<Item = String>>(&mut self, lines: I) -> i32;
    /// Ensures that read statements from the interactive prompt is terminated.
    fn terminate_quotes(&mut self, command: String) -> Result<String, ()>;
    /// Ion's interface to Liner's `read_line` method, which handles everything related to
    /// rendering, controlling, and getting input from the prompt.
    fn readln(&mut self) -> Option<String>;
    /// Generates the prompt that will be used by Liner.
    fn prompt(&mut self) -> String;
    /// Display version information and exit
    fn display_version(&self);
    // Executes the PROMPT function, if it exists, and returns the output.
    fn prompt_fn(&mut self) -> Option<String>;
    // Handles commands given by the REPL, and saves them to history.
    fn save_command(&mut self, command: &str);
    // Resets the flow control fields to their default values.
    fn reset_flow(&mut self);
}

impl Binary for Shell {
    fn display_version(&self) {
        println!("{}", include!(concat!(env!("OUT_DIR"), "/version_string")));
        process::exit(0);
    }

    fn save_command(&mut self, cmd: &str) {
        if cmd.starts_with('~') {
            if !cmd.ends_with('/')
                && self
                    .variables
                    .tilde_expansion(cmd, &self.directory_stack)
                    .map_or(false, |path| Path::new(&path).is_dir())
            {
                self.save_command_in_history(&[cmd, "/"].concat());
            } else {
                self.save_command_in_history(cmd);
            }
            return;
        }

        if Path::new(cmd).is_dir() & !cmd.ends_with('/') {
            self.save_command_in_history(&[cmd, "/"].concat());
        } else {
            self.save_command_in_history(cmd);
        }
    }

    fn reset_flow(&mut self) {
        self.flow_control.level = 0;
        self.flow_control.current_if_mode = 0;
        self.flow_control.current_statement = Statement::Default;
    }

    fn execute_interactive(mut self) {
        self.context = Some({
            let mut context = Context::new();
            context.word_divider_fn = Box::new(word_divide);
            if "1" == self.get_var_or_empty("HISTFILE_ENABLED") {
                let path = self.get_var("HISTFILE").expect("shell didn't set HISTFILE");
                context.history.set_file_name(Some(path.clone()));
                if !Path::new(path.as_str()).exists() {
                    eprintln!("ion: creating history file at \"{}\"", path);
                    if let Err(why) = File::create(path) {
                        eprintln!("ion: could not create history file: {}", why);
                    }
                }
                match context.history.load_history() {
                    Ok(()) => {
                        // pass
                    }
                    Err(ref err) if err.kind() == ErrorKind::NotFound => {
                        let history_filename = self.get_var_or_empty("HISTFILE");
                        eprintln!(
                            "ion: failed to find history file {}: {}",
                            history_filename, err
                        );
                    }
                    Err(err) => {
                        eprintln!("ion: failed to load history: {}", err);
                    }
                }
            }
            context
        });

        self.evaluate_init_file();

        self.variables
            .set_array("args", iter::once(env::args().next().unwrap()).collect());

        loop {
            if let Some(command) = self.readln() {
                if !command.is_empty() {
                    if let Ok(command) = self.terminate_quotes(command.replace("\\\n", "")) {
                        let cmd: &str = &designators::expand_designators(&self, command.trim());
                        self.on_command(&cmd);
                        self.save_command(&cmd);
                    } else {
                        self.reset_flow();
                    }
                }
            } else {
                self.reset_flow();
            }
        }
    }

    fn execute_arguments<A: Iterator<Item = String>>(&mut self, mut args: A) {
        if let Some(mut arg) = args.next() {
            for argument in args {
                arg.push(' ');
                if argument == "" {
                    arg.push_str("''");
                } else {
                    arg.push_str(&argument);
                }
            }
            self.on_command(&arg);
        } else {
            eprintln!("ion: -c requires an argument");
            self.exit(FAILURE);
        }

        if self.flow_control.level != 0 {
            eprintln!(
                "ion: unexpected end of arguments: expected end block for `{}`",
                self.flow_control.current_statement.short()
            );
            self.exit(FAILURE);
        }
    }

    fn terminate_quotes(&mut self, command: String) -> Result<String, ()> {
        terminate_quotes(self, command)
    }

    fn terminate_script_quotes<I: Iterator<Item = String>>(&mut self, lines: I) -> i32 {
        terminate_script_quotes(self, lines)
    }

    fn readln(&mut self) -> Option<String> { readln(self) }

    fn prompt_fn(&mut self) -> Option<String> { prompt_fn(self) }

    fn prompt(&mut self) -> String { prompt(self) }
}

struct WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    iter:       I,
    count:      usize,
    word_start: Option<usize>,
}
impl<I> WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    #[inline]
    fn check_boundary(&mut self, c: char, index: usize, escaped: bool) -> Option<(usize, usize)> {
        if let Some(start) = self.word_start {
            if c == ' ' && !escaped {
                self.word_start = None;
                Some((start, index))
            } else {
                self.next()
            }
        } else {
            if c != ' ' {
                self.word_start = Some(index);
            }
            self.next()
        }
    }
}
impl<I> Iterator for WordDivide<I>
where
    I: Iterator<Item = (usize, char)>,
{
    type Item = (usize, usize);

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        match self.iter.next() {
            Some((i, '\\')) => {
                if let Some((_, cnext)) = self.iter.next() {
                    // We use `i` in order to include the backslash as part of the word
                    self.check_boundary(cnext, i, true)
                } else {
                    self.next()
                }
            }
            Some((i, c)) => self.check_boundary(c, i, false),
            None => {
                // When start has been set, that means we have encountered a full word.
                self.word_start.take().map(|start| (start, self.count - 1))
            }
        }
    }
}

fn word_divide<'a>(buf: &'a Buffer) -> Vec<(usize, usize)> {
    // -> impl Iterator<Item = (usize, usize)> + 'a
    WordDivide {
        iter:       buf.chars().cloned().enumerate(),
        count:      0,
        word_start: None,
    }.collect() // TODO: return iterator directly :D
}
<|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.

/*!
 * This module contains the code to convert from the wacky tcx data
 * structures into the hair. The `builder` is generally ignorant of
 * the tcx etc, and instead goes through the `Cx` for most of its
 * work.
 */

use hair::*;
use repr::*;
use std::fmt::{Debug, Formatter, Error};
use std::hash::{Hash, Hasher};

use rustc::middle::const_eval::ConstVal;
use rustc::middle::def_id::DefId;
use rustc::middle::infer::InferCtxt;
use rustc::middle::subst::{Subst, Substs};
use rustc::middle::ty::{self, Ty};
use syntax::codemap::Span;
use syntax::parse::token::{self, special_idents};

#[derive(Copy, Clone)]
pub struct Cx<'a,'tcx:'a> {
    tcx: &'a ty::ctxt<'tcx>,
    infcx: &'a InferCtxt<'a,'tcx>,
}

impl<'a,'tcx> Cx<'a,'tcx> {
    pub fn new(infcx: &'a InferCtxt<'a,'tcx>) -> Cx<'a,'tcx> {
        Cx { tcx: infcx.tcx, infcx: infcx }
    }
}

pub use self::pattern::PatNode;

impl<'a,'tcx:'a> Cx<'a, 'tcx> {
    /// Normalizes `ast` into the appropriate `mirror` type.
    pub fn mirror<M:Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
        ast.make_mirror(self)
    }

    pub fn unit_ty(&mut self) -> Ty<'tcx> {
        self.tcx.mk_nil()
    }

    pub fn usize_ty(&mut self) -> Ty<'tcx> {
        self.tcx.types.usize
    }

    pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Uint(value as u64) }
    }

    pub fn bool_ty(&mut self) -> Ty<'tcx> {
        self.tcx.types.bool
    }

    pub fn true_literal(&mut self) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Bool(true) }
    }

    pub fn false_literal(&mut self) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Bool(false) }
    }

    pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
        let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
        self.cmp_method_ref(eq_def_id, "eq", ty)
    }

    pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
        let ord_def_id = self.tcx.lang_items.ord_trait().unwrap();
        self.cmp_method_ref(ord_def_id, "le", ty)
    }

    pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
        adt_def.variants.len()
    }

    pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> {
        adt_def.variants[variant_index]
            .fields
            .iter()
            .enumerate()
            .map(|(index, field)| {
                if field.name == special_idents::unnamed_field.name {
                    Field::Indexed(index)
                } else {
                    Field::Named(field.name)
                }
            })
            .collect()
    }

    pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool {
        if self.infcx.type_moves_by_default(ty, span) {
            // FIXME(#21859) we should do an add'l check here to determine if
            // any dtor will execute, but the relevant fn
            // (`type_needs_drop`) is currently factored into
            // `librustc_trans`, so we can't easily do so.
            true
        } else {
            // if type implements Copy, cannot require drop
            false
        }
    }

    pub fn span_bug(&mut self, span: Span, message: &str) -> ! {
        self.tcx.sess.span_bug(span, message)
    }

    pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
        self.tcx
    }

    fn cmp_method_ref(&mut self,
                      trait_def_id: DefId,
                      method_name: &str,
                      arg_ty: Ty<'tcx>)
                      -> ItemRef<'tcx> {
        let method_name = token::intern(method_name);
        let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
        for trait_item in self.tcx.trait_items(trait_def_id).iter() {
            match *trait_item {
                ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
                    if method.name == method_name {
                        let method_ty = self.tcx.lookup_item_type(method.def_id);
                        let method_ty = method_ty.ty.subst(self.tcx, &substs);
                        return ItemRef {
                            ty: method_ty,
                            def_id: method.def_id,
                            substs: self.tcx.mk_substs(substs),
                        };
                    }
                }
                ty::ImplOrTraitItem::ConstTraitItem(..) |
                ty::ImplOrTraitItem::TypeTraitItem(..) => {
                }
            }
        }

        self.tcx.sess.bug(
            &format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
    }
}

// We only need this impl so that we do deriving for things that are
// defined relative to the `Hair` trait. See `Hair` trait for more
// details.
impl<'a,'tcx> PartialEq for Cx<'a,'tcx> {
    fn eq(&self, _: &Cx<'a,'tcx>) -> bool {
        panic!("Cx should never ACTUALLY be compared for equality")
    }
}

impl<'a,'tcx> Eq for Cx<'a,'tcx> { }

impl<'a,'tcx> Hash for Cx<'a,'tcx> {
    fn hash<H: Hasher>(&self, _: &mut H) {
        panic!("Cx should never ACTUALLY be hashed")
    }
}

impl<'a,'tcx> Debug for Cx<'a,'tcx> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        write!(fmt, "Tcx")
    }
}

mod block;
mod expr;
mod pattern;
mod to_ref;

<commit_msg>remove now unnecessary trait impls<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.

/*!
 * This module contains the code to convert from the wacky tcx data
 * structures into the hair. The `builder` is generally ignorant of
 * the tcx etc, and instead goes through the `Cx` for most of its
 * work.
 */

use hair::*;
use repr::*;

use rustc::middle::const_eval::ConstVal;
use rustc::middle::def_id::DefId;
use rustc::middle::infer::InferCtxt;
use rustc::middle::subst::{Subst, Substs};
use rustc::middle::ty::{self, Ty};
use syntax::codemap::Span;
use syntax::parse::token::{self, special_idents};

#[derive(Copy, Clone)]
pub struct Cx<'a,'tcx:'a> {
    tcx: &'a ty::ctxt<'tcx>,
    infcx: &'a InferCtxt<'a,'tcx>,
}

impl<'a,'tcx> Cx<'a,'tcx> {
    pub fn new(infcx: &'a InferCtxt<'a,'tcx>) -> Cx<'a,'tcx> {
        Cx { tcx: infcx.tcx, infcx: infcx }
    }
}

pub use self::pattern::PatNode;

impl<'a,'tcx:'a> Cx<'a, 'tcx> {
    /// Normalizes `ast` into the appropriate `mirror` type.
    pub fn mirror<M:Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
        ast.make_mirror(self)
    }

    pub fn unit_ty(&mut self) -> Ty<'tcx> {
        self.tcx.mk_nil()
    }

    pub fn usize_ty(&mut self) -> Ty<'tcx> {
        self.tcx.types.usize
    }

    pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Uint(value as u64) }
    }

    pub fn bool_ty(&mut self) -> Ty<'tcx> {
        self.tcx.types.bool
    }

    pub fn true_literal(&mut self) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Bool(true) }
    }

    pub fn false_literal(&mut self) -> Literal<'tcx> {
        Literal::Value { value: ConstVal::Bool(false) }
    }

    pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
        let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
        self.cmp_method_ref(eq_def_id, "eq", ty)
    }

    pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
        let ord_def_id = self.tcx.lang_items.ord_trait().unwrap();
        self.cmp_method_ref(ord_def_id, "le", ty)
    }

    pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
        adt_def.variants.len()
    }

    pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> {
        adt_def.variants[variant_index]
            .fields
            .iter()
            .enumerate()
            .map(|(index, field)| {
                if field.name == special_idents::unnamed_field.name {
                    Field::Indexed(index)
                } else {
                    Field::Named(field.name)
                }
            })
            .collect()
    }

    pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool {
        if self.infcx.type_moves_by_default(ty, span) {
            // FIXME(#21859) we should do an add'l check here to determine if
            // any dtor will execute, but the relevant fn
            // (`type_needs_drop`) is currently factored into
            // `librustc_trans`, so we can't easily do so.
            true
        } else {
            // if type implements Copy, cannot require drop
            false
        }
    }

    pub fn span_bug(&mut self, span: Span, message: &str) -> ! {
        self.tcx.sess.span_bug(span, message)
    }

    pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
        self.tcx
    }

    fn cmp_method_ref(&mut self,
                      trait_def_id: DefId,
                      method_name: &str,
                      arg_ty: Ty<'tcx>)
                      -> ItemRef<'tcx> {
        let method_name = token::intern(method_name);
        let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
        for trait_item in self.tcx.trait_items(trait_def_id).iter() {
            match *trait_item {
                ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
                    if method.name == method_name {
                        let method_ty = self.tcx.lookup_item_type(method.def_id);
                        let method_ty = method_ty.ty.subst(self.tcx, &substs);
                        return ItemRef {
                            ty: method_ty,
                            def_id: method.def_id,
                            substs: self.tcx.mk_substs(substs),
                        };
                    }
                }
                ty::ImplOrTraitItem::ConstTraitItem(..) |
                ty::ImplOrTraitItem::TypeTraitItem(..) => {
                }
            }
        }

        self.tcx.sess.bug(
            &format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
    }
}

mod block;
mod expr;
mod pattern;
mod to_ref;

<|endoftext|>


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

pub use self::imp::OsRng;

use mem;

fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
    let mut buf: [u8; 4] = [0; 4];
    fill_buf(&mut buf);
    unsafe { mem::transmute::<[u8; 4], u32>(buf) }
}

fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
    let mut buf: [u8; 8] = [0; 8];
    fill_buf(&mut buf);
    unsafe { mem::transmute::<[u8; 8], u64>(buf) }
}

#[cfg(all(unix,
          not(target_os = "ios"),
          not(target_os = "openbsd"),
          not(target_os = "freebsd"),
          not(target_os = "fuchsia")))]
mod imp {
    use self::OsRngInner::*;
    use super::{next_u32, next_u64};

    use fs::File;
    use io;
    use libc;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64",
                  target_arch = "s390x")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "s390x")]
        const NR_GETRANDOM: libc::c_long = 349;
        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
        const NR_GETRANDOM: libc::c_long = 359;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        const GRND_NONBLOCK: libc::c_uint = 0x0001;

        unsafe {
            libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64",
                      target_arch = "s390x"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::EAGAIN {
                    // if getrandom() returns EAGAIN it would have blocked
                    // because the non-blocking pool (urandom) has not
                    // initialized in the kernel yet due to a lack of entropy
                    // the fallback we do here is to avoid blocking applications
                    // which could depend on this call without ever knowing
                    // they do and don't have a work around. The PRNG of
                    // /dev/urandom will still be used but not over a completely
                    // full entropy pool
                    let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
                    let mut reader_rng = ReaderRng::new(reader);
                    reader_rng.fill_bytes(&mut v[read..]);
                    read += v.len();
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64",
                  target_arch = "s390x")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64",
                      target_arch = "s390x"))))]
    fn is_getrandom_available() -> bool { false }

    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = File::open("/dev/urandom")?;
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => next_u32(&mut getrandom_fill_bytes),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => next_u64(&mut getrandom_fill_bytes),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use libc;
    use sys::os::errno;
    use rand::Rng;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    extern {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len(),
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(target_os = "freebsd")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use libc;
    use rand::Rng;
    use ptr;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mib = [libc::CTL_KERN, libc::KERN_ARND];
            // kern.arandom permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let mut s_len = s.len();
                let ret = unsafe {
                    libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
                                 s.as_mut_ptr() as *mut _, &mut s_len,
                                 ptr::null(), 0)
                };
                if ret == -1 || s_len != s.len() {
                    panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
                           ret, s.len(), s_len);
                }
            }
        }
    }
}

#[cfg(target_os = "fuchsia")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use rand::Rng;

    #[link(name = "zircon")]
    extern {
        fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
    }

    fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
        unsafe {
            let mut actual = 0;
            let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
            if status == 0 {
                Ok(actual)
            } else {
                Err(status)
            }
        }
    }

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mut buf = v;
            while !buf.is_empty() {
                let ret = getrandom(buf);
                match ret {
                    Err(err) => {
                        panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
                            err, buf.len())
                    }
                    Ok(actual) => {
                        let move_buf = buf;
                        buf = &mut move_buf[(actual as usize)..];
                    }
                }
            }
        }
    }
}
<commit_msg>Fix NR_GETRANDOM for linux x32<commit_after>// Copyright 2013-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.

pub use self::imp::OsRng;

use mem;

fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
    let mut buf: [u8; 4] = [0; 4];
    fill_buf(&mut buf);
    unsafe { mem::transmute::<[u8; 4], u32>(buf) }
}

fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
    let mut buf: [u8; 8] = [0; 8];
    fill_buf(&mut buf);
    unsafe { mem::transmute::<[u8; 8], u64>(buf) }
}

#[cfg(all(unix,
          not(target_os = "ios"),
          not(target_os = "openbsd"),
          not(target_os = "freebsd"),
          not(target_os = "fuchsia")))]
mod imp {
    use self::OsRngInner::*;
    use super::{next_u32, next_u64};

    use fs::File;
    use io;
    use libc;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64",
                  target_arch = "s390x")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
        const NR_GETRANDOM: libc::c_long = 0x40000000 + 318;
        #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "s390x")]
        const NR_GETRANDOM: libc::c_long = 349;
        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
        const NR_GETRANDOM: libc::c_long = 359;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        const GRND_NONBLOCK: libc::c_uint = 0x0001;

        unsafe {
            libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64",
                      target_arch = "s390x"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else if err == libc::EAGAIN {
                    // if getrandom() returns EAGAIN it would have blocked
                    // because the non-blocking pool (urandom) has not
                    // initialized in the kernel yet due to a lack of entropy
                    // the fallback we do here is to avoid blocking applications
                    // which could depend on this call without ever knowing
                    // they do and don't have a work around. The PRNG of
                    // /dev/urandom will still be used but not over a completely
                    // full entropy pool
                    let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom");
                    let mut reader_rng = ReaderRng::new(reader);
                    reader_rng.fill_bytes(&mut v[read..]);
                    read += v.len();
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc",
                  target_arch = "powerpc64",
                  target_arch = "s390x")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc",
                      target_arch = "powerpc64",
                      target_arch = "s390x"))))]
    fn is_getrandom_available() -> bool { false }

    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = File::open("/dev/urandom")?;
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => next_u32(&mut getrandom_fill_bytes),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => next_u64(&mut getrandom_fill_bytes),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use libc;
    use sys::os::errno;
    use rand::Rng;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let ret = unsafe {
                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
                };
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    extern {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len(),
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(target_os = "freebsd")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use libc;
    use rand::Rng;
    use ptr;

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mib = [libc::CTL_KERN, libc::KERN_ARND];
            // kern.arandom permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                let mut s_len = s.len();
                let ret = unsafe {
                    libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint,
                                 s.as_mut_ptr() as *mut _, &mut s_len,
                                 ptr::null(), 0)
                };
                if ret == -1 || s_len != s.len() {
                    panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
                           ret, s.len(), s_len);
                }
            }
        }
    }
}

#[cfg(target_os = "fuchsia")]
mod imp {
    use super::{next_u32, next_u64};

    use io;
    use rand::Rng;

    #[link(name = "zircon")]
    extern {
        fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
    }

    fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
        unsafe {
            let mut actual = 0;
            let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
            if status == 0 {
                Ok(actual)
            } else {
                Err(status)
            }
        }
    }

    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            next_u32(&mut |v| self.fill_bytes(v))
        }
        fn next_u64(&mut self) -> u64 {
            next_u64(&mut |v| self.fill_bytes(v))
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mut buf = v;
            while !buf.is_empty() {
                let ret = getrandom(buf);
                match ret {
                    Err(err) => {
                        panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
                            err, buf.len())
                    }
                    Ok(actual) => {
                        let move_buf = buf;
                        buf = &mut move_buf[(actual as usize)..];
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use issue::Issue;

#[derive(Deserialize)]
pub struct SearchResponse {
    pub expand: String,
    #[serde(rename = "startAt")]
    pub start_at: i64,
    #[serde(rename = "maxResult")]
    pub max_result: i64,
    pub issues: Vec<Issue>,
}<commit_msg>:art: Fix property names<commit_after>use issue::Issue;

#[derive(Deserialize)]
pub struct SearchResponse {
    #[serde(rename = "startAt")]
    pub start_at: i64,
    #[serde(rename = "maxResult")]
    pub max_results: i64,
    pub total: i64,
    pub issues: Vec<Issue>,
}<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file(f: File) -> BackendOperationResult {
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file(f: File) -> BackendOperationResult {
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id(id: FileID) -> Option<File> {
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<commit_msg>Implement Storage::put_file()<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;
use storage::parser::{FileHeaderParser, Parser, ParserError};

use module::Module;
use runtime::Runtime;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    pub fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn build<M: Module>(rt: &Runtime, m: &M) -> StorageBackend {
        let path = rt.get_rtp() + m.name() + "/store";
        StorageBackend::new(path)
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file<'a, HP>(&self, f: File, p: &Parser<HP>) ->
        Result<BackendOperationResult, ParserError>
        where HP: FileHeaderParser<'a>
    {
        let written = p.write(f.contents());
        if let Ok(string) = written {
            let path = self.basepath + &f.id()[..];
            debug!("Writing file: {}", path);
            Ok(Ok(()))
        } else {
            Err(written.err().unwrap())
        }
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file(f: File) -> BackendOperationResult {
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id(id: FileID) -> Option<File> {
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<|endoftext|>


<commit_before>extern crate hyper;

use std::io::Read;
use self::hyper::Client;
use self::hyper::header::Connection;

use std;
use std::collections::HashMap;
use std::io::{Error, ErrorKind};
use std::cell::Cell;
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};

pub struct WebResource {
     pub pages: HashMap<String, String>,
     client: Client
}

impl WebResource {

    pub fn new() -> Self {
        WebResource {
            pages: HashMap::new(),
            client: Client::new(),
        }
    }

    // let fetch_page = move |url: &str| -> String {
    //     download_map.entry(String::from(url))
    //                 .or_insert_with(move || {
    //                     match download_page(&client, &String::from(url)) {
    //                         Ok(s) => s,
    //                         Err(e) => format!("{:?}", e),
    //                     }
    //                 })
    //                 .clone()
    // };
    //

    pub fn fetch(&mut self, url: &String) -> Result<String, Error> {
        match self.client.get(url).send() {
            Ok(mut resp) => {
                let mut s = String::new();
                match resp.read_to_string(&mut s) {
                    Ok(size) => Ok(s),
                    Err(e) => Err(e),
                }
            }
            Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
        }
    }

    pub fn fetch_safe(&mut self, url: &str) -> String {
        match self.fetch(&String::from(url)) {
            Ok(s) => s,
            Err(e) => format!("{:?}", e),
        }
    }

    pub fn find(&mut self, url: &str) -> String {
        match self.pages.get(url) {
            Some(page) => page.clone(),
            None => { String::from("None") }
        }
    }

    pub fn get(&mut self, url: &str) -> String {
        if !self.pages.contains_key(url) {
            let res = self.fetch_safe(url);
            self.pages.insert(String::from(url), res);
        }
        self.find(url)
    }
}
<commit_msg>[FIX] receive invalid document from show request<commit_after>extern crate hyper;

use std::io::Read;
use self::hyper::Client;
use self::hyper::header::Connection;

use std;
use std::collections::HashMap;
use std::io::{Error, ErrorKind};
use std::cell::Cell;
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};

use self::hyper::header::{Headers, UserAgent};

pub struct WebResource {
     pub pages: HashMap<String, String>,
     client: Client
}

impl WebResource {

    pub fn new() -> Self {
        WebResource {
            pages: HashMap::new(),
            client: Client::new(),
        }
    }

    // let fetch_page = move |url: &str| -> String {
    //     download_map.entry(String::from(url))
    //                 .or_insert_with(move || {
    //                     match download_page(&client, &String::from(url)) {
    //                         Ok(s) => s,
    //                         Err(e) => format!("{:?}", e),
    //                     }
    //                 })
    //                 .clone()
    // };
    //

    pub fn fetch(&mut self, url: &String) -> Result<String, Error> {

        let mut headers = Headers::new();
        headers.set(UserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36".to_owned()));

        match self.client.get(url).headers(headers).send() {
            Ok(mut resp) => {
                let mut s = String::new();
                match resp.read_to_string(&mut s) {
                    Ok(size) => Ok(s),
                    Err(e) => Err(e),
                }
            }
            Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
        }
    }

    pub fn fetch_safe(&mut self, url: &str) -> String {
        match self.fetch(&String::from(url)) {
            Ok(s) => s,
            Err(e) => format!("{:?}", e),
        }
    }

    pub fn find(&mut self, url: &str) -> String {
        match self.pages.get(url) {
            Some(page) => page.clone(),
            None => { String::from("None") }
        }
    }

    pub fn get(&mut self, url: &str) -> String {
        if !self.pages.contains_key(url) {
            let res = self.fetch_safe(url);
            self.pages.insert(String::from(url), res);
        }
        self.find(url)
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces. This delegates to the platform-specific
//! implementation.

use texturegl::Texture;

use azure::AzSkiaGrGLSharedSurfaceRef;
use geom::size::Size2D;
use std::ptr;

#[cfg(not(target_os="android"))]
use gleam::gl;

#[cfg(target_os="macos")]
pub use platform::macos::surface::{NativeCompositingGraphicsContext,
                                   NativeGraphicsMetadata,
                                   NativePaintingGraphicsContext,
                                   IOSurfaceNativeSurface};

#[cfg(target_os="linux")]
pub use platform::linux::surface::{NativeCompositingGraphicsContext,
                                   NativeGraphicsMetadata,
                                   NativePaintingGraphicsContext,
                                   PixmapNativeSurface};

#[cfg(target_os="android")]
pub use platform::android::surface::{NativeCompositingGraphicsContext,
                                     NativeGraphicsMetadata,
                                     NativePaintingGraphicsContext,
                                     EGLImageNativeSurface};

pub enum NativeSurface {
    MemoryBuffer(MemoryBufferNativeSurface),
#[cfg(target_os="linux")]
    Pixmap(PixmapNativeSurface),
#[cfg(target_os="macos")]
    IOSurface(IOSurfaceNativeSurface),
#[cfg(target_os="android")]
    EGLImage(EGLImageNativeSurface),
}

#[cfg(target_os="linux")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        return NativeSurface::Pixmap(PixmapNativeSurface::from_azure_surface(surface));
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        if native_context.display == ptr::null_mut() {
            NativeSurface::MemoryBuffer(MemoryBufferNativeSurface::new(native_context, size, stride))
        } else {
            NativeSurface::Pixmap(PixmapNativeSurface::new(native_context, size, stride))
        }
   }
}

#[cfg(target_os="macos")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        NativeSurface::IOSurface(IOSurfaceNativeSurface::from_azure_surface(surface))
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        NativeSurface::IOSurface(IOSurfaceNativeSurface::new(native_context, size, stride))
   }
}

#[cfg(target_os="android")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        NativeSurface::EGLImage(EGLImageNativeSurface::from_azure_surface(surface))
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        NativeSurface::EGLImage(EGLImageNativeSurface::new(native_context, size, stride))
   }
}

macro_rules! native_surface_method_with_mutability {
    ($self_:ident, $function_name:ident, $surface:ident, $pattern:pat, $($argument:ident),*) => {
        match *$self_ {
            NativeSurface::MemoryBuffer($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="linux")]
            NativeSurface::Pixmap($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="macos")]
            NativeSurface::IOSurface($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="android")]
            NativeSurface::EGLImage($pattern) =>
                $surface.$function_name($($argument), *),
        }
    };
}

macro_rules! native_surface_method_mut {
    ($self_:ident $function_name:ident ($($argument:ident),*)) => {
        native_surface_method_with_mutability!($self_,
                                               $function_name,
                                               surface,
                                               ref mut surface,
                                               $($argument),
                                               *)
    };
}

macro_rules! native_surface_method {
    ($self_:ident $function_name:ident ($($argument:ident),*)) => {
        native_surface_method_with_mutability!($self_,
                                               $function_name,
                                               surface,
                                               ref surface,
                                               $($argument),
                                               *)
    };
}

impl NativeSurface {
    /// Binds the surface to a GPU texture. Compositing task only.
    pub fn bind_to_texture(&self,
                           native_context: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           size: Size2D<int>) {
        native_surface_method!(self bind_to_texture (native_context, texture, size))
    }

    /// Uploads pixel data to the surface. Painting task only.
    pub fn upload(&mut self, native_context: &NativePaintingGraphicsContext, data: &[u8]) {
        native_surface_method_mut!(self upload (native_context, data))
    }

    /// Returns an opaque ID identifying the surface for debugging.
    pub fn get_id(&self) -> int {
        native_surface_method!(self get_id ())
    }

    /// Destroys the surface. After this, it is an error to use the surface. Painting task only.
    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        native_surface_method_mut!(self destroy (graphics_context))
    }

    /// Records that the surface will leak if destroyed. This is done by the compositor immediately
    /// after receiving the surface.
    pub fn mark_will_leak(&mut self) {
        native_surface_method_mut!(self mark_will_leak ())
    }

    /// Marks the surface as not leaking. The painting task and the compositing task call this when
    /// they are certain that the surface will not leak. For example:
    ///
    /// 1. When sending buffers back to the render task, either the render task will receive them
    ///    or the render task has crashed. In the former case, they're the render task's
    ///    responsibility, so this is OK. In the latter case, the kernel or window server is going
    ///    to clean up the layer buffers. Either way, no leaks.
    ///
    /// 2. If the compositor is shutting down, the render task is also shutting down. In that case
    ///    it will destroy all its pixmaps, so no leak.
    ///
    /// 3. If the painting task is sending buffers to the compositor, then they are marked as not
    ///    leaking, because of the possibility that the compositor will die before the buffers are
    ///    destroyed.
    ///
    /// This helps debug leaks. For performance this may want to become a no-op in the future.
    pub fn mark_wont_leak(&mut self) {
        native_surface_method_mut!(self mark_wont_leak ())
    }
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct MemoryBufferNativeSurface {
    bytes: Vec<u8>,
}

impl MemoryBufferNativeSurface {
    pub fn new(_: &NativePaintingGraphicsContext, _: Size2D<i32>, _: i32) -> MemoryBufferNativeSurface {
        MemoryBufferNativeSurface{
            bytes: vec!(),
        }
    }

    /// This may only be called on the compositor side.
    #[cfg(not(target_os="android"))]
    pub fn bind_to_texture(&self, _: &NativeCompositingGraphicsContext, texture: &Texture, size: Size2D<int>) {
        let _bound = texture.bind();
        gl::tex_image_2d(gl::TEXTURE_2D,
                         0,
                         gl::RGBA as i32,
                         size.width as i32,
                         size.height as i32,
                         0,
                         gl::BGRA,
                         gl::UNSIGNED_BYTE,
                         Some(self.bytes.as_slice()));
    }

    #[cfg(target_os="android")]
    pub fn bind_to_texture(&self, _: &NativeCompositingGraphicsContext, _: &Texture, _: Size2D<int>) {
        panic!("Binding a memory surface to a texture is not yet supported on Android.");
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, _: &NativePaintingGraphicsContext, data: &[u8]) {
        self.bytes.push_all(data);
    }

    pub fn get_id(&self) -> int {
        0
    }

    pub fn destroy(&mut self, _: &NativePaintingGraphicsContext) {
    }

    pub fn mark_will_leak(&mut self) {
    }

    pub fn mark_wont_leak(&mut self) {
    }
}

<commit_msg>Replace bytes when uploading to MemoryBufferNativeSurface<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Implementation of cross-process surfaces. This delegates to the platform-specific
//! implementation.

use texturegl::Texture;

use azure::AzSkiaGrGLSharedSurfaceRef;
use geom::size::Size2D;
use std::ptr;

#[cfg(not(target_os="android"))]
use gleam::gl;

#[cfg(target_os="macos")]
pub use platform::macos::surface::{NativeCompositingGraphicsContext,
                                   NativeGraphicsMetadata,
                                   NativePaintingGraphicsContext,
                                   IOSurfaceNativeSurface};

#[cfg(target_os="linux")]
pub use platform::linux::surface::{NativeCompositingGraphicsContext,
                                   NativeGraphicsMetadata,
                                   NativePaintingGraphicsContext,
                                   PixmapNativeSurface};

#[cfg(target_os="android")]
pub use platform::android::surface::{NativeCompositingGraphicsContext,
                                     NativeGraphicsMetadata,
                                     NativePaintingGraphicsContext,
                                     EGLImageNativeSurface};

pub enum NativeSurface {
    MemoryBuffer(MemoryBufferNativeSurface),
#[cfg(target_os="linux")]
    Pixmap(PixmapNativeSurface),
#[cfg(target_os="macos")]
    IOSurface(IOSurfaceNativeSurface),
#[cfg(target_os="android")]
    EGLImage(EGLImageNativeSurface),
}

#[cfg(target_os="linux")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        return NativeSurface::Pixmap(PixmapNativeSurface::from_azure_surface(surface));
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        if native_context.display == ptr::null_mut() {
            NativeSurface::MemoryBuffer(MemoryBufferNativeSurface::new(native_context, size, stride))
        } else {
            NativeSurface::Pixmap(PixmapNativeSurface::new(native_context, size, stride))
        }
   }
}

#[cfg(target_os="macos")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        NativeSurface::IOSurface(IOSurfaceNativeSurface::from_azure_surface(surface))
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        NativeSurface::IOSurface(IOSurfaceNativeSurface::new(native_context, size, stride))
   }
}

#[cfg(target_os="android")]
impl NativeSurface {
    pub fn from_azure_surface(surface: AzSkiaGrGLSharedSurfaceRef) -> NativeSurface {
        NativeSurface::EGLImage(EGLImageNativeSurface::from_azure_surface(surface))
    }

    /// Creates a new native surface with uninitialized data.
    pub fn new(native_context: &NativePaintingGraphicsContext,
               size: Size2D<i32>,
               stride: i32)
               -> NativeSurface {
        NativeSurface::EGLImage(EGLImageNativeSurface::new(native_context, size, stride))
   }
}

macro_rules! native_surface_method_with_mutability {
    ($self_:ident, $function_name:ident, $surface:ident, $pattern:pat, $($argument:ident),*) => {
        match *$self_ {
            NativeSurface::MemoryBuffer($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="linux")]
            NativeSurface::Pixmap($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="macos")]
            NativeSurface::IOSurface($pattern) =>
                $surface.$function_name($($argument), *),
            #[cfg(target_os="android")]
            NativeSurface::EGLImage($pattern) =>
                $surface.$function_name($($argument), *),
        }
    };
}

macro_rules! native_surface_method_mut {
    ($self_:ident $function_name:ident ($($argument:ident),*)) => {
        native_surface_method_with_mutability!($self_,
                                               $function_name,
                                               surface,
                                               ref mut surface,
                                               $($argument),
                                               *)
    };
}

macro_rules! native_surface_method {
    ($self_:ident $function_name:ident ($($argument:ident),*)) => {
        native_surface_method_with_mutability!($self_,
                                               $function_name,
                                               surface,
                                               ref surface,
                                               $($argument),
                                               *)
    };
}

impl NativeSurface {
    /// Binds the surface to a GPU texture. Compositing task only.
    pub fn bind_to_texture(&self,
                           native_context: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           size: Size2D<int>) {
        native_surface_method!(self bind_to_texture (native_context, texture, size))
    }

    /// Uploads pixel data to the surface. Painting task only.
    pub fn upload(&mut self, native_context: &NativePaintingGraphicsContext, data: &[u8]) {
        native_surface_method_mut!(self upload (native_context, data))
    }

    /// Returns an opaque ID identifying the surface for debugging.
    pub fn get_id(&self) -> int {
        native_surface_method!(self get_id ())
    }

    /// Destroys the surface. After this, it is an error to use the surface. Painting task only.
    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        native_surface_method_mut!(self destroy (graphics_context))
    }

    /// Records that the surface will leak if destroyed. This is done by the compositor immediately
    /// after receiving the surface.
    pub fn mark_will_leak(&mut self) {
        native_surface_method_mut!(self mark_will_leak ())
    }

    /// Marks the surface as not leaking. The painting task and the compositing task call this when
    /// they are certain that the surface will not leak. For example:
    ///
    /// 1. When sending buffers back to the render task, either the render task will receive them
    ///    or the render task has crashed. In the former case, they're the render task's
    ///    responsibility, so this is OK. In the latter case, the kernel or window server is going
    ///    to clean up the layer buffers. Either way, no leaks.
    ///
    /// 2. If the compositor is shutting down, the render task is also shutting down. In that case
    ///    it will destroy all its pixmaps, so no leak.
    ///
    /// 3. If the painting task is sending buffers to the compositor, then they are marked as not
    ///    leaking, because of the possibility that the compositor will die before the buffers are
    ///    destroyed.
    ///
    /// This helps debug leaks. For performance this may want to become a no-op in the future.
    pub fn mark_wont_leak(&mut self) {
        native_surface_method_mut!(self mark_wont_leak ())
    }
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct MemoryBufferNativeSurface {
    bytes: Vec<u8>,
}

impl MemoryBufferNativeSurface {
    pub fn new(_: &NativePaintingGraphicsContext, _: Size2D<i32>, _: i32) -> MemoryBufferNativeSurface {
        MemoryBufferNativeSurface{
            bytes: vec!(),
        }
    }

    /// This may only be called on the compositor side.
    #[cfg(not(target_os="android"))]
    pub fn bind_to_texture(&self, _: &NativeCompositingGraphicsContext, texture: &Texture, size: Size2D<int>) {
        let _bound = texture.bind();
        gl::tex_image_2d(gl::TEXTURE_2D,
                         0,
                         gl::RGBA as i32,
                         size.width as i32,
                         size.height as i32,
                         0,
                         gl::BGRA,
                         gl::UNSIGNED_BYTE,
                         Some(self.bytes.as_slice()));
    }

    #[cfg(target_os="android")]
    pub fn bind_to_texture(&self, _: &NativeCompositingGraphicsContext, _: &Texture, _: Size2D<int>) {
        panic!("Binding a memory surface to a texture is not yet supported on Android.");
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, _: &NativePaintingGraphicsContext, data: &[u8]) {
        self.bytes.clear();
        self.bytes.push_all(data);
    }

    pub fn get_id(&self) -> int {
        0
    }

    pub fn destroy(&mut self, _: &NativePaintingGraphicsContext) {
    }

    pub fn mark_will_leak(&mut self) {
    }

    pub fn mark_wont_leak(&mut self) {
    }
}

<|endoftext|>


<commit_before>use alloc::string::String;
use core::char;

use crate::read::{ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE, U16Bytes};

/// The `.rsrc` section of a PE file.
#[derive(Debug, Clone, Copy)]
pub struct ResourceDirectory<'data> {
    data: &'data [u8],
}

impl<'data> ResourceDirectory<'data> {
    /// Construct from the data of the `.rsrc` section.
    pub fn new(data: &'data [u8]) -> Self {
        ResourceDirectory { data }
    }

    /// Parses the root resource directory.
    pub fn root(&self) -> Result<ResourceDirectoryTable<'data>> {
        ResourceDirectoryTable::parse(&self.data, 0)
    }
}

/// A table of resource entries.
#[derive(Debug, Clone)]
pub struct ResourceDirectoryTable<'data> {
    /// The table header.
    pub header: &'data pe::ImageResourceDirectory,
    /// The table entries.
    pub entries: &'data [pe::ImageResourceDirectoryEntry],
}

impl<'data> ResourceDirectoryTable<'data> {
    fn parse(data: &'data [u8], offset: u32) -> Result<Self> {
        let mut offset = u64::from(offset);
        let header = data
            .read::<pe::ImageResourceDirectory>(&mut offset)
            .read_error("Invalid resource table header")?;
        let entries_count = header.number_of_id_entries.get(LE) as usize
            + header.number_of_named_entries.get(LE) as usize;
        let entries = data
            .read_slice::<pe::ImageResourceDirectoryEntry>(&mut offset, entries_count)
            .read_error("Invalid resource table entries")?;
        Ok(Self { header, entries })
    }
}

impl pe::ImageResourceDirectoryEntry {
    /// Returns true if the entry has a name, rather than an ID.
    pub fn has_name(&self) -> bool {
        self.name_or_id.get(LE) & pe::IMAGE_RESOURCE_NAME_IS_STRING != 0
    }

    /// Returns the section offset of the name.
    ///
    /// Valid if `has_name()` returns true.
    fn name(&self) -> ResourceName {
        let offset = self.name_or_id.get(LE) & !pe::IMAGE_RESOURCE_NAME_IS_STRING;
        ResourceName { offset }
    }

    /// Returns the ID.
    ///
    /// Valid if `has_string_name()` returns false.
    fn id(&self) -> u16 {
        (self.name_or_id.get(LE) & 0x0000_FFFF) as u16
    }

    /// Returns the entry name
    pub fn name_or_id(&self) -> ResourceNameOrId {
        if self.has_name() {
            ResourceNameOrId::Name(self.name())
        } else {
            ResourceNameOrId::Id(self.id())
        }
    }

    /// Returns true if the entry is a subtable.
    pub fn is_table(&self) -> bool {
        self.offset_to_data_or_directory.get(LE) & pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY != 0
    }

    /// Returns the section offset of the associated table or data.
    pub fn data_offset(&self) -> u32 {
        self.offset_to_data_or_directory.get(LE) & !pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY
    }

    /// Returns the data associated to this directory entry.
    pub fn data<'data>(
        &self,
        section: ResourceDirectory<'data>,
    ) -> Result<ResourceDirectoryEntryData<'data>> {
        if self.is_table() {
            ResourceDirectoryTable::parse(section.data, self.data_offset())
                .map(|t| ResourceDirectoryEntryData::Table(t))
        } else {
            section
                .data
                .read_at::<pe::ImageResourceDataEntry>(self.data_offset().into())
                .read_error("Invalid resource entry")
                .map(|d| ResourceDirectoryEntryData::Data(d))
        }
    }
}

/// Data associated with a resource directory entry.
#[derive(Debug, Clone)]
pub enum ResourceDirectoryEntryData<'data> {
    /// A subtable entry.
    Table(ResourceDirectoryTable<'data>),
    /// A resource data entry.
    Data(&'data pe::ImageResourceDataEntry),
}

impl<'data> ResourceDirectoryEntryData<'data> {
    /// Converts to an option of table.
    ///
    /// Helper for iterator filtering.
    pub fn table(self) -> Option<ResourceDirectoryTable<'data>> {
        match self {
            Self::Table(dir) => Some(dir),
            _ => None,
        }
    }

    /// Converts to an option of data entry.
    ///
    /// Helper for iterator filtering.
    pub fn data(self) -> Option<&'data pe::ImageResourceDataEntry> {
        match self {
            Self::Data(rsc) => Some(rsc),
            _ => None,
        }
    }
}

/// A resource name.
#[derive(Debug, Clone, Copy)]
pub struct ResourceName {
    offset: u32,
}

impl ResourceName {
    /// Converts to a `String`.
    pub fn to_string_lossy(&self, directory: ResourceDirectory) -> Result<String> {
        let d = self.data(directory)?.iter().map(|c| c.get(LE));

        Ok(char::decode_utf16(d)
            .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
            .collect::<String>())
    }

    /// Returns the string unicode buffer.
    pub fn data<'data>(
        &self,
        directory: ResourceDirectory<'data>,
    ) -> Result<&'data [U16Bytes<LE>]> {
        let mut offset = u64::from(self.offset);
        let len = directory
            .data
            .read::<U16Bytes<LE>>(&mut offset)
            .read_error("Invalid resource name offset")?;
        directory
            .data
            .read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
            .read_error("Invalid resource name length")
    }
}

/// A resource name or ID.
///
/// Can be either a string or a numeric ID.
#[derive(Debug)]
pub enum ResourceNameOrId {
    /// A resource name.
    Name(ResourceName),
    /// A resource ID.
    Id(u16),
}

impl ResourceNameOrId {
    /// Converts to an option of name.
    ///
    /// Helper for iterator filtering.
    pub fn name(self) -> Option<ResourceName> {
        match self {
            Self::Name(name) => Some(name),
            _ => None,
        }
    }

    /// Converts to an option of ID.
    ///
    /// Helper for iterator filtering.
    pub fn id(self) -> Option<u16> {
        match self {
            Self::Id(id) => Some(id),
            _ => None,
        }
    }
}
<commit_msg>read/pe: add ResourceName::raw_data method (#487)<commit_after>use alloc::string::String;
use core::char;

use crate::read::{ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE, U16Bytes};

/// The `.rsrc` section of a PE file.
#[derive(Debug, Clone, Copy)]
pub struct ResourceDirectory<'data> {
    data: &'data [u8],
}

impl<'data> ResourceDirectory<'data> {
    /// Construct from the data of the `.rsrc` section.
    pub fn new(data: &'data [u8]) -> Self {
        ResourceDirectory { data }
    }

    /// Parses the root resource directory.
    pub fn root(&self) -> Result<ResourceDirectoryTable<'data>> {
        ResourceDirectoryTable::parse(&self.data, 0)
    }
}

/// A table of resource entries.
#[derive(Debug, Clone)]
pub struct ResourceDirectoryTable<'data> {
    /// The table header.
    pub header: &'data pe::ImageResourceDirectory,
    /// The table entries.
    pub entries: &'data [pe::ImageResourceDirectoryEntry],
}

impl<'data> ResourceDirectoryTable<'data> {
    fn parse(data: &'data [u8], offset: u32) -> Result<Self> {
        let mut offset = u64::from(offset);
        let header = data
            .read::<pe::ImageResourceDirectory>(&mut offset)
            .read_error("Invalid resource table header")?;
        let entries_count = header.number_of_id_entries.get(LE) as usize
            + header.number_of_named_entries.get(LE) as usize;
        let entries = data
            .read_slice::<pe::ImageResourceDirectoryEntry>(&mut offset, entries_count)
            .read_error("Invalid resource table entries")?;
        Ok(Self { header, entries })
    }
}

impl pe::ImageResourceDirectoryEntry {
    /// Returns true if the entry has a name, rather than an ID.
    pub fn has_name(&self) -> bool {
        self.name_or_id.get(LE) & pe::IMAGE_RESOURCE_NAME_IS_STRING != 0
    }

    /// Returns the section offset of the name.
    ///
    /// Valid if `has_name()` returns true.
    fn name(&self) -> ResourceName {
        let offset = self.name_or_id.get(LE) & !pe::IMAGE_RESOURCE_NAME_IS_STRING;
        ResourceName { offset }
    }

    /// Returns the ID.
    ///
    /// Valid if `has_string_name()` returns false.
    fn id(&self) -> u16 {
        (self.name_or_id.get(LE) & 0x0000_FFFF) as u16
    }

    /// Returns the entry name
    pub fn name_or_id(&self) -> ResourceNameOrId {
        if self.has_name() {
            ResourceNameOrId::Name(self.name())
        } else {
            ResourceNameOrId::Id(self.id())
        }
    }

    /// Returns true if the entry is a subtable.
    pub fn is_table(&self) -> bool {
        self.offset_to_data_or_directory.get(LE) & pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY != 0
    }

    /// Returns the section offset of the associated table or data.
    pub fn data_offset(&self) -> u32 {
        self.offset_to_data_or_directory.get(LE) & !pe::IMAGE_RESOURCE_DATA_IS_DIRECTORY
    }

    /// Returns the data associated to this directory entry.
    pub fn data<'data>(
        &self,
        section: ResourceDirectory<'data>,
    ) -> Result<ResourceDirectoryEntryData<'data>> {
        if self.is_table() {
            ResourceDirectoryTable::parse(section.data, self.data_offset())
                .map(|t| ResourceDirectoryEntryData::Table(t))
        } else {
            section
                .data
                .read_at::<pe::ImageResourceDataEntry>(self.data_offset().into())
                .read_error("Invalid resource entry")
                .map(|d| ResourceDirectoryEntryData::Data(d))
        }
    }
}

/// Data associated with a resource directory entry.
#[derive(Debug, Clone)]
pub enum ResourceDirectoryEntryData<'data> {
    /// A subtable entry.
    Table(ResourceDirectoryTable<'data>),
    /// A resource data entry.
    Data(&'data pe::ImageResourceDataEntry),
}

impl<'data> ResourceDirectoryEntryData<'data> {
    /// Converts to an option of table.
    ///
    /// Helper for iterator filtering.
    pub fn table(self) -> Option<ResourceDirectoryTable<'data>> {
        match self {
            Self::Table(dir) => Some(dir),
            _ => None,
        }
    }

    /// Converts to an option of data entry.
    ///
    /// Helper for iterator filtering.
    pub fn data(self) -> Option<&'data pe::ImageResourceDataEntry> {
        match self {
            Self::Data(rsc) => Some(rsc),
            _ => None,
        }
    }
}

/// A resource name.
#[derive(Debug, Clone, Copy)]
pub struct ResourceName {
    offset: u32,
}

impl ResourceName {
    /// Converts to a `String`.
    pub fn to_string_lossy(&self, directory: ResourceDirectory) -> Result<String> {
        let d = self.data(directory)?.iter().map(|c| c.get(LE));

        Ok(char::decode_utf16(d)
            .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
            .collect::<String>())
    }

    /// Returns the string unicode buffer.
    pub fn data<'data>(
        &self,
        directory: ResourceDirectory<'data>,
    ) -> Result<&'data [U16Bytes<LE>]> {
        let mut offset = u64::from(self.offset);
        let len = directory
            .data
            .read::<U16Bytes<LE>>(&mut offset)
            .read_error("Invalid resource name offset")?;
        directory
            .data
            .read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
            .read_error("Invalid resource name length")
    }

    /// Returns the string buffer as raw bytes.
    pub fn raw_data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u8]> {
        self.data(directory).map(crate::pod::bytes_of_slice)
    }
}

/// A resource name or ID.
///
/// Can be either a string or a numeric ID.
#[derive(Debug)]
pub enum ResourceNameOrId {
    /// A resource name.
    Name(ResourceName),
    /// A resource ID.
    Id(u16),
}

impl ResourceNameOrId {
    /// Converts to an option of name.
    ///
    /// Helper for iterator filtering.
    pub fn name(self) -> Option<ResourceName> {
        match self {
            Self::Name(name) => Some(name),
            _ => None,
        }
    }

    /// Converts to an option of ID.
    ///
    /// Helper for iterator filtering.
    pub fn id(self) -> Option<u16> {
        match self {
            Self::Id(id) => Some(id),
            _ => None,
        }
    }
}
<|endoftext|>