<commit_before>use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::str;

use ansi_term::Style;
use ansi_term::Colour::{Red, Yellow};

use parser;
#[derive(Debug)]
pub enum ProcessingError {
    ParseError(parser::ParseError),
    IoError(io::Error),
}

impl From<io::Error> for ProcessingError {
    fn from(from: io::Error) -> Self {
        ProcessingError::IoError(from)
    }
}

impl From<parser::ParseError> for ProcessingError {
    fn from(from: parser::ParseError) -> Self {
        ProcessingError::ParseError(from)
    }
}

pub fn get_error_and_line_for_file(parse_error: &parser::ParseError,
                                   file_name: &str)
                                   -> (parser::ParseError, String) {
    let mut parse_error = parse_error.clone();
    let mut buf_reader = io::BufReader::new(File::open(file_name).unwrap());
    let mut line = buf_reader.by_ref().lines().nth(parse_error.line - 1);

    let line_content;

    // error was in last line which was empty
    if line.is_none() {
        parse_error.line -= 1;
        buf_reader.seek(io::SeekFrom::Start(0)).unwrap();
        // more helpful to point to end of previous line
        line = buf_reader.lines().nth(parse_error.line - 1);
        line_content = line.unwrap().unwrap();
        parse_error.column = line_content.len() + 1;
    } else {
        line_content = line.unwrap().unwrap();
    }
    (parse_error, line_content)
}

pub fn print_parse_error(file_name: &str, line_content: &str, parse_error: &parser::ParseError) {
    println!("{}: {}: line {}, col {}: expected one of {:?}",
             Style::new().bold().paint((*file_name).to_owned()),
             Red.bold().paint("parse error"),
             parse_error.line,
             parse_error.column,
             parse_error.expected);
    println!("{}", line_content);
    let mut pointer_string = String::from_utf8(vec![b' '; parse_error.column - 1]).unwrap();
    pointer_string.push('^');
    println!("{}", Style::new().bold().paint(pointer_string));
}

use ast::OffsetSpan;

#[derive(Debug)]
pub struct SourceSpan {
    pub start_line: usize,
    pub start_col: usize,
    pub end_line: usize,
    pub end_col: usize,
}

pub fn offset_span_to_source_span(span: OffsetSpan, input: &str) -> SourceSpan {
    let (start_line, start_col) = offset_to_line_and_col(input, span.0);
    let (end_line, end_col) = offset_to_line_and_col(input, span.1 - 1);
    SourceSpan {
        start_line: start_line,
        start_col: start_col,
        end_line: end_line,
        end_col: end_col,
    }
}

fn offset_to_line_and_col(input: &str, pos: usize) -> (usize, usize) {
    let mut remaining = pos;
    let mut line_num: usize = 1;
    for line in input.lines() {
        let line_length = line.len() + 1;
        if remaining < line_length {
            return (line_num, remaining + 1);
        }
        remaining -= line_length;
        line_num += 1;
    }
    (line_num, remaining + 1)
}

use runtime::RuntimeError;
use typechecker::TypeCheckerIssue;

fn adjust_source_span(span: &mut SourceSpan, file_content: &str) {
    if (span.start_line != span.end_line) && span.end_col == 1 {
        span.end_col = 0;
    }
    while (span.end_col == 0) && span.end_line > span.start_line {
        span.end_line -= 1;
        span.end_col = file_content.lines().nth(span.end_line - 1).unwrap().len();
    }
}

pub fn print_interpreter_error_for_file(err: RuntimeError,
                                        span: SourceSpan,
                                        file_content: &str,
                                        file_name: &str) {
    print_typechecker_error_for_file(TypeCheckerIssue::RuntimeError(err),
                                     span,
                                     file_content,
                                     file_name);
}

pub fn print_typechecker_error_for_file(err: TypeCheckerIssue,
                                        span: SourceSpan,
                                        file_content: &str,
                                        file_name: &str) {
    let mut span = span;
    let mut error_to_print_after_this = None;
    adjust_source_span(&mut span, file_content);
    if span.start_line == span.end_line {
        println!("in {}, line {}, col {}:",
                 Style::new().bold().paint(file_name.to_string()),
                 span.start_line,
                 span.start_col);
    } else {
        println!("in {}, starting on line {}, col {}:",
                 Style::new().bold().paint(file_name.to_string()),
                 span.start_line,
                 span.start_col);
    }
    match err {
        TypeCheckerIssue::RuntimeError(e) => {
            match e {
                RuntimeError::ReferenceError(id) => {
                    println!("{}: `{}` was not declared",
                             Red.bold().paint("reference error"),
                             id);
                }
                RuntimeError::UndeclaredAssignment(id) => {
                    println!("{}: cannot assign to undeclared `{}`",
                             Red.bold().paint("reference error"),
                             id);
                }
                RuntimeError::BinaryTypeError(binary_op, type1, type2) => {
                    println!("{}: `{}` cannot operate on types {} and {}",
                             Red.bold().paint("type error"),
                             binary_op,
                             type1,
                             type2);
                }
                RuntimeError::UnaryTypeError(unary_op, typ) => {
                    println!("{}: `{}` cannot operate on type {}",
                             Red.bold().paint("type error"),
                             unary_op,
                             typ);
                }
                RuntimeError::NoneError(possible_id) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: tried to use return value of non-returning function \
                                      `{}`",
                                     Red.bold().paint("missing value error"),
                                     id);
                        }
                        None => {
                            println!("{}: tried to use return value of non-returning function",
                                     Red.bold().paint("missing value error"));
                        }
                    }
                }
                RuntimeError::CallToNonFunction(possible_id, other_type) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: cannot call `{}` ({}) as Function",
                                     Red.bold().paint("type error"),
                                     id,
                                     other_type);
                        }
                        None => {
                            println!("{}: cannot call {} as Function",
                                     Red.bold().paint("type error"),
                                     other_type);
                        }
                    }
                }
                RuntimeError::ArgumentLength(possible_id) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: function `{}` called with incorrect number of arguments",
                                     Red.bold().paint("arguments mismatch"),
                                     id);
                        }
                        None => {
                            println!("{}: function called with incorrect number of arguments",
                                     Red.bold().paint("arguments mismatch"));
                        }
                    }
                }
                RuntimeError::GeneralRuntimeError(message) => {
                    println!("{}: {}", Red.bold().paint("runtime error"), message);
                }
                RuntimeError::InsideFunctionCall(error_with_position) => {
                    println!("{}:", Red.bold().paint("error in function call"));
                    let unboxed_error_with_position = *error_with_position;
                    let (next_error, next_pos) = unboxed_error_with_position;
                    error_to_print_after_this = Some((TypeCheckerIssue::RuntimeError(next_error),
                                                      next_pos));
                }
                RuntimeError::IndexOutOfBounds(index) => {
                    println!("{}: index `{}` is out of bounds of the tuple",
                             Red.bold().paint("index of out bounds"),
                             index);
                }
                RuntimeError::SubscriptOnNonSubscriptable(typ) => {
                    println!("{}: cannot subscript type {}",
                             Red.bold().paint("type error"),
                             typ);
                }
                RuntimeError::NonIntegralSubscript(typ) => {
                    println!("{}: cannot use non-integral {:?} as subscript",
                             Red.bold().paint("non integral subscript"),
                             typ);
                }
            }
        }
        TypeCheckerIssue::MultipleTypesFromBranchWarning(id) => {
            println!("{}: `{}` gets different types in branches",
                     Style::new().bold().paint("multiple types from branch"),
                     id);
        }
        TypeCheckerIssue::InsideFunctionCall(issue_with_position) => {
            println!("{}:", Red.bold().paint("issue in function call"));
            error_to_print_after_this = Some(*issue_with_position);
        }
    }

    if span.start_line == span.end_line {
        let left_padding_size = span.start_line.to_string().len() + 3;
        println!("{} | {}",
                 span.start_line,
                 file_content.lines().nth(span.start_line - 1).unwrap());
        let left_padding = String::from_utf8(vec![b' '; span.start_col + left_padding_size - 1])
            .unwrap();
        let pointer_string = String::from_utf8(vec![b'^'; span.end_col + 1 - span.start_col])
            .unwrap();
        println!("{}{}", left_padding, Yellow.bold().paint(pointer_string));
    } else {
        let first_line_start_bytes = file_content.lines()
            .nth(span.start_line - 1)
            .unwrap()
            .bytes()
            .take(span.start_col - 1)
            .collect::<Vec<u8>>();
        let first_line_start_string = str::from_utf8(&first_line_start_bytes).unwrap();
        let first_line_rest_bytes = file_content.lines()
            .nth(span.start_line - 1)
            .unwrap()
            .bytes()
            .skip(span.start_col - 1)
            .collect::<Vec<u8>>();
        let first_line_rest_string = str::from_utf8(&first_line_rest_bytes).unwrap();

        let max_idx_width = span.end_line.to_string().len();

        println!("{line_num:width$} |", line_num = "", width = max_idx_width);

        println!("{line_num:width$} | {}{}",
                 first_line_start_string,
                 Red.bold().paint(first_line_rest_string),
                 line_num = span.start_line,
                 width = max_idx_width);

        for line_num in span.start_line..span.end_line - 1 {
            println!("{line_num:width$} | {}",
                     Red.bold().paint(file_content.lines().nth(line_num).unwrap()),
                     line_num = line_num + 1,
                     width = max_idx_width);
        }

        if span.end_col != 0 {
            let last_line_start_bytes = file_content.lines()
                .nth(span.end_line - 1)
                .unwrap()
                .bytes()
                .take(span.end_col)
                .collect::<Vec<u8>>();
            let last_line_start_string = str::from_utf8(&last_line_start_bytes).unwrap();
            let last_line_rest_bytes = file_content.lines()
                .nth(span.end_line - 1)
                .unwrap()
                .bytes()
                .skip(span.end_col)
                .collect::<Vec<u8>>();
            let last_line_rest_string = str::from_utf8(&last_line_rest_bytes).unwrap();
            println!("{line_num:width$} | {}{}",
                     Red.bold().paint(last_line_start_string),
                     last_line_rest_string,
                     line_num = span.end_line,
                     width = max_idx_width);
        }

        println!("{line_num:width$} |", line_num = "", width = max_idx_width);
    }
    if let Some(next_err) = error_to_print_after_this {
        let span = offset_span_to_source_span(next_err.1, &file_content);
        print_typechecker_error_for_file(next_err.0, span, file_content, file_name);
    }
}
<commit_msg>Improve error message slightly for InsideFunctionCall issues<commit_after>use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::str;

