<commit_before>use state::{Editable, Undoable, Saveable, Movement};
use termion::event::Key;
use view::View;
use clipboard::ClipboardContext;

#[derive(Clone)]
enum State {
    Insert,
    Message(String),
    Prompt(String, String),
    Exit,
}

pub struct Command {
    state: State,
}

impl Command {
    pub fn new() -> Command {
        Command { state: State::Insert }
    }

    pub fn treat_event<T>(&mut self, content: &mut T, view: &mut View, key: Key) -> bool
        where T: Editable + Saveable + Undoable
    {
        self.state = match self.state.clone() {
            State::Insert => treat_insert_event(content, view, key),
            State::Prompt(prompt, message) => {
                treat_prompt_event(content, view, key, prompt, message)
            }
            State::Message(_) => treat_message_event(content, view, key),
            State::Exit => panic!("continued after an Exit state"),
        };
        if let State::Exit = self.state {
            return true;
        }
        false
    }
}

fn treat_message_event<T>(content: &mut T, view: &mut View, key: Key) -> State
    where T: Editable + Saveable + Undoable
{
    view.quiet();
    treat_insert_event(content, view, key)
}

fn treat_insert_event<T>(content: &mut T, view: &mut View, key: Key) -> State
    where T: Editable + Saveable + Undoable
{
    match key {
        Key::Ctrl('q') => State::Exit,
        Key::Ctrl('s') => {
            let prompt = "Save to: ".to_string();
            let message = content.name().clone();
            view.prompt(&prompt, &message);
            State::Prompt(prompt, message)
        }
        key => {
            match key {
                Key::Ctrl('z') => content.undo(),
                Key::Ctrl('y') => content.redo(),
                Key::Ctrl('v') => {
                    let ctx = ClipboardContext::new().unwrap();
                    for c in ctx.get_contents().unwrap().chars() {
                        content.insert(c);
                    }
                }
                Key::Up => content.step(Movement::Up),
                Key::Down => content.step(Movement::Down),
                Key::Left => content.step(Movement::Left),
                Key::Right => content.step(Movement::Right),
                Key::PageUp => content.step(Movement::PageUp(view.lines_height() as usize)),
                Key::PageDown => content.step(Movement::PageDown(view.lines_height() as usize)),
                Key::Home => content.step(Movement::LineStart),
                Key::End => content.step(Movement::LineEnd),
                Key::Backspace => {
                    content.delete();
                }
                Key::Char(c) => content.insert(c),
                _ => {}
            }
            State::Insert
        }
    }
}
fn treat_prompt_event<T>(content: &mut T,
                         view: &mut View,
                         key: Key,
                         prompt: String,
                         mut message: String)
                         -> State
    where T: Editable + Saveable + Undoable
{
    match key {
        Key::Char('\n') => {
            let old_name = content.name().clone();
            content.set_name(message);
            let msg = match content.save() {
                Err(e) => {
                    content.set_name(old_name);
                    e.to_string()
                },
                Ok(_) => format!("Saved file {}", content.name()),
            };
            view.message(&msg);
            State::Message(msg)
        }
        Key::Char(c) => {
            message.push(c);
            view.prompt(&prompt, &message);
            State::Prompt(prompt, message)
        }
        Key::Backspace => {
            message.pop();
            view.prompt(&prompt, &message);
            State::Prompt(prompt, message)
        }
        _ => State::Prompt(prompt, message),
    }
}
<commit_msg>refactored out state cloning<commit_after>use state::{Editable, Undoable, Saveable, Movement};
use termion::event::Key;
use view::View;
use clipboard::ClipboardContext;

enum State {
    Insert,
    Message(String),
    Prompt(String, String),
    Exit,
}

pub struct Command {
    state: State,
}

impl Command {
    pub fn new() -> Command {
        Command { state: State::Insert }
    }

    pub fn treat_event<T>(&mut self, content: &mut T, view: &mut View, key: Key) -> bool
        where T: Editable + Saveable + Undoable
    {
        match self.state {
            State::Insert => treat_insert_event(content, view, key, &mut self.state),
            State::Prompt(_, _) => treat_prompt_event(content, view, key, &mut self.state),
            State::Message(_) => treat_message_event(content, view, key, &mut self.state),
            State::Exit => panic!("continued after an Exit state"),
        };
        if let State::Exit = self.state {
            return true;
        }
        false
    }
}

fn treat_message_event<T>(content: &mut T, view: &mut View, key: Key, state: &mut State)
    where T: Editable + Saveable + Undoable
{
    view.quiet();
    treat_insert_event(content, view, key, state)
}

fn treat_insert_event<T>(content: &mut T, view: &mut View, key: Key, state: &mut State)
    where T: Editable + Saveable + Undoable
{
    match key {
        Key::Ctrl('q') => {
            *state = State::Exit;
        }
        Key::Ctrl('s') => {
            let prompt = "Save to: ".to_string();
            let message = content.name().clone();
            view.prompt(&prompt, &message);
            *state = State::Prompt(prompt, message);
        }
        key => {
            match key {
                Key::Ctrl('z') => content.undo(),
                Key::Ctrl('y') => content.redo(),
                Key::Ctrl('v') => {
                    let ctx = ClipboardContext::new().unwrap();
                    for c in ctx.get_contents().unwrap().chars() {
                        content.insert(c);
                    }
                }
                Key::Up => content.step(Movement::Up),
                Key::Down => content.step(Movement::Down),
                Key::Left => content.step(Movement::Left),
                Key::Right => content.step(Movement::Right),
                Key::PageUp => content.step(Movement::PageUp(view.lines_height() as usize)),
                Key::PageDown => content.step(Movement::PageDown(view.lines_height() as usize)),
                Key::Home => content.step(Movement::LineStart),
                Key::End => content.step(Movement::LineEnd),
                Key::Backspace => {
                    content.delete();
                }
                Key::Char(c) => content.insert(c),
                _ => {}
            }
            *state = State::Insert;
        }
    }
}
fn treat_prompt_event<T>(content: &mut T, view: &mut View, key: Key, state: &mut State)
    where T: Editable + Saveable + Undoable
{
    match key {
        Key::Char('\n') => {
            let msg: String;
            if let State::Prompt(_, ref mut message) = *state {
                let old_name = content.name().clone();
                content.set_name(message.clone());
                msg = match content.save() {
                    Err(e) => {
                        content.set_name(old_name);
                        e.to_string()
                    }
                    Ok(_) => format!("Saved file {}", content.name()),
                };
                view.message(&msg);
            } else {
                panic!("Treating prompt event when even is not a Prompt");
            }
            *state = State::Message(msg);
        }
        Key::Char(c) => {
            if let State::Prompt(ref prompt, ref mut message) = *state {
                message.push(c);
                view.prompt(&prompt, &message);
            } else {
                panic!("Treating prompt event when even is not a Prompt");
            }
        }
        Key::Backspace => {
            if let State::Prompt(ref prompt, ref mut message) = *state {
                message.pop();
                view.prompt(&prompt, &message);
            } else {
                panic!("Treating prompt event when even is not a Prompt");
            }
        }
        Key::Ctrl('q') => {
            *state = State::Exit;
        }
        _ => {}
    }
}
<|endoftext|>