use ansi_term::Style;
use ansi_term::Colour::{Red, Yellow};

use parser;
#[derive(Debug)]
pub enum ProcessingError {
    ParseError(parser::ParseError),
    IoError(io::Error),
}

impl From<io::Error> for ProcessingError {
    fn from(from: io::Error) -> Self {
        ProcessingError::IoError(from)
    }
}

impl From<parser::ParseError> for ProcessingError {
    fn from(from: parser::ParseError) -> Self {
        ProcessingError::ParseError(from)
    }
}

pub fn get_error_and_line_for_file(parse_error: &parser::ParseError,
                                   file_name: &str)
                                   -> (parser::ParseError, String) {
    let mut parse_error = parse_error.clone();
    let mut buf_reader = io::BufReader::new(File::open(file_name).unwrap());
    let mut line = buf_reader.by_ref().lines().nth(parse_error.line - 1);

    let line_content;

    // error was in last line which was empty
    if line.is_none() {
        parse_error.line -= 1;
        buf_reader.seek(io::SeekFrom::Start(0)).unwrap();
        // more helpful to point to end of previous line
        line = buf_reader.lines().nth(parse_error.line - 1);
        line_content = line.unwrap().unwrap();
        parse_error.column = line_content.len() + 1;
    } else {
        line_content = line.unwrap().unwrap();
    }
    (parse_error, line_content)
}

pub fn print_parse_error(file_name: &str, line_content: &str, parse_error: &parser::ParseError) {
    println!("{}: {}: line {}, col {}: expected one of {:?}",
             Style::new().bold().paint((*file_name).to_owned()),
             Red.bold().paint("parse error"),
             parse_error.line,
             parse_error.column,
             parse_error.expected);
    println!("{}", line_content);
    let mut pointer_string = String::from_utf8(vec![b' '; parse_error.column - 1]).unwrap();
    pointer_string.push('^');
    println!("{}", Style::new().bold().paint(pointer_string));
}

use ast::OffsetSpan;

#[derive(Debug)]
pub struct SourceSpan {
    pub start_line: usize,
    pub start_col: usize,
    pub end_line: usize,
    pub end_col: usize,
}

pub fn offset_span_to_source_span(span: OffsetSpan, input: &str) -> SourceSpan {
    let (start_line, start_col) = offset_to_line_and_col(input, span.0);
    let (end_line, end_col) = offset_to_line_and_col(input, span.1 - 1);
    SourceSpan {
        start_line: start_line,
        start_col: start_col,
        end_line: end_line,
        end_col: end_col,
    }
}

fn offset_to_line_and_col(input: &str, pos: usize) -> (usize, usize) {
    let mut remaining = pos;
    let mut line_num: usize = 1;
    for line in input.lines() {
        let line_length = line.len() + 1;
        if remaining < line_length {
            return (line_num, remaining + 1);
        }
        remaining -= line_length;
        line_num += 1;
    }
    (line_num, remaining + 1)
}

use runtime::RuntimeError;
use typechecker::TypeCheckerIssue;

fn adjust_source_span(span: &mut SourceSpan, file_content: &str) {
    if (span.start_line != span.end_line) && span.end_col == 1 {
        span.end_col = 0;
    }
    while (span.end_col == 0) && span.end_line > span.start_line {
        span.end_line -= 1;
        span.end_col = file_content.lines().nth(span.end_line - 1).unwrap().len();
    }
}

pub fn print_interpreter_error_for_file(err: RuntimeError,
                                        span: SourceSpan,
                                        file_content: &str,
                                        file_name: &str) {
    print_typechecker_error_for_file(TypeCheckerIssue::RuntimeError(err),
                                     span,
                                     file_content,
                                     file_name);
}

pub fn print_typechecker_error_for_file(err: TypeCheckerIssue,
                                        span: SourceSpan,
                                        file_content: &str,
                                        file_name: &str) {
    let mut span = span;
    let mut error_to_print_after_this = None;
    adjust_source_span(&mut span, file_content);
    if span.start_line == span.end_line {
        println!("in {}, line {}, col {}:",
                 Style::new().bold().paint(file_name.to_string()),
                 span.start_line,
                 span.start_col);
    } else {
        println!("in {}, starting on line {}, col {}:",
                 Style::new().bold().paint(file_name.to_string()),
                 span.start_line,
                 span.start_col);
    }
    match err {
        TypeCheckerIssue::RuntimeError(e) => {
            match e {
                RuntimeError::ReferenceError(id) => {
                    println!("{}: `{}` was not declared",
                             Red.bold().paint("reference error"),
                             id);
                }
                RuntimeError::UndeclaredAssignment(id) => {
                    println!("{}: cannot assign to undeclared `{}`",
                             Red.bold().paint("reference error"),
                             id);
                }
                RuntimeError::BinaryTypeError(binary_op, type1, type2) => {
                    println!("{}: `{}` cannot operate on types {} and {}",
                             Red.bold().paint("type error"),
                             binary_op,
                             type1,
                             type2);
                }
                RuntimeError::UnaryTypeError(unary_op, typ) => {
                    println!("{}: `{}` cannot operate on type {}",
                             Red.bold().paint("type error"),
                             unary_op,
                             typ);
                }
                RuntimeError::NoneError(possible_id) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: tried to use return value of non-returning function \
                                      `{}`",
                                     Red.bold().paint("missing value error"),
                                     id);
                        }
                        None => {
                            println!("{}: tried to use return value of non-returning function",
                                     Red.bold().paint("missing value error"));
                        }
                    }
                }
                RuntimeError::CallToNonFunction(possible_id, other_type) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: cannot call `{}` ({}) as Function",
                                     Red.bold().paint("type error"),
                                     id,
                                     other_type);
                        }
                        None => {
                            println!("{}: cannot call {} as Function",
                                     Red.bold().paint("type error"),
                                     other_type);
                        }
                    }
                }
                RuntimeError::ArgumentLength(possible_id) => {
                    match possible_id {
                        Some(id) => {
                            println!("{}: function `{}` called with incorrect number of arguments",
                                     Red.bold().paint("arguments mismatch"),
                                     id);
                        }
                        None => {
                            println!("{}: function called with incorrect number of arguments",
                                     Red.bold().paint("arguments mismatch"));
                        }
                    }
                }
                RuntimeError::GeneralRuntimeError(message) => {
                    println!("{}: {}", Red.bold().paint("runtime error"), message);
                }
                RuntimeError::InsideFunctionCall(error_with_position) => {
                    println!("{}:", Red.bold().paint("error in function call"));
                    let unboxed_error_with_position = *error_with_position;
                    let (next_error, next_pos) = unboxed_error_with_position;
                    error_to_print_after_this = Some((TypeCheckerIssue::RuntimeError(next_error),
                                                      next_pos));
                }
                RuntimeError::IndexOutOfBounds(index) => {
                    println!("{}: index `{}` is out of bounds of the tuple",
                             Red.bold().paint("index of out bounds"),
                             index);
                }
                RuntimeError::SubscriptOnNonSubscriptable(typ) => {
                    println!("{}: cannot subscript type {}",
                             Red.bold().paint("type error"),
                             typ);
                }
                RuntimeError::NonIntegralSubscript(typ) => {
                    println!("{}: cannot use non-integral {:?} as subscript",
                             Red.bold().paint("non integral subscript"),
                             typ);
                }
            }
        }
        TypeCheckerIssue::MultipleTypesFromBranchWarning(id) => {
            println!("{}: `{}` gets different types in branches",
                     Style::new().bold().paint("multiple types from branch"),
                     id);
        }
        TypeCheckerIssue::InsideFunctionCall(issue_with_position) => {
            println!("{}:", Red.bold().paint("issue in function call"));
            error_to_print_after_this = Some(*issue_with_position);
        }
    }

    if span.start_line == span.end_line {
        let left_padding_size = span.start_line.to_string().len() + 3;
        println!("{} | {}",
                 span.start_line,
                 file_content.lines().nth(span.start_line - 1).unwrap());
        let left_padding = String::from_utf8(vec![b' '; span.start_col + left_padding_size - 1])
            .unwrap();
        let pointer_string = String::from_utf8(vec![b'^'; span.end_col + 1 - span.start_col])
            .unwrap();
        println!("{}{}", left_padding, Yellow.bold().paint(pointer_string));
    } else {
        let first_line_start_bytes = file_content.lines()
            .nth(span.start_line - 1)
            .unwrap()
            .bytes()
            .take(span.start_col - 1)
            .collect::<Vec<u8>>();
        let first_line_start_string = str::from_utf8(&first_line_start_bytes).unwrap();
        let first_line_rest_bytes = file_content.lines()
            .nth(span.start_line - 1)
            .unwrap()
            .bytes()
            .skip(span.start_col - 1)
            .collect::<Vec<u8>>();
        let first_line_rest_string = str::from_utf8(&first_line_rest_bytes).unwrap();

        let max_idx_width = span.end_line.to_string().len();

        println!("{line_num:width$} |", line_num = "", width = max_idx_width);

        println!("{line_num:width$} | {}{}",
                 first_line_start_string,
                 Red.bold().paint(first_line_rest_string),
                 line_num = span.start_line,
                 width = max_idx_width);

        for line_num in span.start_line..span.end_line - 1 {
            println!("{line_num:width$} | {}",
                     Red.bold().paint(file_content.lines().nth(line_num).unwrap()),
                     line_num = line_num + 1,
                     width = max_idx_width);
        }

        if span.end_col != 0 {
            let last_line_start_bytes = file_content.lines()
                .nth(span.end_line - 1)
                .unwrap()
                .bytes()
                .take(span.end_col)
                .collect::<Vec<u8>>();
            let last_line_start_string = str::from_utf8(&last_line_start_bytes).unwrap();
            let last_line_rest_bytes = file_content.lines()
                .nth(span.end_line - 1)
                .unwrap()
                .bytes()
                .skip(span.end_col)
                .collect::<Vec<u8>>();
            let last_line_rest_string = str::from_utf8(&last_line_rest_bytes).unwrap();
            println!("{line_num:width$} | {}{}",
                     Red.bold().paint(last_line_start_string),
                     last_line_rest_string,
                     line_num = span.end_line,
                     width = max_idx_width);
        }

        println!("{line_num:width$} |", line_num = "", width = max_idx_width);
    }
    if let Some(next_err) = error_to_print_after_this {
        let span = offset_span_to_source_span(next_err.1, &file_content);
        print_typechecker_error_for_file(next_err.0, span, file_content, &("function in ".to_owned() + file_name));
    }
}
<|endoftext|>


<commit_before>//! Process window events
use std::sync::{Arc, mpsc};
use std;

use glutin;

use input;
use sync::PriorityMutex;
use term::Term;
use tty::process_should_exit;

/// The event processor
pub struct Processor<'a, W: 'a> {
    writer: &'a mut W,
    input_processor: input::Processor,
    terminal: Arc<PriorityMutex<Term>>,
    resize_tx: mpsc::Sender<(u32, u32)>,
}

impl<'a, W> Processor<'a, W>
    where W: std::io::Write
{
    /// Create a new event processor
    ///
    /// Takes a writer which is expected to be hooked up to the write end of a
    /// pty.
    pub fn new(writer: &mut W,
               terminal: Arc<PriorityMutex<Term>>,
               resize_tx: mpsc::Sender<(u32, u32)>)
               -> Processor<W>
    {
        Processor {
            writer: writer,
            terminal: terminal,
            input_processor: input::Processor::new(),
            resize_tx: resize_tx,
        }
    }

    fn handle_event(&mut self, event: glutin::Event) {
        match event {
            glutin::Event::Closed => panic!("window closed"), // TODO ...
            glutin::Event::ReceivedCharacter(c) => {
                match c {
                    // Ignore BACKSPACE and DEL. These are handled specially.
                    '\u{8}' | '\u{7f}' => (),
                    // OSX arrow keys send invalid characters; ignore.
                    '\u{f700}' | '\u{f701}' | '\u{f702}' | '\u{f703}' => (),
                    _ => {
                        let encoded = c.encode_utf8();
                        self.writer.write(encoded.as_slice()).unwrap();
                    }
                }
            },
            glutin::Event::Resized(w, h) => {
                self.resize_tx.send((w, h)).expect("send new size");
            },
            glutin::Event::KeyboardInput(state, _code, key, mods) => {
                // Acquire term lock
                let terminal = self.terminal.lock_high();

                self.input_processor.process(state, key, mods,
                                             &mut input::WriteNotifier(self.writer),
                                             *terminal.mode());
            },
            _ => (),
        }
    }

    /// Process at least one event and handle any additional queued events.
    pub fn process_events(&mut self, window: &glutin::Window) {
        for event in window.wait_events() {
            self.handle_event(event);
            break;
        }

        for event in window.poll_events() {
            self.handle_event(event);
        }
    }
}
<commit_msg>Fix resize not redrawing immediately<commit_after>//! Process window events
use std::sync::{Arc, mpsc};
use std;

use glutin;

use input;
use sync::PriorityMutex;
use term::Term;
use tty::process_should_exit;

/// The event processor
pub struct Processor<'a, W: 'a> {
    writer: &'a mut W,
    input_processor: input::Processor,
    terminal: Arc<PriorityMutex<Term>>,
    resize_tx: mpsc::Sender<(u32, u32)>,
}

impl<'a, W> Processor<'a, W>
    where W: std::io::Write
{
    /// Create a new event processor
    ///
    /// Takes a writer which is expected to be hooked up to the write end of a
    /// pty.
    pub fn new(writer: &mut W,
               terminal: Arc<PriorityMutex<Term>>,
               resize_tx: mpsc::Sender<(u32, u32)>)
               -> Processor<W>
    {
        Processor {
            writer: writer,
            terminal: terminal,
            input_processor: input::Processor::new(),
            resize_tx: resize_tx,
        }
    }

    fn handle_event(&mut self, event: glutin::Event) {
        match event {
            glutin::Event::Closed => panic!("window closed"), // TODO ...
            glutin::Event::ReceivedCharacter(c) => {
                match c {
                    // Ignore BACKSPACE and DEL. These are handled specially.
                    '\u{8}' | '\u{7f}' => (),
                    // OSX arrow keys send invalid characters; ignore.
                    '\u{f700}' | '\u{f701}' | '\u{f702}' | '\u{f703}' => (),
                    _ => {
                        let encoded = c.encode_utf8();
                        self.writer.write(encoded.as_slice()).unwrap();
                    }
                }
            },
            glutin::Event::Resized(w, h) => {
                self.resize_tx.send((w, h)).expect("send new size");
                // Acquire term lock
                let mut terminal = self.terminal.lock_high();
                terminal.dirty = true;
            },
            glutin::Event::KeyboardInput(state, _code, key, mods) => {
                // Acquire term lock
                let terminal = self.terminal.lock_high();

                self.input_processor.process(state, key, mods,
                                             &mut input::WriteNotifier(self.writer),
                                             *terminal.mode());
            },
            _ => (),
        }
    }

    /// Process at least one event and handle any additional queued events.
    pub fn process_events(&mut self, window: &glutin::Window) {
        for event in window.wait_events() {
            self.handle_event(event);
            break;
        }

        for event in window.poll_events() {
            self.handle_event(event);
        }
    }
}
<|endoftext|>


<commit_before>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use sdl2;

/// A key code.
pub use sdl2::keyboard::Keycode;

/// A struct that holds the state of modifier buttons such as ctrl or shift.
pub use sdl2::keyboard::Mod;
/// A mouse button press.
pub use sdl2::mouse::MouseButton;
/// A struct containing the mouse state at a given instant.
pub use sdl2::mouse::MouseState;

/// A controller button.
pub use sdl2::controller::Button;
/// A controller axis.
pub use sdl2::controller::Axis;

/// The event iterator
pub use sdl2::event::EventPollIterator;
pub use sdl2::event::Event;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

use context::Context;
use GameResult;

pub use sdl2::keyboard::{CAPSMOD, LALTMOD, LCTRLMOD, LGUIMOD, LSHIFTMOD, MODEMOD, NOMOD, NUMMOD,
                         RALTMOD, RCTRLMOD, RESERVEDMOD, RGUIMOD, RSHIFTMOD};

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(
        &mut self,
        _ctx: &mut Context,
        _state: mouse::MouseState,
        _x: i32,
        _y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: i32, _y: i32) {}

    /// A keyboard button was pressed.
    fn key_down_event(&mut self, ctx: &mut Context, keycode: Keycode, _keymod: Mod, _repeat: bool) {
        if keycode == keyboard::Keycode::Escape {
            ctx.quit().expect("Should never fail");
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
    }

    /// Candidate text is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// https://wiki.libsdl.org/SDL_TextEditingEvent
    /// https://wiki.libsdl.org/SDL_TextInputEvent
    /// https://wiki.libsdl.org/Tutorials/TextInput
    fn text_editing_event(&mut self, _ctx: &mut Context, _text: String, _start: i32, _length: i32) {

    }

    /// Resulting text (usually a unicode character) is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// https://wiki.libsdl.org/SDL_TextEditingEvent
    /// https://wiki.libsdl.org/SDL_TextInputEvent
    /// https://wiki.libsdl.org/Tutorials/TextInput
    fn text_input_event(&mut self, _ctx: &mut Context, _text: String) {}

    /// A controller button was pressed; instance_id identifies which controller.
    fn controller_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: Button,
        _instance_id: i32,
    ) {
    }
    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _instance_id: i32) {}
    /// A controller axis moved.
    fn controller_axis_event(
        &mut self,
        _ctx: &mut Context,
        _axis: Axis,
        _value: i16,
        _instance_id: i32,
    ) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        println!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// A handle to access the OS's event pump.
pub struct Events(sdl2::EventPump);

use std::fmt;
impl fmt::Debug for Events {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Events: {:p}>", self)
    }
}

impl Events {
    /// Create a new Events object.
    pub fn new(ctx: &Context) -> GameResult<Events> {
        let e = ctx.sdl_context.event_pump()?;
        Ok(Events(e))
    }