<commit_before>use screen::*;
use ui_utils;
use piston_window::{self, PistonWindow};
use conrod::{self, Widget, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenu {
    ui: conrod::Ui<piston_window::Glyphs>,
    state: Option<State>,
}

impl MainMenu {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        MainMenu {
            ui: ui_utils::create_ui(&window, &context.assets_path),
            state: None,
        }
    }
}

enum State {
    NewGame,
    Options,
    Exit,
}

impl Screen for MainMenu {
    fn on_input(&mut self, _: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        self.ui.handle_event(window);
        let mut result = Vec::new();

        match self.state {
            Some(State::NewGame) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(Battle::new(&window, context))));
            }
            Some(State::Options) => {
                result.push(InputResult::PushScreen(Box::new(Options::new(&window, context))));
            }
            Some(State::Exit) => {
                result.push(InputResult::PopScreen);
            }
            None => {}
        }

        self.state = None;
        result
    }

    fn on_draw(&mut self, _: &piston_window::RenderArgs, window: &PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, _: &piston_window::UpdateArgs) {
        let button_color = conrod::color::rgb(0.4, 0.75, 0.6);

        let state = &mut self.state;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .color(button_color)
                .label("New game")
                .react(|| *state = Some(State::NewGame))
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .color(button_color)
                .label("Options")
                .react(|| *state = Some(State::Options))
                .set(OPTIONS_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(OPTIONS_BUTTON, 45.0)
                .color(button_color)
                .label("Exit")
                .react(|| *state = Some(State::Exit))
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}
<commit_msg>TODO note<commit_after>use screen::*;
use ui_utils;
use piston_window::{self, PistonWindow};
use conrod::{self, Widget, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenu {
    ui: conrod::Ui<piston_window::Glyphs>,
    state: Option<State>,
}

impl MainMenu {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        MainMenu {
            ui: ui_utils::create_ui(&window, &context.assets_path),
            state: None,
        }
    }
}

enum State {
    NewGame,
    Options,
    Exit,
}

impl Screen for MainMenu {
    fn on_input(&mut self, _: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        self.ui.handle_event(window);
        let mut result = Vec::new();

        match self.state {
            Some(State::NewGame) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(Battle::new(&window, context))));
            }
            Some(State::Options) => {
                result.push(InputResult::PushScreen(Box::new(Options::new(&window, context))));
            }
            Some(State::Exit) => {
                result.push(InputResult::PopScreen);
            }
            None => {}
        }

        // TODO: on scope exit?
        self.state = None;
        result
    }

    fn on_draw(&mut self, _: &piston_window::RenderArgs, window: &PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, _: &piston_window::UpdateArgs) {
        let button_color = conrod::color::rgb(0.4, 0.75, 0.6);

        let state = &mut self.state;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .color(button_color)
                .label("New game")
                .react(|| *state = Some(State::NewGame))
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .color(button_color)
                .label("Options")
                .react(|| *state = Some(State::Options))
                .set(OPTIONS_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(OPTIONS_BUTTON, 45.0)
                .color(button_color)
                .label("Exit")
                .react(|| *state = Some(State::Exit))
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}
<|endoftext|>


<commit_before>#![feature(rustc_private, i128_type)]
extern crate miri;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate syntax;

use std::path::{PathBuf, Path};
use std::io::Write;
use std::sync::{Mutex, Arc};
use std::io;

use rustc::session::Session;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc::ty::TyCtxt;
use syntax::ast;

struct MiriCompilerCalls {
    default: RustcDefaultCalls,
    /// whether we are building for the host
    host_target: bool,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType
    ) -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>
    ) -> Compilation {
        self.default.late_callback(matches, sess, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if !self.host_target {
            // only fully compile targets on the host
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (String::from("miri"), syntax::feature_gate::AttributeType::Whitelisted);
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();
    let limits = Default::default();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(miri::ResourceLimits, TyCtxt<'a, 'tcx, 'tcx>, &'a CompileState<'a, 'tcx>);
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::Item_::ItemFn(_, _, _, _, _, body_id) = i.node {
                    if i.attrs.iter().any(|attr| attr.name().map_or(false, |n| n == "test")) {
                        let did = self.1.hir.body_owner_def_id(body_id);
                        println!("running test: {}", self.1.hir.def_path(did).to_string(self.1));
                        miri::eval_main(self.1, did, None, self.0);
                        self.2.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(limits, tcx, state));
    } else if let Some((entry_node_id, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn|
                                if tcx.is_mir_available(start_fn) { Some(start_fn) } else { None });
        miri::eval_main(tcx, entry_def_id, start_wrapper, limits);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn main() {
    let path = option_env!("MIRI_RUSTC_TEST")
        .map(String::from)
        .unwrap_or_else(|| {
            std::env::var("MIRI_RUSTC_TEST")
                .expect("need to set MIRI_RUSTC_TEST to path of rustc tests")
        });

    let mut mir_not_found = Vec::new();
    let mut crate_not_found = Vec::new();
    let mut success = 0;
    let mut failed = Vec::new();
    let mut c_abi_fns = Vec::new();
    let mut abi = Vec::new();
    let mut unsupported = Vec::new();
    let mut unimplemented_intrinsic = Vec::new();
    let mut limits = Vec::new();
    let mut files: Vec<_> = std::fs::read_dir(path).unwrap().collect();
    while let Some(file) = files.pop() {
        let file = file.unwrap();
        let path = file.path();
        if file.metadata().unwrap().is_dir() {
            if !path.to_str().unwrap().ends_with("auxiliary") {
                // add subdirs recursively
                files.extend(std::fs::read_dir(path).unwrap());
            }
            continue;
        }
        if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
            continue;
        }
        let stderr = std::io::stderr();
        write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
        let mut host_target = false;
        let mut args: Vec<String> = std::env::args().filter(|arg| {
            if arg == "--miri_host_target" {
                host_target = true;
                false // remove the flag, rustc doesn't know it
            } else {
                true
            }
        }).collect();
        // file to process
        args.push(path.display().to_string());

        let sysroot_flag = String::from("--sysroot");
        if !args.contains(&sysroot_flag) {
            args.push(sysroot_flag);
            args.push(Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST").display().to_string());
        }

        args.push("-Zmir-opt-level=3".to_owned());
        // for auxilary builds in unit tests
        args.push("-Zalways-encode-mir".to_owned());

        // A threadsafe buffer for writing.
        #[derive(Default, Clone)]
        struct BufWriter(Arc<Mutex<Vec<u8>>>);

        impl Write for BufWriter {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.0.lock().unwrap().write(buf)
            }
            fn flush(&mut self) -> io::Result<()> {
                self.0.lock().unwrap().flush()
            }
        }
        let buf = BufWriter::default();
        let output = buf.clone();
        let result = std::panic::catch_unwind(|| {
            rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
                default: RustcDefaultCalls,
                host_target,
            }, None, Some(Box::new(buf)));
        });

        match result {
            Ok(()) => {
                success += 1;
                writeln!(stderr.lock(), "ok").unwrap()
            },
            Err(_) => {
                let output = output.0.lock().unwrap();
                let output_err = std::str::from_utf8(&output).unwrap();
                if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                    let end = text.find('`').unwrap();
                    mir_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                    let end = text.find('`').unwrap();
                    crate_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                } else {
                    for text in output_err.split("error: ").skip(1) {
                        let end = text.find('\n').unwrap_or(text.len());
                        let c_abi = "can't call C ABI function: ";
                        let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                        let unsupported_s = "miri does not support ";
                        let abi_s = "can't handle function with ";
                        let limit_s = "reached the configured maximum ";
                        if text.starts_with(c_abi) {
                            c_abi_fns.push(text[c_abi.len()..end].to_string());
                        } else if text.starts_with(unimplemented_intrinsic_s) {
                            unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                        } else if text.starts_with(unsupported_s) {
                            unsupported.push(text[unsupported_s.len()..end].to_string());
                        } else if text.starts_with(abi_s) {
                            abi.push(text[abi_s.len()..end].to_string());
                        } else if text.starts_with(limit_s) {
                            limits.push(text[limit_s.len()..end].to_string());
                        } else if text.find("aborting").is_none() {
                            failed.push(text[..end].to_string());
                        }
                    }
                    writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                }
            }
        }
    }
    let stderr = std::io::stderr();
    let mut stderr = stderr.lock();
    writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                        {} C fn, {} ABI, {} unsupported, {} intrinsic",
                        success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                        c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
    writeln!(stderr, "# The \"other reasons\" errors").unwrap();
    writeln!(stderr, "(sorted, deduplicated)").unwrap();
    print_vec(&mut stderr, failed);

    writeln!(stderr, "# can't call C ABI function").unwrap();
    print_vec(&mut stderr, c_abi_fns);

    writeln!(stderr, "# unsupported ABI").unwrap();
    print_vec(&mut stderr, abi);

    writeln!(stderr, "# unsupported").unwrap();
    print_vec(&mut stderr, unsupported);

    writeln!(stderr, "# unimplemented intrinsics").unwrap();
    print_vec(&mut stderr, unimplemented_intrinsic);

    writeln!(stderr, "# mir not found").unwrap();
    print_vec(&mut stderr, mir_not_found);

    writeln!(stderr, "# crate not found").unwrap();
    print_vec(&mut stderr, crate_not_found);
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        for next in &mut v {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<commit_msg>fix rustc_tests build<commit_after>#![feature(rustc_private, i128_type)]
extern crate miri;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate syntax;

use std::path::{PathBuf, Path};
use std::io::Write;
use std::sync::{Mutex, Arc};
use std::io;

use rustc::session::Session;
use rustc::middle::cstore::CrateStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc::ty::TyCtxt;
use syntax::ast;

struct MiriCompilerCalls {
    default: RustcDefaultCalls,
    /// whether we are building for the host
    host_target: bool,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType
    ) -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        cstore: &CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>
    ) -> Compilation {
        self.default.late_callback(matches, sess, cstore, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if !self.host_target {
            // only fully compile targets on the host
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (String::from("miri"), syntax::feature_gate::AttributeType::Whitelisted);
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();
    let limits = Default::default();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(miri::ResourceLimits, TyCtxt<'a, 'tcx, 'tcx>, &'a CompileState<'a, 'tcx>);
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::Item_::ItemFn(_, _, _, _, _, body_id) = i.node {
                    if i.attrs.iter().any(|attr| attr.name().map_or(false, |n| n == "test")) {
                        let did = self.1.hir.body_owner_def_id(body_id);
                        println!("running test: {}", self.1.hir.def_path(did).to_string(self.1));
                        miri::eval_main(self.1, did, None, self.0);
                        self.2.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(limits, tcx, state));
    } else if let Some((entry_node_id, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn|
                                if tcx.is_mir_available(start_fn) { Some(start_fn) } else { None });
        miri::eval_main(tcx, entry_def_id, start_wrapper, limits);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn main() {
    let path = option_env!("MIRI_RUSTC_TEST")
        .map(String::from)
        .unwrap_or_else(|| {
            std::env::var("MIRI_RUSTC_TEST")
                .expect("need to set MIRI_RUSTC_TEST to path of rustc tests")
        });

    let mut mir_not_found = Vec::new();
    let mut crate_not_found = Vec::new();
    let mut success = 0;
    let mut failed = Vec::new();
    let mut c_abi_fns = Vec::new();
    let mut abi = Vec::new();
    let mut unsupported = Vec::new();
    let mut unimplemented_intrinsic = Vec::new();
    let mut limits = Vec::new();
    let mut files: Vec<_> = std::fs::read_dir(path).unwrap().collect();
    while let Some(file) = files.pop() {
        let file = file.unwrap();
        let path = file.path();
        if file.metadata().unwrap().is_dir() {
            if !path.to_str().unwrap().ends_with("auxiliary") {
                // add subdirs recursively
                files.extend(std::fs::read_dir(path).unwrap());
            }
            continue;
        }
        if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
            continue;
        }
        let stderr = std::io::stderr();
        write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
        let mut host_target = false;
        let mut args: Vec<String> = std::env::args().filter(|arg| {
            if arg == "--miri_host_target" {
                host_target = true;
                false // remove the flag, rustc doesn't know it
            } else {
                true
            }
        }).collect();
        // file to process
        args.push(path.display().to_string());

        let sysroot_flag = String::from("--sysroot");
        if !args.contains(&sysroot_flag) {
            args.push(sysroot_flag);
            args.push(Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST").display().to_string());
        }

        args.push("-Zmir-opt-level=3".to_owned());
        // for auxilary builds in unit tests
        args.push("-Zalways-encode-mir".to_owned());

        // A threadsafe buffer for writing.
        #[derive(Default, Clone)]
        struct BufWriter(Arc<Mutex<Vec<u8>>>);

        impl Write for BufWriter {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.0.lock().unwrap().write(buf)
            }
            fn flush(&mut self) -> io::Result<()> {
                self.0.lock().unwrap().flush()
            }
        }
        let buf = BufWriter::default();
        let output = buf.clone();
        let result = std::panic::catch_unwind(|| {
            rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
                default: RustcDefaultCalls,
                host_target,
            }, None, Some(Box::new(buf)));
        });

        match result {
            Ok(()) => {
                success += 1;
                writeln!(stderr.lock(), "ok").unwrap()
            },
            Err(_) => {
                let output = output.0.lock().unwrap();
                let output_err = std::str::from_utf8(&output).unwrap();
                if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                    let end = text.find('`').unwrap();
                    mir_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                    let end = text.find('`').unwrap();
                    crate_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                } else {
                    for text in output_err.split("error: ").skip(1) {
                        let end = text.find('\n').unwrap_or(text.len());
                        let c_abi = "can't call C ABI function: ";
                        let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                        let unsupported_s = "miri does not support ";
                        let abi_s = "can't handle function with ";
                        let limit_s = "reached the configured maximum ";
                        if text.starts_with(c_abi) {
                            c_abi_fns.push(text[c_abi.len()..end].to_string());
                        } else if text.starts_with(unimplemented_intrinsic_s) {
                            unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                        } else if text.starts_with(unsupported_s) {
                            unsupported.push(text[unsupported_s.len()..end].to_string());
                        } else if text.starts_with(abi_s) {
                            abi.push(text[abi_s.len()..end].to_string());
                        } else if text.starts_with(limit_s) {
                            limits.push(text[limit_s.len()..end].to_string());
                        } else if text.find("aborting").is_none() {
                            failed.push(text[..end].to_string());
                        }
                    }
                    writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                }
            }
        }
    }
    let stderr = std::io::stderr();
    let mut stderr = stderr.lock();
    writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                        {} C fn, {} ABI, {} unsupported, {} intrinsic",
                        success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                        c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
    writeln!(stderr, "# The \"other reasons\" errors").unwrap();
    writeln!(stderr, "(sorted, deduplicated)").unwrap();
    print_vec(&mut stderr, failed);

    writeln!(stderr, "# can't call C ABI function").unwrap();
    print_vec(&mut stderr, c_abi_fns);

    writeln!(stderr, "# unsupported ABI").unwrap();
    print_vec(&mut stderr, abi);

    writeln!(stderr, "# unsupported").unwrap();
    print_vec(&mut stderr, unsupported);

    writeln!(stderr, "# unimplemented intrinsics").unwrap();
    print_vec(&mut stderr, unimplemented_intrinsic);

    writeln!(stderr, "# mir not found").unwrap();
    print_vec(&mut stderr, mir_not_found);

    writeln!(stderr, "# crate not found").unwrap();
    print_vec(&mut stderr, crate_not_found);
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        for next in &mut v {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<|endoftext|>


<commit_before>//! Data types used in our public API.

use ffi::Encoding;
pub use self::Reliability::{Reliable, Unreliable};

/// Possible data formats.
#[deriving(PartialEq, Eq, Show)]
pub enum Format {
    /// Process the text as-is.
    Text,
    /// Try to stip HTML tags and expand entities.
    Html
}

/// Is the output of the language decoder reliable?
#[deriving(PartialEq, Eq, Show)]
pub enum Reliability {
    /// The decoder is reasonably confident about this guess.
    Reliable,
    /// The decoder does not have high confidence in this guess.
    Unreliable
}

impl Reliability {
    /// Construct from a boolean value.
    pub fn from_bool(is_reliable: bool) -> Reliability {
        if is_reliable { Reliable } else { Unreliable }
    }
}

/// A language code, normally two letters for common languages.
#[deriving(PartialEq, Eq, Show)]
pub struct Lang(pub &'static str);

/// Hints to the decoder, which it will use to make better guesses.
///
/// ```
/// use std::default::Default;
/// use cld2::Hints;
///
/// // Specify just one hint.
/// let hints = Hints{content_language: Some("en"),
///                   .. Default::default()};
/// assert_eq!(Some("en"), hints.content_language);
/// assert_eq!(None, hints.tld);
/// ```
#[deriving(Show, Default)]
pub struct Hints<'a> {
    /// A value from an HTTP Content-Language header.  The value "fr,en"
    /// will bias the decoder towards French and English.
    pub content_language: Option<&'a str>,

    /// The top-level domain associated with this text.  The value "fr"
    /// will bias the decoder towards French.
    pub tld: Option<&'a str>,

    /// The original encoding of the text, before it was converted to
    /// UTF-8.  See `Encoding` for legal values.
    #[experimental]
    pub encoding: Option<Encoding>,

    /// An extra language hint.
    pub language: Option<Lang>
}

/// Detailed information about how well the input text matched a specific
/// language.
pub struct LanguageScore {
    /// The language matched.
    pub language: Option<Lang>,

    /// The percentage of the text which appears to be in this language.
    /// Between 0 and 100.
    pub percent: u8,

    /// Scores near 1.0 indicate a "normal" text for this language.  Scores
    /// further away from 1.0 indicated strange or atypical texts.
    pub normalized_score: f64
}

/// Detailed language detection results.
///
/// Note: Do not rely on this struct containing only the fields listed
/// below.  It may gain extra fields in the future.
pub struct DetectionResult {
    /// The language detected.
    pub language: Option<Lang>,

    /// The scores for the top 3 candidate languages.
    pub scores: [LanguageScore, ..3],

    /// The number of bytes of actual text found, excluding tags, etc.
    pub text_bytes: i32,

    /// Is this guess reliable?
    pub reliability: Reliability,

    /// A private field to keep the user from being able to construct
    /// instances directly, so we can extend this struct without breaking
    /// the API.  There's probably a better way to do this.
    _dummy: ()
}

impl DetectionResult {
    /// Create a new DetectionResult.  You don't actually need to call
    /// this directly.
    pub fn new(language: Option<Lang>, scores: [LanguageScore, ..3],
               text_bytes: i32, reliability: Reliability) -> DetectionResult {
        DetectionResult{language: language, scores: scores,
                        text_bytes: text_bytes, reliability: reliability,
                        _dummy: ()}
    }
}
<commit_msg>Make semi-internal API as experimental<commit_after>//! Data types used in our public API.

use ffi::Encoding;
pub use self::Reliability::{Reliable, Unreliable};

/// Possible data formats.
#[deriving(PartialEq, Eq, Show)]
pub enum Format {
    /// Process the text as-is.
    Text,
    /// Try to stip HTML tags and expand entities.
    Html
}

/// Is the output of the language decoder reliable?
#[deriving(PartialEq, Eq, Show)]
pub enum Reliability {
    /// The decoder is reasonably confident about this guess.
    Reliable,
    /// The decoder does not have high confidence in this guess.
    Unreliable
}

impl Reliability {
    /// Construct from a boolean value.
    pub fn from_bool(is_reliable: bool) -> Reliability {
        if is_reliable { Reliable } else { Unreliable }
    }
}

/// A language code, normally two letters for common languages.
#[deriving(PartialEq, Eq, Show)]
pub struct Lang(pub &'static str);

/// Hints to the decoder, which it will use to make better guesses.
///
/// ```
/// use std::default::Default;
/// use cld2::Hints;
///
/// // Specify just one hint.
/// let hints = Hints{content_language: Some("en"),
///                   .. Default::default()};
/// assert_eq!(Some("en"), hints.content_language);
/// assert_eq!(None, hints.tld);
/// ```
#[deriving(Show, Default)]
pub struct Hints<'a> {
    /// A value from an HTTP Content-Language header.  The value "fr,en"
    /// will bias the decoder towards French and English.
    pub content_language: Option<&'a str>,

    /// The top-level domain associated with this text.  The value "fr"
    /// will bias the decoder towards French.
    pub tld: Option<&'a str>,

    /// The original encoding of the text, before it was converted to
    /// UTF-8.  See `Encoding` for legal values.
    #[experimental]
    pub encoding: Option<Encoding>,

    /// An extra language hint.
    pub language: Option<Lang>
}

/// Detailed information about how well the input text matched a specific
/// language.
pub struct LanguageScore {
    /// The language matched.
    pub language: Option<Lang>,

    /// The percentage of the text which appears to be in this language.
    /// Between 0 and 100.
    pub percent: u8,

    /// Scores near 1.0 indicate a "normal" text for this language.  Scores
    /// further away from 1.0 indicated strange or atypical texts.
    pub normalized_score: f64
}

/// Detailed language detection results.
///
/// Note: Do not rely on this struct containing only the fields listed
/// below.  It may gain extra fields in the future.
pub struct DetectionResult {
    /// The language detected.
    pub language: Option<Lang>,

    /// The scores for the top 3 candidate languages.
    pub scores: [LanguageScore, ..3],

    /// The number of bytes of actual text found, excluding tags, etc.
    pub text_bytes: i32,

    /// Is this guess reliable?
    pub reliability: Reliability,

    /// A private field to keep the user from being able to construct
    /// instances directly, so we can extend this struct without breaking
    /// the API.  There's probably a better way to do this.
    _dummy: ()
}

impl DetectionResult {
    /// Create a new DetectionResult.  You generally don't need to call
    /// this directly.
    #[experimental]
    pub fn new(language: Option<Lang>, scores: [LanguageScore, ..3],
               text_bytes: i32, reliability: Reliability) -> DetectionResult {
        DetectionResult{language: language, scores: scores,
                        text_bytes: text_bytes, reliability: reliability,
                        _dummy: ()}
    }
}
<|endoftext|>


<commit_before>//! Basic types and their methods for linear algebra

use ndarray::LinalgScalar;
use num_complex::Complex;
use num_traits::*;
use rand::Rng;
use rand::distributions::*;
use std::fmt::Debug;
use std::iter::Sum;

use super::lapack_traits::LapackScalar;

pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;

/// General Scalar trait. This generalizes complex and real number.
///
/// You can use the following operations with `A: Scalar`:
///
/// - [abs](trait.Absolute.html#method.abs)
/// - [squared](trait.Absolute.html#tymethod.squared)
/// - [sqrt](trait.SquareRoot.html#tymethod.sqrt)
/// - [exp](trait.Exponential.html#tymethod.exp)
/// - [conj](trait.Conjugate.html#tymethod.conj)
/// - [randn](trait.RandNormal.html#tymethod.randn)
///
pub trait Scalar
    : LapackScalar
    + LinalgScalar
    + AssociatedReal
    + AssociatedComplex
    + Absolute
    + SquareRoot
    + Exponential
    + Conjugate
    + RandNormal
    + Debug {
}

impl Scalar for f32 {}
impl Scalar for f64 {}
impl Scalar for c32 {}
impl Scalar for c64 {}

pub trait RealScalar: Scalar + Float + Sum {}

impl RealScalar for f32 {}
impl RealScalar for f64 {}

/// Define associating real float type
pub trait AssociatedReal: Sized {
    type Real: RealScalar;
    fn inject(Self::Real) -> Self;
    fn add_real(self, Self::Real) -> Self;
    fn sub_real(self, Self::Real) -> Self;
    fn mul_real(self, Self::Real) -> Self;
    fn div_real(self, Self::Real) -> Self;
}

/// Define associating complex type
pub trait AssociatedComplex: Sized {
    type Complex;
    fn inject(Self) -> Self::Complex;
    fn add_complex(self, Self::Complex) -> Self::Complex;
    fn sub_complex(self, Self::Complex) -> Self::Complex;
    fn mul_complex(self, Self::Complex) -> Self::Complex;
}

/// Define `abs()` more generally
pub trait Absolute: AssociatedReal {
    fn squared(&self) -> Self::Real;
    fn abs(&self) -> Self::Real {
        self.squared().sqrt()
    }
}

/// Define `sqrt()` more generally
pub trait SquareRoot {
    fn sqrt(&self) -> Self;
}

/// Define `exp()` more generally
pub trait Exponential {
    fn exp(&self) -> Self;
}

/// Complex conjugate value
pub trait Conjugate: Copy {
    fn conj(self) -> Self;
}

/// Scalars which can be initialized from Gaussian random number
pub trait RandNormal {
    fn randn<R: Rng>(&mut R) -> Self;
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { r }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedReal for $complex {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { Self::new(r, 0.0) }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedComplex for $real {
    type Complex = $complex;
    fn inject(r: Self) -> Self::Complex { Self::Complex::new(r, 0.0) }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
    fn inject(c: Self) -> Self::Complex { c }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl Absolute for $real {
    fn squared(&self) -> Self::Real {
        *self * *self
    }
    fn abs(&self) -> Self::Real{
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    fn squared(&self) -> Self::Real {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Real {
        self.norm()
    }
}

impl SquareRoot for $real {
    fn sqrt(&self) -> Self {
        Float::sqrt(*self)
    }
}

impl SquareRoot for $complex {
    fn sqrt(&self) -> Self {
        Complex::sqrt(self)
    }
}

impl Exponential for $real {
    fn exp(&self) -> Self {
        Float::exp(*self)
    }
}

impl Exponential for $complex {
    fn exp(&self) -> Self {
        Complex::exp(self)
    }
}

impl Conjugate for $real {
    fn conj(self) -> Self {
        self
    }
}

impl Conjugate for $complex {
    fn conj(self) -> Self {
        Complex::conj(&self)
    }
}

impl RandNormal for $real {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        dist.ind_sample(rng) as $real
    }
}

impl RandNormal for $complex {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        let re = dist.ind_sample(rng) as $real;
        let im = dist.ind_sample(rng) as $real;
        Self::new(re, im)
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<commit_msg>Add from_f64, into_real<commit_after>//! Basic types and their methods for linear algebra

use ndarray::LinalgScalar;
use num_complex::Complex;
use num_traits::*;
use rand::Rng;
use rand::distributions::*;
use std::fmt::Debug;
use std::iter::Sum;

use super::lapack_traits::LapackScalar;

pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;

/// General Scalar trait. This generalizes complex and real number.
///
/// You can use the following operations with `A: Scalar`:
///
/// - [abs](trait.Absolute.html#method.abs)
/// - [squared](trait.Absolute.html#tymethod.squared)
/// - [sqrt](trait.SquareRoot.html#tymethod.sqrt)
/// - [exp](trait.Exponential.html#tymethod.exp)
/// - [conj](trait.Conjugate.html#tymethod.conj)
/// - [randn](trait.RandNormal.html#tymethod.randn)
///
pub trait Scalar
    : LapackScalar
    + LinalgScalar
    + AssociatedReal
    + AssociatedComplex
    + Absolute
    + SquareRoot
    + Exponential
    + Conjugate
    + RandNormal
    + Debug {
}

impl Scalar for f32 {}
impl Scalar for f64 {}
impl Scalar for c32 {}
impl Scalar for c64 {}

pub trait RealScalar: Scalar + Float + Sum {
    fn from_f64(f64) -> Self;
}

impl RealScalar for f32 {
    fn from_f64(f: f64) -> Self {
        f as f32
    }
}
impl RealScalar for f64 {
    fn from_f64(f: f64) -> Self {
        f
    }
}

/// Convert `f64` into `RealScalar`
///
/// ```rust
/// fn mult2<A: RealScalar>(a: A) -> A {
///     a * into_real(2.0);
/// }
/// ```
pub fn into_real<T: RealScalar>(f: f64) -> T {
    T::from_f64(f)
}

/// Define associating real float type
pub trait AssociatedReal: Sized {
    type Real: RealScalar;
    fn inject(Self::Real) -> Self;
    fn add_real(self, Self::Real) -> Self;
    fn sub_real(self, Self::Real) -> Self;
    fn mul_real(self, Self::Real) -> Self;
    fn div_real(self, Self::Real) -> Self;
}

/// Define associating complex type
pub trait AssociatedComplex: Sized {
    type Complex;
    fn inject(Self) -> Self::Complex;
    fn add_complex(self, Self::Complex) -> Self::Complex;
    fn sub_complex(self, Self::Complex) -> Self::Complex;
    fn mul_complex(self, Self::Complex) -> Self::Complex;
}

/// Define `abs()` more generally
pub trait Absolute: AssociatedReal {
    fn squared(&self) -> Self::Real;
    fn abs(&self) -> Self::Real {
        self.squared().sqrt()
    }
}

/// Define `sqrt()` more generally
pub trait SquareRoot {
    fn sqrt(&self) -> Self;
}

/// Define `exp()` more generally
pub trait Exponential {
    fn exp(&self) -> Self;
}

/// Complex conjugate value
pub trait Conjugate: Copy {
    fn conj(self) -> Self;
}

/// Scalars which can be initialized from Gaussian random number
pub trait RandNormal {
    fn randn<R: Rng>(&mut R) -> Self;
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { r }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedReal for $complex {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { Self::new(r, 0.0) }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedComplex for $real {
    type Complex = $complex;
    fn inject(r: Self) -> Self::Complex { Self::Complex::new(r, 0.0) }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
    fn inject(c: Self) -> Self::Complex { c }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl Absolute for $real {
    fn squared(&self) -> Self::Real {
        *self * *self
    }
    fn abs(&self) -> Self::Real{
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    fn squared(&self) -> Self::Real {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Real {
        self.norm()
    }
}

impl SquareRoot for $real {
    fn sqrt(&self) -> Self {
        Float::sqrt(*self)
    }
}

impl SquareRoot for $complex {
    fn sqrt(&self) -> Self {
        Complex::sqrt(self)
    }
}

impl Exponential for $real {
    fn exp(&self) -> Self {
        Float::exp(*self)
    }
}

impl Exponential for $complex {
    fn exp(&self) -> Self {
        Complex::exp(self)
    }
}

impl Conjugate for $real {
    fn conj(self) -> Self {
        self
    }
}

impl Conjugate for $complex {
    fn conj(self) -> Self {
        Complex::conj(&self)
    }
}

impl RandNormal for $real {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        dist.ind_sample(rng) as $real
    }
}

impl RandNormal for $complex {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        let re = dist.ind_sample(rng) as $real;
        let im = dist.ind_sample(rng) as $real;
        Self::new(re, im)
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Runtime type information.

use translate::{FromGlib, ToGlib, from_glib};
use ffi as glib_ffi;
use gobject_ffi;

/// A GLib or GLib-based library type
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Type {
    /// An invalid `Type` used as error return value in some functions
    Invalid,
    /// The fundamental type corresponding to the unit type `()`
    Unit,
    /// The fundamental type corresponding to `i8`
    I8,
    /// The fundamental type corresponding to `u8`
    U8,
    /// The fundamental type corresponding to `bool`
    Bool,
    /// The fundamental type corresponding to `i32`
    I32,
    /// The fundamental type corresponding to `u32`
    U32,
    /// The fundamental type corresponding to C `long`
    ILong,
    /// The fundamental type corresponding to C `unsigned long`
    ULong,
    /// The fundamental type corresponding to `i64`
    I64,
    /// The fundamental type corresponding to `u64`
    U64,
    /// The fundamental type corresponding to `f32`
    F32,
    /// The fundamental type corresponding to `f64`
    F64,
    /// The fundamental type corresponding to `String`
    String,
    /// The fundamental type corresponding to a pointer
    Pointer,
    /// The fundamental type of GVariant
    Variant,
    /// The fundamental type from which all interfaces are derived
    BaseInterface,
    /// The fundamental type from which all enumeration types are derived
    BaseEnum,
    /// The fundamental type from which all flags types are derived
    BaseFlags,
    /// The fundamental type from which all boxed types are derived
    BaseBoxed,
    /// The fundamental type from which all `GParamSpec` types are derived
    BaseParamSpec,
    /// The fundamental type from which all objects are derived
    BaseObject,
    /// A non-fundamental type identified by value of type `usize`
    Other(usize),
}

/// Types that are supported by GLib dynamic typing.
pub trait StaticType {
    /// Returns the type identifier of `Self`.
    fn static_type() -> Type;
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a T {
    fn static_type() -> Type {
        T::static_type()
    }
}

macro_rules! builtin {
    ($name:ident, $val:ident) => {
        impl StaticType for $name {
            fn static_type() -> Type {
                Type::$val
            }
        }
    }
}

builtin!(bool, Bool);
builtin!(i8, I8);
builtin!(u8, U8);
builtin!(i32, I32);
builtin!(u32, U32);
builtin!(i64, I64);
builtin!(u64, U64);
builtin!(f32, F32);
builtin!(f64, F64);
builtin!(str, String);
builtin!(String, String);

pub trait InstanceType {
    fn instance_type(&self) -> Type;
}

#[inline]
pub fn instance_of<C: StaticType>(ptr: glib_ffi::gconstpointer) -> bool {
    unsafe {
        from_glib(
            gobject_ffi::g_type_check_instance_is_a(
                ptr as *mut _, <C as StaticType>::static_type().to_glib()))
    }
}

impl FromGlib<glib_ffi::GType> for Type {
    #[inline]
    fn from_glib(val: glib_ffi::GType) -> Type {
        use self::Type::*;
        match val {
            gobject_ffi::G_TYPE_INVALID => Invalid,
            gobject_ffi::G_TYPE_NONE => Unit,
            gobject_ffi::G_TYPE_INTERFACE => BaseInterface,
            gobject_ffi::G_TYPE_CHAR => I8,
            gobject_ffi::G_TYPE_UCHAR => U8,
            gobject_ffi::G_TYPE_BOOLEAN => Bool,
            gobject_ffi::G_TYPE_INT => I32,
            gobject_ffi::G_TYPE_UINT => U32,
            gobject_ffi::G_TYPE_LONG => ILong,
            gobject_ffi::G_TYPE_ULONG => ULong,
            gobject_ffi::G_TYPE_INT64 => I64,
            gobject_ffi::G_TYPE_UINT64 => U64,
            gobject_ffi::G_TYPE_ENUM => BaseEnum,
            gobject_ffi::G_TYPE_FLAGS => BaseFlags,
            gobject_ffi::G_TYPE_FLOAT => F32,
            gobject_ffi::G_TYPE_DOUBLE => F64,
            gobject_ffi::G_TYPE_STRING => String,
            gobject_ffi::G_TYPE_POINTER => Pointer,
            gobject_ffi::G_TYPE_BOXED => BaseBoxed,
            gobject_ffi::G_TYPE_PARAM => BaseParamSpec,
            gobject_ffi::G_TYPE_OBJECT => BaseObject,
            gobject_ffi::G_TYPE_VARIANT => Variant,
            x => Other(x as usize),
        }
    }
}

impl ToGlib for Type {
    type GlibType = glib_ffi::GType;

    fn to_glib(&self) -> glib_ffi::GType {
        use self::Type::*;
        match *self {
            Invalid => gobject_ffi::G_TYPE_INVALID,
            Unit => gobject_ffi::G_TYPE_NONE,
            BaseInterface => gobject_ffi::G_TYPE_INTERFACE,
            I8 => gobject_ffi::G_TYPE_CHAR,
            U8 => gobject_ffi::G_TYPE_UCHAR,
            Bool => gobject_ffi::G_TYPE_BOOLEAN,
            I32 => gobject_ffi::G_TYPE_INT,
            U32 => gobject_ffi::G_TYPE_UINT,
            ILong => gobject_ffi::G_TYPE_LONG,
            ULong => gobject_ffi::G_TYPE_ULONG,
            I64 => gobject_ffi::G_TYPE_INT64,
            U64 => gobject_ffi::G_TYPE_UINT64,
            BaseEnum => gobject_ffi::G_TYPE_ENUM,
            BaseFlags => gobject_ffi::G_TYPE_FLAGS,
            F32 => gobject_ffi::G_TYPE_FLOAT,
            F64 => gobject_ffi::G_TYPE_DOUBLE,
            String => gobject_ffi::G_TYPE_STRING,
            Pointer => gobject_ffi::G_TYPE_POINTER,
            BaseBoxed => gobject_ffi::G_TYPE_BOXED,
            BaseParamSpec => gobject_ffi::G_TYPE_PARAM,
            BaseObject => gobject_ffi::G_TYPE_OBJECT,
            Variant => gobject_ffi::G_TYPE_VARIANT,
            Other(x) => x as glib_ffi::GType,
        }
    }
}
<commit_msg>Implement Display/Debug for Type, and Type::name()<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Runtime type information.

use translate::{FromGlib, ToGlib, from_glib, from_glib_none};
use ffi as glib_ffi;
use gobject_ffi;

use std::fmt;

/// A GLib or GLib-based library type
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
    /// An invalid `Type` used as error return value in some functions
    Invalid,
    /// The fundamental type corresponding to the unit type `()`
    Unit,
    /// The fundamental type corresponding to `i8`
    I8,
    /// The fundamental type corresponding to `u8`
    U8,
    /// The fundamental type corresponding to `bool`
    Bool,
    /// The fundamental type corresponding to `i32`
    I32,
    /// The fundamental type corresponding to `u32`
    U32,
    /// The fundamental type corresponding to C `long`
    ILong,
    /// The fundamental type corresponding to C `unsigned long`
    ULong,
    /// The fundamental type corresponding to `i64`
    I64,
    /// The fundamental type corresponding to `u64`
    U64,
    /// The fundamental type corresponding to `f32`
    F32,
    /// The fundamental type corresponding to `f64`
    F64,
    /// The fundamental type corresponding to `String`
    String,
    /// The fundamental type corresponding to a pointer
    Pointer,
    /// The fundamental type of GVariant
    Variant,
    /// The fundamental type from which all interfaces are derived
    BaseInterface,
    /// The fundamental type from which all enumeration types are derived
    BaseEnum,
    /// The fundamental type from which all flags types are derived
    BaseFlags,
    /// The fundamental type from which all boxed types are derived
    BaseBoxed,
    /// The fundamental type from which all `GParamSpec` types are derived
    BaseParamSpec,
    /// The fundamental type from which all objects are derived
    BaseObject,
    /// A non-fundamental type identified by value of type `usize`
    Other(usize),
}

impl Type {
    pub fn name(&self) -> String {
        unsafe {
            from_glib_none(gobject_ffi::g_type_name(self.to_glib()))
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

/// Types that are supported by GLib dynamic typing.
pub trait StaticType {
    /// Returns the type identifier of `Self`.
    fn static_type() -> Type;
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a T {
    fn static_type() -> Type {
        T::static_type()
    }
}

macro_rules! builtin {
    ($name:ident, $val:ident) => {
        impl StaticType for $name {
            fn static_type() -> Type {
                Type::$val
            }
        }
    }
}

builtin!(bool, Bool);
builtin!(i8, I8);
builtin!(u8, U8);
builtin!(i32, I32);
builtin!(u32, U32);
builtin!(i64, I64);
builtin!(u64, U64);
builtin!(f32, F32);
builtin!(f64, F64);
builtin!(str, String);
builtin!(String, String);

pub trait InstanceType {
    fn instance_type(&self) -> Type;
}

#[inline]
pub fn instance_of<C: StaticType>(ptr: glib_ffi::gconstpointer) -> bool {
    unsafe {
        from_glib(
            gobject_ffi::g_type_check_instance_is_a(
                ptr as *mut _, <C as StaticType>::static_type().to_glib()))
    }
}

impl FromGlib<glib_ffi::GType> for Type {
    #[inline]
    fn from_glib(val: glib_ffi::GType) -> Type {
        use self::Type::*;
        match val {
            gobject_ffi::G_TYPE_INVALID => Invalid,
            gobject_ffi::G_TYPE_NONE => Unit,
            gobject_ffi::G_TYPE_INTERFACE => BaseInterface,
            gobject_ffi::G_TYPE_CHAR => I8,
            gobject_ffi::G_TYPE_UCHAR => U8,
            gobject_ffi::G_TYPE_BOOLEAN => Bool,
            gobject_ffi::G_TYPE_INT => I32,
            gobject_ffi::G_TYPE_UINT => U32,
            gobject_ffi::G_TYPE_LONG => ILong,
            gobject_ffi::G_TYPE_ULONG => ULong,
            gobject_ffi::G_TYPE_INT64 => I64,
            gobject_ffi::G_TYPE_UINT64 => U64,
            gobject_ffi::G_TYPE_ENUM => BaseEnum,
            gobject_ffi::G_TYPE_FLAGS => BaseFlags,
            gobject_ffi::G_TYPE_FLOAT => F32,
            gobject_ffi::G_TYPE_DOUBLE => F64,
            gobject_ffi::G_TYPE_STRING => String,
            gobject_ffi::G_TYPE_POINTER => Pointer,
            gobject_ffi::G_TYPE_BOXED => BaseBoxed,
            gobject_ffi::G_TYPE_PARAM => BaseParamSpec,
            gobject_ffi::G_TYPE_OBJECT => BaseObject,
            gobject_ffi::G_TYPE_VARIANT => Variant,
            x => Other(x as usize),
        }
    }
}

impl ToGlib for Type {
    type GlibType = glib_ffi::GType;

    fn to_glib(&self) -> glib_ffi::GType {
        use self::Type::*;
        match *self {
            Invalid => gobject_ffi::G_TYPE_INVALID,
            Unit => gobject_ffi::G_TYPE_NONE,
            BaseInterface => gobject_ffi::G_TYPE_INTERFACE,
            I8 => gobject_ffi::G_TYPE_CHAR,
            U8 => gobject_ffi::G_TYPE_UCHAR,
            Bool => gobject_ffi::G_TYPE_BOOLEAN,
            I32 => gobject_ffi::G_TYPE_INT,
            U32 => gobject_ffi::G_TYPE_UINT,
            ILong => gobject_ffi::G_TYPE_LONG,
            ULong => gobject_ffi::G_TYPE_ULONG,
            I64 => gobject_ffi::G_TYPE_INT64,
            U64 => gobject_ffi::G_TYPE_UINT64,
            BaseEnum => gobject_ffi::G_TYPE_ENUM,
            BaseFlags => gobject_ffi::G_TYPE_FLAGS,
            F32 => gobject_ffi::G_TYPE_FLOAT,
            F64 => gobject_ffi::G_TYPE_DOUBLE,
            String => gobject_ffi::G_TYPE_STRING,
            Pointer => gobject_ffi::G_TYPE_POINTER,
            BaseBoxed => gobject_ffi::G_TYPE_BOXED,
            BaseParamSpec => gobject_ffi::G_TYPE_PARAM,
            BaseObject => gobject_ffi::G_TYPE_OBJECT,
            Variant => gobject_ffi::G_TYPE_VARIANT,
            Other(x) => x as glib_ffi::GType,
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    error::ParseError,
    stream::buf_reader::{Buffer, Bufferless, CombineBuffer},
};

use std::{
    fmt,
    io::{self, Read},
    pin::Pin,
};

#[derive(Debug)]
pub enum Error<E, P> {
    Parse(E),
    Io { position: P, error: io::Error },
}

impl<'a, P> From<Error<crate::easy::Errors<u8, &'a [u8], P>, P>>
    for crate::easy::Errors<u8, &'a [u8], P>
where
    P: Ord + Clone,
{
    fn from(e: Error<crate::easy::Errors<u8, &'a [u8], P>, P>) -> Self {
        match e {
            Error::Parse(e) => e,
            Error::Io { position, error } => {
                crate::easy::Errors::from_error(position, crate::easy::Error::Other(error.into()))
            }
        }
    }
}

impl<E, P> std::error::Error for Error<E, P>
where
    E: std::error::Error,
    P: fmt::Display + fmt::Debug,
{
}

impl<E: fmt::Display, P: fmt::Display> fmt::Display for Error<E, P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Parse(e) => e.fmt(f),
            Error::Io { position: _, error } => error.fmt(f),
        }
    }
}

#[derive(Default)]
/// Used together with the `decode!` macro
pub struct Decoder<S, P, C = Buffer> {
    position: P,
    state: S,
    buffer: C,
    end_of_input: bool,
}

impl<S, P> Decoder<S, P, Buffer>
where
    P: Default,
    S: Default,
{
    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new() -> Self {
        Decoder::default()
    }

    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new_buffer() -> Self {
        Decoder::new()
    }
}

impl<S, P> Decoder<S, P, Bufferless>
where
    P: Default,
    S: Default,
{
    /// Constructs a new `Decoder` without an internal buffer. Requires the read instance to be
    /// wrapped with combine's [`BufReader`] instance to
    ///
    /// [`BufReader`]: super::buf_reader::BufReader
    pub fn new_bufferless() -> Self {
        Decoder::default()
    }
}

impl<S, P> Decoder<S, P> {
    pub fn buffer(&self) -> &[u8] {
        &self.buffer.0
    }
}

impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub fn advance<R>(&mut self, read: &mut R, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance(read, removed)
    }

    #[doc(hidden)]
    #[cfg(feature = "pin-project-lite")]
    pub fn advance_pin<R>(&mut self, read: Pin<&mut R>, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance_pin(read, removed);
    }

    pub fn position(&self) -> &P {
        &self.position
    }

    #[doc(hidden)]
    pub fn __inner(&mut self) -> (&mut S, &mut P, &C, bool) {
        (
            &mut self.state,
            &mut self.position,
            &self.buffer,
            self.end_of_input,
        )
    }
}

impl<S, P, C> Decoder<S, P, C>
where
    C: ,
{
    #[doc(hidden)]
    pub fn __before_parse<R>(&mut self, mut reader: R) -> io::Result<()>
    where
        R: Read,
        C: crate::stream::buf_reader::CombineSyncRead<R>,
    {
        if self.buffer.extend_buf_sync(&mut reader)? == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-02")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_02<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_02_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_02_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_03<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_03_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_03_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "futures-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_async<R>(&mut self, reader: Pin<&mut R>) -> io::Result<()>
    where
        R: futures_io_03::AsyncRead,
        C: crate::stream::buf_reader::CombineAsyncRead<R>,
    {
        let copied = self.buffer.extend_buf(reader).await?;

        if copied == 0 {
            self.end_of_input = true;
        }
        Ok(())
    }
}
<commit_msg>Fix warning<commit_after>use crate::{
    error::ParseError,
    stream::buf_reader::{Buffer, Bufferless, CombineBuffer},
};

use std::{
    fmt,
    io::{self, Read},
};

#[cfg(feature = "pin-project-lite")]
use std::pin::Pin;

#[derive(Debug)]
pub enum Error<E, P> {
    Parse(E),
    Io { position: P, error: io::Error },
}

impl<'a, P> From<Error<crate::easy::Errors<u8, &'a [u8], P>, P>>
    for crate::easy::Errors<u8, &'a [u8], P>
where
    P: Ord + Clone,
{
    fn from(e: Error<crate::easy::Errors<u8, &'a [u8], P>, P>) -> Self {
        match e {
            Error::Parse(e) => e,
            Error::Io { position, error } => {
                crate::easy::Errors::from_error(position, crate::easy::Error::Other(error.into()))
            }
        }
    }
}

impl<E, P> std::error::Error for Error<E, P>
where
    E: std::error::Error,
    P: fmt::Display + fmt::Debug,
{
}

impl<E: fmt::Display, P: fmt::Display> fmt::Display for Error<E, P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Parse(e) => e.fmt(f),
            Error::Io { position: _, error } => error.fmt(f),
        }
    }
}

#[derive(Default)]
/// Used together with the `decode!` macro
pub struct Decoder<S, P, C = Buffer> {
    position: P,
    state: S,
    buffer: C,
    end_of_input: bool,
}

impl<S, P> Decoder<S, P, Buffer>
where
    P: Default,
    S: Default,
{
    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new() -> Self {
        Decoder::default()
    }

    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new_buffer() -> Self {
        Decoder::new()
    }
}

impl<S, P> Decoder<S, P, Bufferless>
where
    P: Default,
    S: Default,
{
    /// Constructs a new `Decoder` without an internal buffer. Requires the read instance to be
    /// wrapped with combine's [`BufReader`] instance to
    ///
    /// [`BufReader`]: super::buf_reader::BufReader
    pub fn new_bufferless() -> Self {
        Decoder::default()
    }
}

impl<S, P> Decoder<S, P> {
    pub fn buffer(&self) -> &[u8] {
        &self.buffer.0
    }
}

impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub fn advance<R>(&mut self, read: &mut R, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance(read, removed)
    }

    #[doc(hidden)]
    #[cfg(feature = "pin-project-lite")]
    pub fn advance_pin<R>(&mut self, read: Pin<&mut R>, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance_pin(read, removed);
    }

    pub fn position(&self) -> &P {
        &self.position
    }

    #[doc(hidden)]
    pub fn __inner(&mut self) -> (&mut S, &mut P, &C, bool) {
        (
            &mut self.state,
            &mut self.position,
            &self.buffer,
            self.end_of_input,
        )
    }
}

impl<S, P, C> Decoder<S, P, C>
where
    C: ,
{
    #[doc(hidden)]
    pub fn __before_parse<R>(&mut self, mut reader: R) -> io::Result<()>
    where
        R: Read,
        C: crate::stream::buf_reader::CombineSyncRead<R>,
    {
        if self.buffer.extend_buf_sync(&mut reader)? == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-02")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_02<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_02_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_02_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_03<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_03_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_03_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "futures-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_async<R>(&mut self, reader: Pin<&mut R>) -> io::Result<()>
    where
        R: futures_io_03::AsyncRead,
        C: crate::stream::buf_reader::CombineAsyncRead<R>,
    {
        let copied = self.buffer.extend_buf(reader).await?;

        if copied == 0 {
            self.end_of_input = true;
        }
        Ok(())
    }
}
<|endoftext|>