    /// Get an iterator for all events.
    pub fn poll(&mut self) -> EventPollIterator {
        self.0.poll_iter()
    }
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, state: &mut S) -> GameResult<()>
where
    S: EventHandler,
{
    let mut event_pump = ctx.sdl_context.event_pump()?;

    let mut continuing = true;
    while continuing {
        ctx.timer_context.tick();

        for event in event_pump.poll_iter() {
            ctx.process_event(&event);
            match event {
                Quit { .. } => {
                    continuing = state.quit_event(ctx);
                    // println!("Quit event: {:?}", t);
                }
                KeyDown {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_down_event(ctx, key, keymod, repeat)
                    }
                }
                KeyUp {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_up_event(ctx, key, keymod, repeat)
                    }
                }
                TextEditing {
                    text,
                    start,
                    length,
                    ..
                } => state.text_editing_event(ctx, text, start, length),
                TextInput { text, .. } => state.text_input_event(ctx, text),
                MouseButtonDown {
                    mouse_btn, x, y, ..
                } => state.mouse_button_down_event(ctx, mouse_btn, x, y),
                MouseButtonUp {
                    mouse_btn, x, y, ..
                } => state.mouse_button_up_event(ctx, mouse_btn, x, y),
                MouseMotion {
                    mousestate,
                    x,
                    y,
                    xrel,
                    yrel,
                    ..
                } => {
                    state.mouse_motion_event(ctx, mousestate, x, y, xrel, yrel);
                }
                MouseWheel { x, y, .. } => state.mouse_wheel_event(ctx, x, y),
                ControllerButtonDown { button, which, .. } => {
                    state.controller_button_down_event(ctx, button, which)
                }
                ControllerButtonUp { button, which, .. } => {
                    state.controller_button_up_event(ctx, button, which)
                }
                ControllerAxisMotion {
                    axis, value, which, ..
                } => state.controller_axis_event(ctx, axis, value, which),
                Window {
                    win_event: event::WindowEvent::FocusGained,
                    ..
                } => state.focus_event(ctx, true),
                Window {
                    win_event: event::WindowEvent::FocusLost,
                    ..
                } => state.focus_event(ctx, false),
                Window {
                    win_event: event::WindowEvent::Resized(w, h),
                    ..
                } => {
                    state.resize_event(ctx, w as u32, h as u32);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<commit_msg>#316: Fix cargo doc warnings<commit_after>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to do this, you can write your own mainloop and
//! get the necessary event machinery by calling
//! `context.sdl_context.event_pump()` on your `Context`.  You can
//! then call whatever SDL event methods you want on that.  This is
//! not particularly elegant and is not guaranteed to be stable across
//! different versions of ggez (for instance, we may someday get rid of SDL2),
//! but trying to wrap it
//! up more conveniently really ends up with the exact same interface.
//!
//! See the `eventloop` example for an implementation.

use sdl2;

/// A key code.
pub use sdl2::keyboard::Keycode;

/// A struct that holds the state of modifier buttons such as ctrl or shift.
pub use sdl2::keyboard::Mod;
/// A mouse button press.
pub use sdl2::mouse::MouseButton;
/// A struct containing the mouse state at a given instant.
pub use sdl2::mouse::MouseState;

/// A controller button.
pub use sdl2::controller::Button;
/// A controller axis.
pub use sdl2::controller::Axis;

/// The event iterator
pub use sdl2::event::EventPollIterator;
pub use sdl2::event::Event;

use sdl2::event::Event::*;
use sdl2::event;
use sdl2::mouse;
use sdl2::keyboard;

use context::Context;
use GameResult;

pub use sdl2::keyboard::{CAPSMOD, LALTMOD, LCTRLMOD, LGUIMOD, LSHIFTMOD, MODEMOD, NOMOD, NUMMOD,
                         RALTMOD, RCTRLMOD, RESERVEDMOD, RGUIMOD, RSHIFTMOD};

/// A trait defining event callbacks; your primary interface with
/// `ggez`'s event loop.  Have a type implement this trait and
/// override at least the update() and draw() methods, then pass it to
/// `event::run()` to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// `key_down_event()`, which will by default exit the game if escape
/// is pressed.  Just override the methods you want to do things with.
pub trait EventHandler {
    /// Called upon each physics update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// `graphics::clear()` and end it with
    /// `graphics::present()` and `timer::yield_now()`
    fn draw(&mut self, _ctx: &mut Context) -> GameResult<()>;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: mouse::MouseButton,
        _x: i32,
        _y: i32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(
        &mut self,
        _ctx: &mut Context,
        _state: mouse::MouseState,
        _x: i32,
        _y: i32,
        _xrel: i32,
        _yrel: i32,
    ) {
    }

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: i32, _y: i32) {}

    /// A keyboard button was pressed.
    fn key_down_event(&mut self, ctx: &mut Context, keycode: Keycode, _keymod: Mod, _repeat: bool) {
        if keycode == keyboard::Keycode::Escape {
            ctx.quit().expect("Should never fail");
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: Keycode, _keymod: Mod, _repeat: bool) {
    }

    /// Candidate text is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_editing_event(&mut self, _ctx: &mut Context, _text: String, _start: i32, _length: i32) {

    }

    /// Resulting text (usually a unicode character) is passed by the OS (via Input Method Editor).
    /// Refer to:
    /// <https://wiki.libsdl.org/SDL_TextEditingEvent>
    /// <https://wiki.libsdl.org/SDL_TextInputEvent>
    /// <https://wiki.libsdl.org/Tutorials/TextInput>
    fn text_input_event(&mut self, _ctx: &mut Context, _text: String) {}

    /// A controller button was pressed; instance_id identifies which controller.
    fn controller_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: Button,
        _instance_id: i32,
    ) {
    }
    /// A controller button was released.
    fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _instance_id: i32) {}
    /// A controller axis moved.
    fn controller_axis_event(
        &mut self,
        _ctx: &mut Context,
        _axis: Axis,
        _value: i16,
        _instance_id: i32,
    ) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        println!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window.
    /// Is not called when you resize it yourself with
    /// `graphics::set_mode()` though.
    fn resize_event(&mut self, _ctx: &mut Context, _width: u32, _height: u32) {}
}

/// A handle to access the OS's event pump.
pub struct Events(sdl2::EventPump);

use std::fmt;
impl fmt::Debug for Events {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Events: {:p}>", self)
    }
}

impl Events {
    /// Create a new Events object.
    pub fn new(ctx: &Context) -> GameResult<Events> {
        let e = ctx.sdl_context.event_pump()?;
        Ok(Events(e))
    }

    /// Get an iterator for all events.
    pub fn poll(&mut self) -> EventPollIterator {
        self.0.poll_iter()
    }
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the `timer` module for more info.
pub fn run<S>(ctx: &mut Context, state: &mut S) -> GameResult<()>
where
    S: EventHandler,
{
    let mut event_pump = ctx.sdl_context.event_pump()?;

    let mut continuing = true;
    while continuing {
        ctx.timer_context.tick();

        for event in event_pump.poll_iter() {
            ctx.process_event(&event);
            match event {
                Quit { .. } => {
                    continuing = state.quit_event(ctx);
                    // println!("Quit event: {:?}", t);
                }
                KeyDown {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_down_event(ctx, key, keymod, repeat)
                    }
                }
                KeyUp {
                    keycode,
                    keymod,
                    repeat,
                    ..
                } => {
                    if let Some(key) = keycode {
                        state.key_up_event(ctx, key, keymod, repeat)
                    }
                }
                TextEditing {
                    text,
                    start,
                    length,
                    ..
                } => state.text_editing_event(ctx, text, start, length),
                TextInput { text, .. } => state.text_input_event(ctx, text),
                MouseButtonDown {
                    mouse_btn, x, y, ..
                } => state.mouse_button_down_event(ctx, mouse_btn, x, y),
                MouseButtonUp {
                    mouse_btn, x, y, ..
                } => state.mouse_button_up_event(ctx, mouse_btn, x, y),
                MouseMotion {
                    mousestate,
                    x,
                    y,
                    xrel,
                    yrel,
                    ..
                } => {
                    state.mouse_motion_event(ctx, mousestate, x, y, xrel, yrel);
                }
                MouseWheel { x, y, .. } => state.mouse_wheel_event(ctx, x, y),
                ControllerButtonDown { button, which, .. } => {
                    state.controller_button_down_event(ctx, button, which)
                }
                ControllerButtonUp { button, which, .. } => {
                    state.controller_button_up_event(ctx, button, which)
                }
                ControllerAxisMotion {
                    axis, value, which, ..
                } => state.controller_axis_event(ctx, axis, value, which),
                Window {
                    win_event: event::WindowEvent::FocusGained,
                    ..
                } => state.focus_event(ctx, true),
                Window {
                    win_event: event::WindowEvent::FocusLost,
                    ..
                } => state.focus_event(ctx, false),
                Window {
                    win_event: event::WindowEvent::Resized(w, h),
                    ..
                } => {
                    state.resize_event(ctx, w as u32, h as u32);
                }
                _ => {}
            }
        }
        state.update(ctx)?;
        state.draw(ctx)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to use `ggez`'s built in event loop, you can
//! write your own mainloop and check for events on your own.  This is
//! not particularly hard, there's nothing special about the
//! `EventHandler` trait.  It just tries to simplify the process a
//! little.  For examples of how to write your own main loop, see the
//! source code for this module, or the [`eventloop`
//! example](https://github.com/ggez/ggez/blob/master/examples/eventloop.rs).

use winit::{self, dpi};

/// A mouse button.
pub use winit::event::MouseButton;

/// An analog axis of some device (gamepad thumbstick, joystick...).
pub use gilrs::Axis;
/// A button of some device (gamepad, joystick...).
pub use gilrs::Button;

/// `winit` events; nested in a module for re-export neatness.
pub mod winit_event {
    pub use super::winit::event::{
        DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, MouseScrollDelta,
        TouchPhase, WindowEvent,
    };
}
pub use crate::input::gamepad::GamepadId;
pub use crate::input::keyboard::{KeyCode, KeyMods};

use self::winit_event::*;
/// `winit` event loop.
pub use winit::event_loop::{ControlFlow, EventLoop};

use crate::context::Context;
use crate::error::GameResult;

/// A trait defining event callbacks.  This is your primary interface with
/// `ggez`'s event loop.  Implement this trait for a type and
/// override at least the [`update()`](#tymethod.update) and
/// [`draw()`](#tymethod.draw) methods, then pass it to
/// [`event::run()`](fn.run.html) to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// [`key_down_event()`](#tymethod.key_down_event), which will by
/// default exit the game if the escape key is pressed.  Just
/// override the methods you want to use.
pub trait EventHandler {
    /// Called upon each logic update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// [`graphics::clear()`](../graphics/fn.clear.html) and end it
    /// with [`graphics::present()`](../graphics/fn.present.html) and
    /// maybe [`timer::yield_now()`](../timer/fn.yield_now.html).
    fn draw(&mut self, _ctx: &mut Context) -> GameResult;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32, _dx: f32, _dy: f32) {}

    /// mouse entered or left window area
    fn mouse_enter_or_leave(&mut self, _ctx: &mut Context, _entered: bool) {}

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32) {}

    /// A keyboard button was pressed.
    ///
    /// The default implementation of this will call `ggez::event::quit()`
    /// when the escape key is pressed.  If you override this with
    /// your own event handler you have to re-implment that
    /// functionality yourself.
    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
    ) {
        if keycode == KeyCode::Escape {
            quit(ctx);
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: KeyCode, _keymods: KeyMods) {}

    /// A unicode character was received, usually from keyboard input.
    /// This is the intended way of facilitating text input.
    fn text_input_event(&mut self, _ctx: &mut Context, _character: char) {}

    /// A gamepad button was pressed; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_button_down_event(&mut self, _ctx: &mut Context, _btn: Button, _id: GamepadId) {}

    /// A gamepad button was released; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _id: GamepadId) {}

    /// A gamepad axis moved; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_axis_event(&mut self, _ctx: &mut Context, _axis: Axis, _value: f32, _id: GamepadId) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit (the quit event is cancelled).
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        debug!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window, or when it is resized
    /// via [`graphics::set_mode()`](../graphics/fn.set_mode.html).
    fn resize_event(&mut self, _ctx: &mut Context, _width: f32, _height: f32) {}
}

/// Terminates the [`ggez::event::run()`](fn.run.html) loop by setting
/// [`Context.continuing`](struct.Context.html#structfield.continuing)
/// to `false`.
pub fn quit(ctx: &mut Context) {
    ctx.continuing = false;
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the [`timer`](../timer/index.html) module for more info.
pub fn run<S: 'static>(mut ctx: Context, event_loop: EventLoop<()>, mut state: S) -> !
where
    S: EventHandler,
{
    use crate::input::{keyboard, mouse};

    event_loop.run(move |event, _, control_flow| {
        if !ctx.continuing {
            *control_flow = ControlFlow::Exit;
            return;
        }

        *control_flow = ControlFlow::Poll;

        let ctx = &mut ctx;
        let state = &mut state;

        process_event(ctx, &event);
        match event {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::Resized(logical_size) => {
                    // let actual_size = logical_size;
                    state.resize_event(ctx, logical_size.width as f32, logical_size.height as f32);
                }
                WindowEvent::CloseRequested => {
                    if !state.quit_event(ctx) {
                        quit(ctx);
                    }
                }
                WindowEvent::Focused(gained) => {
                    state.focus_event(ctx, gained);
                }
                WindowEvent::ReceivedCharacter(ch) => {
                    state.text_input_event(ctx, ch);
                }
                WindowEvent::ModifiersChanged(mods) => {
                    ctx.keyboard_context.set_modifiers(KeyMods::from(mods))
                }
                WindowEvent::KeyboardInput {
                    input:
                        KeyboardInput {
                            state: ElementState::Pressed,
                            virtual_keycode: Some(keycode),
                            ..
                        },
                    ..
                } => {
                    let repeat = keyboard::is_key_repeated(ctx);
                    state.key_down_event(ctx, keycode, ctx.keyboard_context.active_mods(), repeat);
                }
                WindowEvent::KeyboardInput {
                    input:
                        KeyboardInput {
                            state: ElementState::Released,
                            virtual_keycode: Some(keycode),
                            ..
                        },
                    ..
                } => {
                    state.key_up_event(ctx, keycode, ctx.keyboard_context.active_mods());
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let (x, y) = match delta {
                        MouseScrollDelta::LineDelta(x, y) => (x, y),
                        MouseScrollDelta::PixelDelta(pos) => {
                            let scale_factor = ctx.gfx_context.window.window().scale_factor();
                            let dpi::LogicalPosition { x, y } = pos.to_logical::<f32>(scale_factor);
                            (x, y)
                        }
                    };
                    state.mouse_wheel_event(ctx, x, y);
                }
                WindowEvent::MouseInput {
                    state: element_state,
                    button,
                    ..
                } => {
                    let position = mouse::position(ctx);
                    match element_state {
                        ElementState::Pressed => {
                            state.mouse_button_down_event(ctx, button, position.x, position.y)
                        }
                        ElementState::Released => {
                            state.mouse_button_up_event(ctx, button, position.x, position.y)
                        }
                    }
                }
                WindowEvent::CursorMoved { .. } => {
                    let position = mouse::position(ctx);
                    let delta = mouse::delta(ctx);
                    state.mouse_motion_event(ctx, position.x, position.y, delta.x, delta.y);
                }
                _x => {
                    // trace!("ignoring window event {:?}", x);
                }
            },
            Event::DeviceEvent { .. } => (),
            Event::Resumed => (),
            Event::Suspended => (),
            Event::NewEvents(_) => (),
            Event::UserEvent(_) => (),
            Event::MainEventsCleared => {
                // If you are writing your own event loop, make sure
                // you include `timer_context.tick()` and
                // `ctx.process_event()` calls.  These update ggez's
                // internal state however necessary.
                ctx.timer_context.tick();

                // Handle gamepad events if necessary.
                if ctx.conf.modules.gamepad {
                    while let Some(gilrs::Event { id, event, .. }) =
                        ctx.gamepad_context.next_event()
                    {
                        match event {
                            gilrs::EventType::ButtonPressed(button, _) => {
                                state.gamepad_button_down_event(ctx, button, GamepadId(id));
                            }
                            gilrs::EventType::ButtonReleased(button, _) => {
                                state.gamepad_button_up_event(ctx, button, GamepadId(id));
                            }
                            gilrs::EventType::AxisChanged(axis, value, _) => {
                                state.gamepad_axis_event(ctx, axis, value, GamepadId(id));
                            }
                            _ => {}
                        }
                    }
                }

                if let Err(e) = state.update(ctx) {
                    error!("Error on EventHandler::update(): {:?}", e);
                    eprintln!("Error on EventHandler::update(): {:?}", e);
                    *control_flow = ControlFlow::Exit;
                    return;
                }

                if let Err(e) = state.draw(ctx) {
                    error!("Error on EventHandler::draw(): {:?}", e);
                    eprintln!("Error on EventHandler::draw(): {:?}", e);
                    *control_flow = ControlFlow::Exit;
                    return;
                }
            }
            Event::RedrawRequested(_) => (),
            Event::RedrawEventsCleared => (),
            Event::LoopDestroyed => (),
        }
    })
}

/// Feeds an `Event` into the `Context` so it can update any internal
/// state it needs to, such as detecting window resizes.  If you are
/// rolling your own event loop, you should call this on the events
/// you receive before processing them yourself.
pub fn process_event(ctx: &mut Context, event: &winit::event::Event<()>) {
    match event {
        winit_event::Event::WindowEvent { event, .. } => match event {
            winit_event::WindowEvent::Resized(physical_size) => {
                ctx.gfx_context.window.resize(*physical_size);
                ctx.gfx_context.resize_viewport();
            }
            winit_event::WindowEvent::CursorMoved {
                position: logical_position,
                ..
            } => {
                ctx.mouse_context
                    .set_last_position(crate::graphics::Point2::new(
                        logical_position.x as f32,
                        logical_position.y as f32,
                    ));
            }
            winit_event::WindowEvent::MouseInput { button, state, .. } => {
                let pressed = match state {
                    winit_event::ElementState::Pressed => true,
                    winit_event::ElementState::Released => false,
                };
                ctx.mouse_context.set_button(*button, pressed);
            }
            winit_event::WindowEvent::ModifiersChanged(mods) => ctx
                .keyboard_context
                .set_modifiers(crate::input::keyboard::KeyMods::from(*mods)),
            winit_event::WindowEvent::KeyboardInput {
                input:
                    winit::event::KeyboardInput {
                        state,
                        virtual_keycode: Some(keycode),
                        ..
                    },
                ..
            } => {
                let pressed = match state {
                    winit_event::ElementState::Pressed => true,
                    winit_event::ElementState::Released => false,
                };
                ctx.keyboard_context.set_key(*keycode, pressed);
            }
            winit_event::WindowEvent::ScaleFactorChanged { .. } => {
                // Nope.
            }
            _ => (),
        },
        winit_event::Event::DeviceEvent {
            event: winit_event::DeviceEvent::MouseMotion { delta: (x, y) },
            ..
        } => ctx
            .mouse_context
            .set_last_delta(crate::graphics::Point2::new(*x as f32, *y as f32)),

        _ => (),
    };
}
<commit_msg>made sure that windows don't get resized when ScaleFactorChanged is called;<commit_after>//! The `event` module contains traits and structs to actually run your game mainloop
//! and handle top-level state, as well as handle input events such as keyboard
//! and mouse.
//!
//! If you don't want to use `ggez`'s built in event loop, you can
//! write your own mainloop and check for events on your own.  This is
//! not particularly hard, there's nothing special about the
//! `EventHandler` trait.  It just tries to simplify the process a
//! little.  For examples of how to write your own main loop, see the
//! source code for this module, or the [`eventloop`
//! example](https://github.com/ggez/ggez/blob/master/examples/eventloop.rs).

use winit::{self, dpi};

/// A mouse button.
pub use winit::event::MouseButton;

/// An analog axis of some device (gamepad thumbstick, joystick...).
pub use gilrs::Axis;
/// A button of some device (gamepad, joystick...).
pub use gilrs::Button;

/// `winit` events; nested in a module for re-export neatness.
pub mod winit_event {
    pub use super::winit::event::{
        DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, MouseScrollDelta,
        TouchPhase, WindowEvent,
    };
}
pub use crate::input::gamepad::GamepadId;
pub use crate::input::keyboard::{KeyCode, KeyMods};

use self::winit_event::*;
/// `winit` event loop.
pub use winit::event_loop::{ControlFlow, EventLoop};

use crate::context::Context;
use crate::error::GameResult;

/// A trait defining event callbacks.  This is your primary interface with
/// `ggez`'s event loop.  Implement this trait for a type and
/// override at least the [`update()`](#tymethod.update) and
/// [`draw()`](#tymethod.draw) methods, then pass it to
/// [`event::run()`](fn.run.html) to run the game's mainloop.
///
/// The default event handlers do nothing, apart from
/// [`key_down_event()`](#tymethod.key_down_event), which will by
/// default exit the game if the escape key is pressed.  Just
/// override the methods you want to use.
pub trait EventHandler {
    /// Called upon each logic update to the game.
    /// This should be where the game's logic takes place.
    fn update(&mut self, _ctx: &mut Context) -> GameResult;

    /// Called to do the drawing of your game.
    /// You probably want to start this with
    /// [`graphics::clear()`](../graphics/fn.clear.html) and end it
    /// with [`graphics::present()`](../graphics/fn.present.html) and
    /// maybe [`timer::yield_now()`](../timer/fn.yield_now.html).
    fn draw(&mut self, _ctx: &mut Context) -> GameResult;

    /// A mouse button was pressed
    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// A mouse button was released
    fn mouse_button_up_event(
        &mut self,
        _ctx: &mut Context,
        _button: MouseButton,
        _x: f32,
        _y: f32,
    ) {
    }

    /// The mouse was moved; it provides both absolute x and y coordinates in the window,
    /// and relative x and y coordinates compared to its last position.
    fn mouse_motion_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32, _dx: f32, _dy: f32) {}

    /// mouse entered or left window area
    fn mouse_enter_or_leave(&mut self, _ctx: &mut Context, _entered: bool) {}

    /// The mousewheel was scrolled, vertically (y, positive away from and negative toward the user)
    /// or horizontally (x, positive to the right and negative to the left).
    fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32) {}

    /// A keyboard button was pressed.
    ///
    /// The default implementation of this will call `ggez::event::quit()`
    /// when the escape key is pressed.  If you override this with
    /// your own event handler you have to re-implment that
    /// functionality yourself.
    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
    ) {
        if keycode == KeyCode::Escape {
            quit(ctx);
        }
    }

    /// A keyboard button was released.
    fn key_up_event(&mut self, _ctx: &mut Context, _keycode: KeyCode, _keymods: KeyMods) {}

    /// A unicode character was received, usually from keyboard input.
    /// This is the intended way of facilitating text input.
    fn text_input_event(&mut self, _ctx: &mut Context, _character: char) {}

    /// A gamepad button was pressed; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_button_down_event(&mut self, _ctx: &mut Context, _btn: Button, _id: GamepadId) {}

    /// A gamepad button was released; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _id: GamepadId) {}

    /// A gamepad axis moved; `id` identifies which gamepad.
    /// Use [`input::gamepad()`](../input/fn.gamepad.html) to get more info about
    /// the gamepad.
    fn gamepad_axis_event(&mut self, _ctx: &mut Context, _axis: Axis, _value: f32, _id: GamepadId) {
    }

    /// Called when the window is shown or hidden.
    fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit (the quit event is cancelled).
    fn quit_event(&mut self, _ctx: &mut Context) -> bool {
        debug!("quit_event() callback called, quitting...");
        false
    }

    /// Called when the user resizes the window, or when it is resized
    /// via [`graphics::set_mode()`](../graphics/fn.set_mode.html).
    fn resize_event(&mut self, _ctx: &mut Context, _width: f32, _height: f32) {}
}

/// Terminates the [`ggez::event::run()`](fn.run.html) loop by setting
/// [`Context.continuing`](struct.Context.html#structfield.continuing)
/// to `false`.
pub fn quit(ctx: &mut Context) {
    ctx.continuing = false;
}

/// Runs the game's main loop, calling event callbacks on the given state
/// object as events occur.
///
/// It does not try to do any type of framerate limiting.  See the
/// documentation for the [`timer`](../timer/index.html) module for more info.
pub fn run<S: 'static>(mut ctx: Context, event_loop: EventLoop<()>, mut state: S) -> !
where
    S: EventHandler,
{
    use crate::input::{keyboard, mouse};

    event_loop.run(move |mut event, _, control_flow| {
        if !ctx.continuing {
            *control_flow = ControlFlow::Exit;
            return;
        }

        *control_flow = ControlFlow::Poll;

        let ctx = &mut ctx;
        let state = &mut state;

        process_event(ctx, &mut event);
        match event {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::Resized(logical_size) => {
                    // let actual_size = logical_size;
                    state.resize_event(ctx, logical_size.width as f32, logical_size.height as f32);
                }
                WindowEvent::CloseRequested => {
                    if !state.quit_event(ctx) {
                        quit(ctx);
                    }
                }
                WindowEvent::Focused(gained) => {
                    state.focus_event(ctx, gained);
                }
                WindowEvent::ReceivedCharacter(ch) => {
                    state.text_input_event(ctx, ch);
                }
                WindowEvent::ModifiersChanged(mods) => {
                    ctx.keyboard_context.set_modifiers(KeyMods::from(mods))
                }
                WindowEvent::KeyboardInput {
                    input:
                        KeyboardInput {
                            state: ElementState::Pressed,
                            virtual_keycode: Some(keycode),
                            ..
                        },
                    ..
                } => {
                    let repeat = keyboard::is_key_repeated(ctx);
                    state.key_down_event(ctx, keycode, ctx.keyboard_context.active_mods(), repeat);
                }
                WindowEvent::KeyboardInput {
                    input:
                        KeyboardInput {
                            state: ElementState::Released,
                            virtual_keycode: Some(keycode),
                            ..
                        },
                    ..
                } => {
                    state.key_up_event(ctx, keycode, ctx.keyboard_context.active_mods());
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let (x, y) = match delta {
                        MouseScrollDelta::LineDelta(x, y) => (x, y),
                        MouseScrollDelta::PixelDelta(pos) => {
                            let scale_factor = ctx.gfx_context.window.window().scale_factor();
                            let dpi::LogicalPosition { x, y } = pos.to_logical::<f32>(scale_factor);
                            (x, y)
                        }
                    };
                    state.mouse_wheel_event(ctx, x, y);
                }
                WindowEvent::MouseInput {
                    state: element_state,
                    button,
                    ..
                } => {
                    let position = mouse::position(ctx);
                    match element_state {
                        ElementState::Pressed => {
                            state.mouse_button_down_event(ctx, button, position.x, position.y)
                        }
                        ElementState::Released => {
                            state.mouse_button_up_event(ctx, button, position.x, position.y)
                        }
                    }
                }
                WindowEvent::CursorMoved { .. } => {
                    let position = mouse::position(ctx);
                    let delta = mouse::delta(ctx);
                    state.mouse_motion_event(ctx, position.x, position.y, delta.x, delta.y);
                }
                _x => {
                    // trace!("ignoring window event {:?}", x);
                }
            },
            Event::DeviceEvent { .. } => (),
            Event::Resumed => (),
            Event::Suspended => (),
            Event::NewEvents(_) => (),
            Event::UserEvent(_) => (),
            Event::MainEventsCleared => {
                // If you are writing your own event loop, make sure
                // you include `timer_context.tick()` and
                // `ctx.process_event()` calls.  These update ggez's
                // internal state however necessary.
                ctx.timer_context.tick();

                // Handle gamepad events if necessary.
                if ctx.conf.modules.gamepad {
                    while let Some(gilrs::Event { id, event, .. }) =
                        ctx.gamepad_context.next_event()
                    {
                        match event {
                            gilrs::EventType::ButtonPressed(button, _) => {
                                state.gamepad_button_down_event(ctx, button, GamepadId(id));
                            }
                            gilrs::EventType::ButtonReleased(button, _) => {
                                state.gamepad_button_up_event(ctx, button, GamepadId(id));
                            }
                            gilrs::EventType::AxisChanged(axis, value, _) => {
                                state.gamepad_axis_event(ctx, axis, value, GamepadId(id));
                            }
                            _ => {}
                        }
                    }
                }

                if let Err(e) = state.update(ctx) {
                    error!("Error on EventHandler::update(): {:?}", e);
                    eprintln!("Error on EventHandler::update(): {:?}", e);
                    *control_flow = ControlFlow::Exit;
                    return;
                }

                if let Err(e) = state.draw(ctx) {
                    error!("Error on EventHandler::draw(): {:?}", e);
                    eprintln!("Error on EventHandler::draw(): {:?}", e);
                    *control_flow = ControlFlow::Exit;
                    return;
                }
            }
            Event::RedrawRequested(_) => (),
            Event::RedrawEventsCleared => (),
            Event::LoopDestroyed => (),
        }
    })
}

/// Feeds an `Event` into the `Context` so it can update any internal
/// state it needs to, such as detecting window resizes.  If you are
/// rolling your own event loop, you should call this on the events
/// you receive before processing them yourself.
pub fn process_event(ctx: &mut Context, event: &mut winit::event::Event<()>) {
    match event {
        winit_event::Event::WindowEvent { event, .. } => match event {
            winit_event::WindowEvent::Resized(physical_size) => {
                ctx.gfx_context.window.resize(*physical_size);
                ctx.gfx_context.resize_viewport();
            }
            winit_event::WindowEvent::CursorMoved {
                position: logical_position,
                ..
            } => {
                ctx.mouse_context
                    .set_last_position(crate::graphics::Point2::new(
                        logical_position.x as f32,
                        logical_position.y as f32,
                    ));
            }
            winit_event::WindowEvent::MouseInput { button, state, .. } => {
                let pressed = match state {
                    winit_event::ElementState::Pressed => true,
                    winit_event::ElementState::Released => false,
                };
                ctx.mouse_context.set_button(*button, pressed);
            }
            winit_event::WindowEvent::ModifiersChanged(mods) => ctx
                .keyboard_context
                .set_modifiers(crate::input::keyboard::KeyMods::from(*mods)),
            winit_event::WindowEvent::KeyboardInput {
                input:
                    winit::event::KeyboardInput {
                        state,
                        virtual_keycode: Some(keycode),
                        ..
                    },
                ..
            } => {
                let pressed = match state {
                    winit_event::ElementState::Pressed => true,
                    winit_event::ElementState::Released => false,
                };
                ctx.keyboard_context.set_key(*keycode, pressed);
            }
            winit_event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
                // actively set the new_inner_size to be the current inner size
                // to stop winit from resizing our window
                **new_inner_size = ctx.gfx_context.window.window().inner_size();
            }
            _ => (),
        },
        winit_event::Event::DeviceEvent {
            event: winit_event::DeviceEvent::MouseMotion { delta: (x, y) },
            ..
        } => ctx
            .mouse_context
            .set_last_delta(crate::graphics::Point2::new(*x as f32, *y as f32)),

        _ => (),
    };
}
<|endoftext|>


<commit_before>
//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;

use super::{Handler, Session};

pub struct LocalHandler;

impl Handler for LocalHandler {
    type Sess = LocalSession;
    fn connect() -> io::Result<Self> { unimplemented!() }
    fn session(&self) -> LocalSession { unimplemented!() }
    fn disconnect(self) { unimplemented!() }
}

pub struct LocalSession;

impl Session for LocalSession {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        unimplemented!()
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        unimplemented!()
    }
}
<commit_msg>Implement types in `local` module<commit_after>
//
// FSUIPC library
// Copyright (c) 2015 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::ptr::null_mut;

use user32::FindWindowExA;
use winapi::windef::HWND;

use super::{Handle, Session};
use super::ipc::*;

pub struct LocalHandle {
    handle: HWND,
}

impl Handle for LocalHandle {
    type Sess = LocalSession;

    fn connect() -> io::Result<Self> {
        unsafe {
            let win_name = CString::new("UIPCMAIN").unwrap();
            let handle = FindWindowExA(
                null_mut(), null_mut(), win_name.as_ptr(), null_mut());
            if handle != null_mut() {
                Ok(LocalHandle { handle: handle })
            } else {
                Err(io::Error::new(
                    io::ErrorKind::ConnectionRefused,
                    "cannot connect to local FSUIPC: cannot create window handle"))
            }
        }
    }

    fn session(&self) -> LocalSession {
        LocalSession {
            handle: self.handle,
            buffer: io::Cursor::new(Vec::with_capacity(4096))
        }
    }

    fn disconnect(self) {}
}

pub struct LocalSession {
    handle: HWND,
    buffer: io::Cursor<Vec<u8>>,
}

impl Session for LocalSession {
    fn read_bytes(&mut self, offset: u16, dest: *mut u8, len: usize) -> io::Result<usize> {
        self.buffer.write_rsd(offset, dest, len)
    }

    fn write_bytes(&mut self, offset: u16, src: *const u8, len: usize) -> io::Result<usize> {
        self.buffer.write_wsd(offset, src, len)
    }
}
<|endoftext|>


<commit_before>//! Provides a way to link `AudioDevice`s into an acyclic graph.

use std::collections::VecDeque;

use types::{AudioDevice, Sample, Time};
use tick::Tick;

pub struct DeviceGraph {
    nodes: Vec<AudioNode>, // the actual nodes
    topology: Vec<usize>, // the order to tick the nodes
    bus: Vec<Sample>, // the audio bus to write samples to
    time: Time // the next timestep
}

impl DeviceGraph {
    pub fn new() -> DeviceGraph {
        DeviceGraph {
            nodes: Vec::new(),
            topology: Vec::new(),
            bus: Vec::new(),
            time: 0
        }
    }

    pub fn add_node<D>(&mut self, device: D) -> AudioNodeIdx
            where D: 'static+AudioDevice {
        let node = AudioNode::new(device, &mut self.bus);
        let idx = self.nodes.len();
        self.nodes.push(node);
        self.topology.push(idx);
        AudioNodeIdx(idx)
    }

    pub fn add_edge(&mut self, from: AudioNodeIdx, from_ch: usize,
                    to: AudioNodeIdx, to_ch: usize) -> Result<(), GraphError> {
        // Check device indices
        let AudioNodeIdx(from_i) = from;
        let AudioNodeIdx(to_i) = to;
        if from_i >= self.nodes.len() {
            return Err(GraphError::FromOutOfRange);
        } else if to_i >= self.nodes.len() {
            return Err(GraphError::ToOutOfRange);
        }

        // Check channels
        if self.nodes[from_i].device.num_outputs() <= from_ch {
            return Err(GraphError::FromChOutOfRange);
        }
        if self.nodes[to_i].device.num_inputs() <= to_ch {
            return Err(GraphError::ToChOutOfRange);
        }
        while self.nodes[to_i].inputs.len() < to_ch {
            self.nodes[to_i].inputs.push(None);
        }

        // Set input
        let (start,_) = self.nodes[from_i].outputs;
        self.nodes[to_i].inputs[to_ch] = Some(start+from_ch);
        self.topological_sort(to_i, to_ch)
    }

    /// Determines the topology of our device graph. If the graph has a cycle,
    /// then we remove the last edge. Otherwise, we set self.topology to
    /// a topologically sorted order.
    fn topological_sort(&mut self, to_i: usize, to_ch: usize) ->
            Result<(), GraphError> {
        // Intialize our set of input edges, and our set of edgeless nodes
        let mut topology = Vec::new();
        let mut inputs: Vec<Vec<_>> = self.nodes.iter().map(
            |node| node.inputs.iter().filter_map(|&o| o).collect()
        ).collect();
        let mut no_inputs: VecDeque<_> = inputs.iter().enumerate().filter_map(
            |(i, ins)| if ins.len() == 0 { Some(i) } else { None }
        ).collect();

        // While there are nodes with no input, we choose one, add it as the
        // next node in our topology, and remove all edges from that node. Any
        // nodes that lose their final edge are added to the edgeless set.
        loop {
            match no_inputs.pop_front() {
                Some(i) => {
                    topology.push(i);
                    let (out_start, out_end) = self.nodes[i].outputs;
                    for out in out_start..out_end {
                        for (j, ins) in inputs.iter_mut().enumerate() {
                            let mut idx = None;
                            for k in 0..ins.len() {
                                if ins[k] == out {
                                    idx = Some(k);
                                    break;
                                }
                            }
                            match idx {
                                Some(k) => {
                                    ins.swap_remove(k);
                                    if ins.len() == 0 {
                                        no_inputs.push_back(j);
                                    }
                                },
                                None => ()
                            }
                        }
                    }
                },
                None => break
            }
        }

        if topology.len() == self.nodes.len() {
            self.topology = topology;
            Ok(())
        } else {
            self.nodes[to_i].inputs[to_ch] = None;
            Err(GraphError::CreatesCycle)
        }
    }
}

impl Tick for DeviceGraph {
    fn tick(&mut self) {
        for &i in self.topology.iter() {
            let inputs: Vec<Sample> = self.nodes[i].inputs.iter().map(|input|
                input.map_or(0.0, |ch| self.bus[ch])).collect();
            let (start, end) = self.nodes[i].outputs;
            self.nodes[i].device.tick(self.time, &inputs,
                                        &mut self.bus[start..end]);
        }
        self.time += 1;
    }
}

#[derive(Copy, Clone, Debug)]
pub enum GraphError {
    FromOutOfRange, FromChOutOfRange, ToOutOfRange, ToChOutOfRange, CreatesCycle
}

#[derive(Copy, Clone, Debug)]
pub struct AudioNodeIdx(usize);

struct AudioNode {
    device: Box<AudioDevice>,
    inputs: Vec<Option<usize>>,
    outputs: (usize, usize)
}

impl AudioNode {
    fn new<D>(device: D, bus: &mut Vec<Sample>) -> AudioNode
            where D: 'static+AudioDevice {
        let num_in = device.num_inputs();
        let mut inputs = Vec::with_capacity(num_in);
        for _ in 0..num_in {
            inputs.push(None)
        }

        let num_out = device.num_outputs();
        let start = bus.len();
        for _ in 0..num_out {
            bus.push(0.0);
        }
        let end = bus.len();

        AudioNode {
            device: Box::new(device),
            inputs: inputs,
            outputs: (start, end)
        }
    }
}
<commit_msg>Remove allocation from graph tick<commit_after>//! Provides a way to link `AudioDevice`s into an acyclic graph.

use std::collections::VecDeque;

use types::{AudioDevice, Sample, Time};
use tick::Tick;

pub struct DeviceGraph {
    nodes: Vec<AudioNode>, // the actual nodes
    topology: Vec<usize>, // the order to tick the nodes
    bus: Vec<Sample>, // the audio bus to write samples to
    time: Time // the next timestep
}

impl DeviceGraph {
    pub fn new() -> DeviceGraph {
        DeviceGraph {
            nodes: Vec::new(),
            topology: Vec::new(),
            bus: Vec::new(),
            time: 0
        }
    }

    pub fn add_node<D>(&mut self, device: D) -> AudioNodeIdx
            where D: 'static+AudioDevice {
        let node = AudioNode::new(device, &mut self.bus);
        let idx = self.nodes.len();
        self.nodes.push(node);
        self.topology.push(idx);
        AudioNodeIdx(idx)
    }

    pub fn add_edge(&mut self, from: AudioNodeIdx, from_ch: usize,
                    to: AudioNodeIdx, to_ch: usize) -> Result<(), GraphError> {
        // Check device indices
        let AudioNodeIdx(from_i) = from;
        let AudioNodeIdx(to_i) = to;
        if from_i >= self.nodes.len() {
            return Err(GraphError::FromOutOfRange);
        } else if to_i >= self.nodes.len() {
            return Err(GraphError::ToOutOfRange);
        }

        // Check channels
        if self.nodes[from_i].device.num_outputs() <= from_ch {
            return Err(GraphError::FromChOutOfRange);
        }
        if self.nodes[to_i].device.num_inputs() <= to_ch {
            return Err(GraphError::ToChOutOfRange);
        }
        while self.nodes[to_i].inputs.len() < to_ch {
            self.nodes[to_i].inputs.push(None);
        }

        // Set input
        let (start,_) = self.nodes[from_i].outputs;
        self.nodes[to_i].inputs[to_ch] = Some(start+from_ch);
        self.topological_sort(to_i, to_ch)
    }

    /// Determines the topology of our device graph. If the graph has a cycle,
    /// then we remove the last edge. Otherwise, we set self.topology to
    /// a topologically sorted order.
    fn topological_sort(&mut self, to_i: usize, to_ch: usize) ->
            Result<(), GraphError> {
        // Intialize our set of input edges, and our set of edgeless nodes
        let mut topology = Vec::new();
        let mut inputs: Vec<Vec<_>> = self.nodes.iter().map(
            |node| node.inputs.iter().filter_map(|&o| o).collect()
        ).collect();
        let mut no_inputs: VecDeque<_> = inputs.iter().enumerate().filter_map(
            |(i, ins)| if ins.len() == 0 { Some(i) } else { None }
        ).collect();

        // While there are nodes with no input, we choose one, add it as the
        // next node in our topology, and remove all edges from that node. Any
        // nodes that lose their final edge are added to the edgeless set.
        loop {
            match no_inputs.pop_front() {
                Some(i) => {
                    topology.push(i);
                    let (out_start, out_end) = self.nodes[i].outputs;
                    for out in out_start..out_end {
                        for (j, ins) in inputs.iter_mut().enumerate() {
                            let mut idx = None;
                            for k in 0..ins.len() {
                                if ins[k] == out {
                                    idx = Some(k);
                                    break;
                                }
                            }
                            match idx {
                                Some(k) => {
                                    ins.swap_remove(k);
                                    if ins.len() == 0 {
                                        no_inputs.push_back(j);
                                    }
                                },
                                None => ()
                            }
                        }
                    }
                },
                None => break
            }
        }

        if topology.len() == self.nodes.len() {
            self.topology = topology;
            Ok(())
        } else {
            self.nodes[to_i].inputs[to_ch] = None;
            Err(GraphError::CreatesCycle)
        }
    }
}

impl Tick for DeviceGraph {
    fn tick(&mut self) {
        for &i in self.topology.iter() {
            self.nodes[i].tick(self.time, &mut self.bus);
        }
        self.time += 1;
    }
}

#[derive(Copy, Clone, Debug)]
pub enum GraphError {
    FromOutOfRange, FromChOutOfRange, ToOutOfRange, ToChOutOfRange, CreatesCycle
}

#[derive(Copy, Clone, Debug)]
pub struct AudioNodeIdx(usize);

struct AudioNode {
    device: Box<AudioDevice>,
    inputs: Vec<Option<usize>>,
    input_buf: Vec<Sample>,
    outputs: (usize, usize)
}

impl AudioNode {
    fn new<D>(device: D, bus: &mut Vec<Sample>) -> AudioNode
            where D: 'static+AudioDevice {
        let num_in = device.num_inputs();
        let mut inputs = Vec::with_capacity(num_in);
        let mut input_buf = Vec::with_capacity(num_in);
        for _ in 0..num_in {
            inputs.push(None);
            input_buf.push(0.0);
        }

        let num_out = device.num_outputs();
        let start = bus.len();
        for _ in 0..num_out {
            bus.push(0.0);
        }
        let end = bus.len();

        AudioNode {
            device: Box::new(device),
            inputs: inputs,
            input_buf: input_buf,
            outputs: (start, end)
        }
    }

    fn tick(&mut self, t: Time, bus: &mut[Sample]) {
        for (i, ch) in self.inputs.iter().enumerate() {
            self.input_buf[i] = ch.map_or(0.0, |j| bus[j]);
        }
        let (start, end) = self.outputs;
        self.device.tick(t, &self.input_buf, &mut bus[start..end]);
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl ListNode {
    fn new(i: i32) -> Self {
        ListNode { val: i, next: None }
    }

    //:= DEBUG: self point changed
    //:= https://stackoverflow.com/questions/50957738/how-to-copy-a-raw-pointer-in-rust?noredirect=1#comment88913158_50957738
    fn add_l(&mut self, l: &Vec<i32>) {
        //let mut p: *mut ListNode = self as *mut ListNode;
        let org = self;
        let mut p: *mut ListNode = org as *mut ListNode;

        for i in l {
            unsafe {
                //println!("{:?}", *p);
                (*p).next = Some(Box::new(ListNode::new(*i)));
                let temp_b = Box::from_raw(p);
                p = Box::into_raw(temp_b.next.unwrap());
            };
        }
    }

    fn add(&mut self, i: &i32) {
        self.next = Some(Box::new(ListNode::new(*i)));
    }

    fn add_head(self, i: i32) -> Self {
        ListNode {
            val: i,
            next: Some(Box::new(self)),
        }
    }

    fn new_l(l: Vec<i32>) -> Self {
        let mut inner_l = l;
        let mut temp = Self::new(*&inner_l.pop().unwrap());
        for i in inner_l.into_iter().rev() {
            temp = temp.add_head(i)
        }
        temp
    }

    fn removeNthFromEnd(&self, n: i32) {}
}
fn main() {
    //let mut a = ListNode::new(1);
    //a.add_l(&vec![2, 3, 4, 5]);

    let a = ListNode::new_l(vec![1, 2, 3, 4, 5]);
    println!("{:?}", a);
}
<commit_msg>a bit<commit_after>use std::rc::Rc;

#[derive(Debug, Clone)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl ListNode {
    fn new(i: i32) -> Self {
        ListNode { val: i, next: None }
    }

    //:= https://stackoverflow.com/questions/50957738/how-to-copy-a-raw-pointer-in-rust?noredirect=1#comment88913158_50957738
    /*
    fn add_l(&mut self, l: &Vec<i32>) {
        //let mut p: *mut ListNode = self as *mut ListNode;
        let org = self;
        let mut p: *mut ListNode = org as *mut ListNode;

        for i in l {
            unsafe {
                //println!("{:?}", *p);
                (*p).next = Some(Box::new(ListNode::new(*i)));
                let temp_b = Box::from_raw(p);
                p = Box::into_raw(temp_b.next.unwrap());
            };
        }
    }*/

    //https://stackoverflow.com/questions/50957738/how-to-copy-a-raw-pointer-when-implementing-a-linked-list-in-rust/50970414#50970414
    fn add_l(&mut self, l: &[i32]) {
        let mut head = self;

        for &val in l {
            head.next = Some(Box::new(ListNode::new(val)));
            head = { head }.next.as_mut().unwrap();
        }
    }

    fn add(&mut self, i: &i32) {
        self.next = Some(Box::new(ListNode::new(*i)));
    }

    fn add_head(self, i: i32) -> Self {
        ListNode {
            val: i,
            next: Some(Box::new(self)),
        }
    }

    fn new_l(l: Vec<i32>) -> Self {
        let mut inner_l = l;
        let mut temp = Self::new(*&inner_l.pop().unwrap());
        for i in inner_l.into_iter().rev() {
            temp = temp.add_head(i)
        }
        temp
    }

    fn removeNthFromEnd(&mut self, n: i32) {
        //let mut head_1 = { self }.next.as_ref().unwrap();
        let mut head_2 = { self }.next.as_ref().unwrap();
        let mut n_h = 0;

        for _ in 1..n {
            head_2 = { head_2 }.next.as_ref().unwrap();
        }

        while let Some(_) = { &head_2 }.next {
            //head_1 = { head_1 }.next.as_mut().unwrap();
            n_h += 1;
            head_2 = { head_2 }.next.as_ref().unwrap();
        }
    }
}
fn main() {
    //let mut a = ListNode::new(1);
    //a.add_l(&vec![2, 3, 4, 5]);

    let mut a = ListNode::new_l(vec![1, 2, 3, 4, 5]);
    a.removeNthFromEnd(1);
    println!("{:?}", a);
}
<|endoftext|>