<commit_before>// Copyright 2013-2014 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Data-driven tests

use std::ops::Deref;
use std::str::FromStr;

use serde_json::Value;
use url::{quirks, Url};

#[test]
fn urltestdata() {
    // Copied form https://github.com/w3c/web-platform-tests/blob/master/url/
    let mut json = Value::from_str(include_str!("urltestdata.json"))
        .expect("JSON parse error in urltestdata.json");

    let mut passed = true;
    for entry in json.as_array_mut().unwrap() {
        if entry.is_string() {
            continue; // ignore comments
        }

        let base = entry.take_string("base");
        let input = entry.take_string("input");
        let failure = entry.take_key("failure").is_some();

        let base = match Url::parse(&base) {
            Ok(base) => base,
            Err(_) if failure => continue,
            Err(message) => {
                eprint_failure(
                    format!("  failed: error parsing base {:?}: {}", base, message),
                    &format!("parse base for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
        };

        let url = match (base.join(&input), failure) {
            (Ok(url), false) => url,
            (Err(_), true) => continue,
            (Err(message), false) => {
                eprint_failure(
                    format!("  failed: {}", message),
                    &format!("parse URL for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
            (Ok(_), true) => {
                eprint_failure(
                    format!("  failed: expected parse error for URL {:?}", input),
                    &format!("parse URL for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
        };

        passed &= check_invariants(&url, &format!("invariants for {:?}", input), None);

        for &attr in ATTRIBS {
            passed &= test_eq_eprint(
                entry.take_string(attr),
                get(&url, attr),
                &format!("{:?} - {}", input, attr),
                None,
            );
        }

        if let Some(expected_origin) = entry.take_key("origin").map(|s| s.string()) {
            passed &= test_eq_eprint(
                expected_origin,
                &quirks::origin(&url),
                &format!("origin for {:?}", input),
                None,
            );
        }
    }

    assert!(passed)
}

#[allow(clippy::option_as_ref_deref)] // introduced in 1.40, MSRV is 1.36
#[test]
fn setters_tests() {
    let mut json = Value::from_str(include_str!("setters_tests.json"))
        .expect("JSON parse error in setters_tests.json");

    let mut passed = true;
    for &attr in ATTRIBS {
        if attr == "href" {
            continue;
        }

        let mut tests = json.take_key(attr).unwrap();
        for mut test in tests.as_array_mut().unwrap().drain(..) {
            let comment = test.take_key("comment").map(|s| s.string());
            let href = test.take_string("href");
            let new_value = test.take_string("new_value");
            let name = format!("{:?}.{} = {:?}", href, attr, new_value);
            let mut expected = test.take_key("expected").unwrap();

            let mut url = Url::parse(&href).unwrap();
            let comment_ref = comment.as_ref().map(|s| s.deref());
            passed &= check_invariants(&url, &name, comment_ref);
            let _ = set(&mut url, attr, &new_value);

            for attr in ATTRIBS {
                if let Some(value) = expected.take_key(attr) {
                    passed &= test_eq_eprint(value.string(), get(&url, attr), &name, comment_ref);
                };
            }

            passed &= check_invariants(&url, &name, comment_ref);
        }
    }

    assert!(passed);
}

fn check_invariants(url: &Url, name: &str, comment: Option<&str>) -> bool {
    let mut passed = true;
    if let Err(e) = url.check_invariants() {
        passed = false;
        eprint_failure(
            format!("  failed: invariants checked -> {:?}", e),
            name,
            comment,
        );
    }

    #[cfg(feature = "serde")]
    {
        let bytes = serde_json::to_vec(url).unwrap();
        let new_url: Url = serde_json::from_slice(&bytes).unwrap();
        passed &= test_eq(url, &new_url, name, comment);
    }

    passed
}

trait JsonExt {
    fn take_key(&mut self, key: &str) -> Option<Value>;
    fn string(self) -> String;
    fn take_string(&mut self, key: &str) -> String;
}

impl JsonExt for Value {
    fn take_key(&mut self, key: &str) -> Option<Value> {
        self.as_object_mut().unwrap().remove(key)
    }

    fn string(self) -> String {
        if let Value::String(s) = self {
            s
        } else {
            panic!("Not a Value::String")
        }
    }

    fn take_string(&mut self, key: &str) -> String {
        self.take_key(key).unwrap().string()
    }
}

fn get<'a>(url: &'a Url, attr: &str) -> &'a str {
    match attr {
        "href" => quirks::href(url),
        "protocol" => quirks::protocol(url),
        "username" => quirks::username(url),
        "password" => quirks::password(url),
        "hostname" => quirks::hostname(url),
        "host" => quirks::host(url),
        "port" => quirks::port(url),
        "pathname" => quirks::pathname(url),
        "search" => quirks::search(url),
        "hash" => quirks::hash(url),
        _ => unreachable!(),
    }
}

#[allow(clippy::unit_arg)]
fn set<'a>(url: &'a mut Url, attr: &str, new: &str) {
    let _ = match attr {
        "protocol" => quirks::set_protocol(url, new),
        "username" => quirks::set_username(url, new),
        "password" => quirks::set_password(url, new),
        "hostname" => quirks::set_hostname(url, new),
        "host" => quirks::set_host(url, new),
        "port" => quirks::set_port(url, new),
        "pathname" => Ok(quirks::set_pathname(url, new)),
        "search" => Ok(quirks::set_search(url, new)),
        "hash" => Ok(quirks::set_hash(url, new)),
        _ => unreachable!(),
    };
}

fn test_eq_eprint(expected: String, actual: &str, name: &str, comment: Option<&str>) -> bool {
    if expected == actual {
        return true;
    }
    eprint_failure(
        format!("expected: {}\n  actual: {}", expected, actual),
        name,
        comment,
    );
    false
}

fn eprint_failure(err: String, name: &str, comment: Option<&str>) {
    eprintln!("    test: {}\n{}", name, err);
    if let Some(comment) = comment {
        eprintln!("{}\n", comment);
    } else {
        eprintln!("");
    }
}

const ATTRIBS: &[&str] = &[
    "href", "protocol", "username", "password", "host", "hostname", "port", "pathname", "search",
    "hash",
];
<commit_msg>url: fix serde tests<commit_after>// Copyright 2013-2014 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Data-driven tests

use std::ops::Deref;
use std::str::FromStr;

use serde_json::Value;
use url::{quirks, Url};

#[test]
fn urltestdata() {
    // Copied form https://github.com/w3c/web-platform-tests/blob/master/url/
    let mut json = Value::from_str(include_str!("urltestdata.json"))
        .expect("JSON parse error in urltestdata.json");

    let mut passed = true;
    for entry in json.as_array_mut().unwrap() {
        if entry.is_string() {
            continue; // ignore comments
        }

        let base = entry.take_string("base");
        let input = entry.take_string("input");
        let failure = entry.take_key("failure").is_some();

        let base = match Url::parse(&base) {
            Ok(base) => base,
            Err(_) if failure => continue,
            Err(message) => {
                eprint_failure(
                    format!("  failed: error parsing base {:?}: {}", base, message),
                    &format!("parse base for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
        };

        let url = match (base.join(&input), failure) {
            (Ok(url), false) => url,
            (Err(_), true) => continue,
            (Err(message), false) => {
                eprint_failure(
                    format!("  failed: {}", message),
                    &format!("parse URL for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
            (Ok(_), true) => {
                eprint_failure(
                    format!("  failed: expected parse error for URL {:?}", input),
                    &format!("parse URL for {:?}", input),
                    None,
                );
                passed = false;
                continue;
            }
        };

        passed &= check_invariants(&url, &format!("invariants for {:?}", input), None);

        for &attr in ATTRIBS {
            passed &= test_eq_eprint(
                entry.take_string(attr),
                get(&url, attr),
                &format!("{:?} - {}", input, attr),
                None,
            );
        }

        if let Some(expected_origin) = entry.take_key("origin").map(|s| s.string()) {
            passed &= test_eq_eprint(
                expected_origin,
                &quirks::origin(&url),
                &format!("origin for {:?}", input),
                None,
            );
        }
    }

    assert!(passed)
}

#[allow(clippy::option_as_ref_deref)] // introduced in 1.40, MSRV is 1.36
#[test]
fn setters_tests() {
    let mut json = Value::from_str(include_str!("setters_tests.json"))
        .expect("JSON parse error in setters_tests.json");

    let mut passed = true;
    for &attr in ATTRIBS {
        if attr == "href" {
            continue;
        }

        let mut tests = json.take_key(attr).unwrap();
        for mut test in tests.as_array_mut().unwrap().drain(..) {
            let comment = test.take_key("comment").map(|s| s.string());
            let href = test.take_string("href");
            let new_value = test.take_string("new_value");
            let name = format!("{:?}.{} = {:?}", href, attr, new_value);
            let mut expected = test.take_key("expected").unwrap();

            let mut url = Url::parse(&href).unwrap();
            let comment_ref = comment.as_ref().map(|s| s.deref());
            passed &= check_invariants(&url, &name, comment_ref);
            let _ = set(&mut url, attr, &new_value);

            for attr in ATTRIBS {
                if let Some(value) = expected.take_key(attr) {
                    passed &= test_eq_eprint(value.string(), get(&url, attr), &name, comment_ref);
                };
            }

            passed &= check_invariants(&url, &name, comment_ref);
        }
    }

    assert!(passed);
}

fn check_invariants(url: &Url, name: &str, comment: Option<&str>) -> bool {
    let mut passed = true;
    if let Err(e) = url.check_invariants() {
        passed = false;
        eprint_failure(
            format!("  failed: invariants checked -> {:?}", e),
            name,
            comment,
        );
    }

    #[cfg(feature = "serde")]
    {
        let bytes = serde_json::to_vec(url).unwrap();
        let new_url: Url = serde_json::from_slice(&bytes).unwrap();
        passed &= test_eq_eprint(url.to_string(), &new_url.to_string(), name, comment);
    }

    passed
}

trait JsonExt {
    fn take_key(&mut self, key: &str) -> Option<Value>;
    fn string(self) -> String;
    fn take_string(&mut self, key: &str) -> String;
}

impl JsonExt for Value {
    fn take_key(&mut self, key: &str) -> Option<Value> {
        self.as_object_mut().unwrap().remove(key)
    }

    fn string(self) -> String {
        if let Value::String(s) = self {
            s
        } else {
            panic!("Not a Value::String")
        }
    }

    fn take_string(&mut self, key: &str) -> String {
        self.take_key(key).unwrap().string()
    }
}

fn get<'a>(url: &'a Url, attr: &str) -> &'a str {
    match attr {
        "href" => quirks::href(url),
        "protocol" => quirks::protocol(url),
        "username" => quirks::username(url),
        "password" => quirks::password(url),
        "hostname" => quirks::hostname(url),
        "host" => quirks::host(url),
        "port" => quirks::port(url),
        "pathname" => quirks::pathname(url),
        "search" => quirks::search(url),
        "hash" => quirks::hash(url),
        _ => unreachable!(),
    }
}

#[allow(clippy::unit_arg)]
fn set<'a>(url: &'a mut Url, attr: &str, new: &str) {
    let _ = match attr {
        "protocol" => quirks::set_protocol(url, new),
        "username" => quirks::set_username(url, new),
        "password" => quirks::set_password(url, new),
        "hostname" => quirks::set_hostname(url, new),
        "host" => quirks::set_host(url, new),
        "port" => quirks::set_port(url, new),
        "pathname" => Ok(quirks::set_pathname(url, new)),
        "search" => Ok(quirks::set_search(url, new)),
        "hash" => Ok(quirks::set_hash(url, new)),
        _ => unreachable!(),
    };
}

fn test_eq_eprint(expected: String, actual: &str, name: &str, comment: Option<&str>) -> bool {
    if expected == actual {
        return true;
    }
    eprint_failure(
        format!("expected: {}\n  actual: {}", expected, actual),
        name,
        comment,
    );
    false
}

fn eprint_failure(err: String, name: &str, comment: Option<&str>) {
    eprintln!("    test: {}\n{}", name, err);
    if let Some(comment) = comment {
        eprintln!("{}\n", comment);
    } else {
        eprintln!("");
    }
}

const ATTRIBS: &[&str] = &[
    "href", "protocol", "username", "password", "host", "hostname", "port", "pathname", "search",
    "hash",
];
<|endoftext|>


<commit_before>#[macro_use]
extern crate capnp;

fn try_go() -> ::capnp::Result<()> {
    let segment: &[::capnp::Word] = &[
        capnp_word!(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
        capnp_word!(0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00),
    ];

    let segments = &[segment];
    let segment_array = capnp::message::SegmentArray::new(segments);
    let message = capnp::message::Reader::new(segment_array, Default::default());
    let root: capnp::any_pointer::Reader = try!(message.get_root());

    // At one point, this failed with:
    // error: pointer computed at offset 33554448, outside bounds of allocation Runtime(702) which has size 16
    let result = root.target_size();

    assert!(result.is_err()); // pointer out-of-bounds error

    Ok(())
}

pub fn main() {
    let _ = try_go();
}
<commit_msg>simplify total_size test<commit_after>#[macro_use]
extern crate capnp;

pub fn main() {
    let segment: &[::capnp::Word] = &[
        capnp_word!(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),
        capnp_word!(0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00),
    ];

    let segments = &[segment];
    let segment_array = capnp::message::SegmentArray::new(segments);
    let message = capnp::message::Reader::new(segment_array, Default::default());
    let root: capnp::any_pointer::Reader = message.get_root().unwrap();

    // At one point, this failed with:
    // error: pointer computed at offset 33554448, outside bounds of allocation Runtime(702) which has size 16
    let result = root.target_size();

    assert!(result.is_err()); // pointer out-of-bounds error
}
<|endoftext|>


<commit_before>use std;
use std::path::Path;

use sdl2::event::Event;
use sdl2::gfx::primitives::DrawRenderer;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Point, Rect};
use sdl2::render::{BlendMode, Renderer, Texture, TextureQuery};
use sdl2::surface::Surface;
use sdl2::ttf::{Font, Sdl2TtfContext, STYLE_BOLD};

use position::Position;
use text::Text;

const BORDER_COLOR: Color = Color::RGBA(255, 255, 255, 64);

const PADDING: i32 = 10;

const FONT_FILE: &'static str = "assets/FantasqueSansMono-Bold.ttf";
const FONT_COLOR: Color = Color::RGBA(45, 200, 45, 255);
const FONT_SIZE: u16 = 18;

pub struct Console<'a> {
    pub visible: bool,

    leader: Text,
    input_buffer: String,
    last_command: String,
    command_history: Vec<String>,
    history_position: usize,
    cursor_position: usize,
    buffer: Vec<String>,
    backbuffer_y: i32,
    texture: Texture,
    backbuffer_texture: Texture,
    ttf_context: &'a Sdl2TtfContext,
    size: (u32, u32),
    font: Font<'a>,
    line_ending: bool, // Tracks where the next print call should append to
    ctrl: bool, // Tracks the Ctrl key being pressed
}

impl<'a> Console<'a> {
    /// Creates a new empty Console
    pub fn new(ttf_context: &'a Sdl2TtfContext, mut renderer: &mut Renderer) -> Console<'a> {
        let (width, height) = renderer.window().unwrap().size();
        let mut texture =
            renderer.create_texture_streaming(PixelFormatEnum::RGBA8888, width / 2, height)
                .unwrap();
        texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for y in 0..height {
                    for x in 0..width / 2 {
                        let x = x as usize;
                        let y = y as usize;
                        let offset = y * pitch + x * 4;
                        buffer[offset + 0] = 182;
                        buffer[offset + 1] = 0;
                        buffer[offset + 2] = 0;
                        buffer[offset + 3] = 0;
                    }
                }
            })
            .unwrap();

        let mut backbuffer_texture =
            renderer.create_texture_streaming(PixelFormatEnum::RGBA8888, width / 2, height)
                .unwrap();
        backbuffer_texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for y in 0..height {
                    for x in 0..width / 2 {
                        let x = x as usize;
                        let y = y as usize;
                        let offset = y * pitch + x * 4;
                        buffer[offset + 0] = 182;
                        buffer[offset + 1] = 0;
                        buffer[offset + 2] = 0;
                        buffer[offset + 3] = 0;
                    }
                }
            })
            .unwrap();

        let mut font = ttf_context.load_font(Path::new(FONT_FILE), FONT_SIZE).unwrap();
        font.set_style(STYLE_BOLD);

        Console {
            visible: false,
            leader: Text::new(&ttf_context,
                              &mut renderer,
                              "hakka>",
                              Position::XY(PADDING, height as i32 - FONT_SIZE as i32 - PADDING),
                              FONT_SIZE,
                              FONT_COLOR,
                              FONT_FILE),
            input_buffer: "".into(),
            last_command: "".into(),
            command_history: Vec::new(),
            history_position: 0,
            cursor_position: 0,
            buffer: Vec::new(),
            backbuffer_y: 0,
            texture: texture,
            backbuffer_texture: backbuffer_texture,
            ttf_context: ttf_context,
            size: (width / 2, height),
            font: font,
            line_ending: true,
            ctrl: false,
        }
    }

    pub fn process(&mut self, event: &Event) {
        match *event {
            Event::KeyUp { keycode: Option::Some(Keycode::Backquote), .. } => {
                self.toggle();
            }
            Event::TextInput { ref text, .. } => {
                if self.visible {
                    if text == "`" || text == "\\" {
                        return;
                    }
                    self.add_text(text);
                }
            }
            Event::MouseWheel { y, .. } => {
                if self.visible {
                    if self.buffer.len() * FONT_SIZE as usize >
                       (self.size.1 - (FONT_SIZE as u32 * 2)) as usize {
                        self.backbuffer_y += y * 2;
                        if self.backbuffer_y < 0 {
                            self.backbuffer_y = 0;
                        }
                    }
                }
            }
            Event::KeyDown { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = true,
                        Some(Keycode::C) => {
                            if self.ctrl {
                                self.input_buffer.push_str("^C");
                                self.commit(false);
                            }
                        }
                        Some(Keycode::Left) => {
                            self.cursor_left();
                        }
                        Some(Keycode::Right) => {
                            self.cursor_right();
                        }
                        Some(Keycode::Backspace) => {
                            self.backspace();
                        }
                        Some(Keycode::Delete) => {
                            if self.cursor_position < self.input_buffer.len() {
                                self.cursor_position += 1;
                                self.backspace();
                            }
                        }
                        _ => (),
                    }
                }
            }
            Event::KeyUp { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = false,
                        Some(Keycode::Up) => {
                            self.history_navigate_back();
                        }
                        Some(Keycode::Down) => {
                            self.history_navigate_forward();
                        }
                        Some(Keycode::Return) => {
                            self.commit(true);
                        }
                        Some(Keycode::End) => {
                            self.cursor_position = self.input_buffer.len();
                        }
                        Some(Keycode::Home) => {
                            self.cursor_position = 0;
                        }
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }

    pub fn process_command(&mut self) {
        let command = self.input_buffer.clone();
        if command.len() > 0 {
            self.command_history.push(command.clone());
            self.last_command = command.clone();

            if command == "exit" {
                std::process::exit(0);
            }
        }
    }

    pub fn clear(&mut self) {
        self.buffer.clear();
    }

    fn history_navigate_back(&mut self) {
        if self.history_position > 0 {
            self.input_buffer = self.command_history[self.history_position - 1].clone();
            self.cursor_position = self.input_buffer.len();

            if self.history_position > 0 {
                self.history_position -= 1;
            }
        }
    }

    fn history_navigate_forward(&mut self) {
        if self.history_position < self.command_history.len() - 1 {
            self.input_buffer = self.command_history[self.history_position + 1].clone();
            self.cursor_position = self.input_buffer.len();
            if self.history_position < self.command_history.len() {
                self.history_position += 1;
            }
        }
    }

    pub fn try_process_command(&mut self) -> Option<String> {
        if self.last_command.len() > 0 {
            let cmd = self.last_command.clone();
            self.last_command.clear();
            Some(cmd)
        } else {
            None
        }
    }

    pub fn print<S>(&mut self, text: S)
        where S: Into<String>
    {
        if !self.line_ending {
            let last = self.buffer.last_mut().unwrap();
            last.push_str(&text.into());
        } else {
            self.buffer.push(text.into());
        }
        self.line_ending = false;
    }

    pub fn println<S>(&mut self, text: S)
        where S: Into<String>
    {
        self.buffer.push(text.into());
        self.line_ending = true;
    }

    pub fn print_lines<S>(&mut self, text: S)
        where S: Into<String>
    {
        for line in text.into().lines() {
            self.println(line);
        }
    }

    pub fn wrap_line(&mut self) {
        self.buffer.push("".into());
        self.line_ending = false;
    }

    /// Toggles the visibility of the Console
    pub fn toggle(&mut self) {
        self.visible = !self.visible;
    }

    pub fn add_text(&mut self, input: &str) {
        self.input_buffer.insert(self.cursor_position, input.chars().next().unwrap());
        self.cursor_position += 1;
    }

    pub fn commit(&mut self, execute: bool) {
        self.buffer.push(format!("hakka> {}", self.input_buffer.clone()));
        if execute {
            self.process_command();
        }
        self.input_buffer.clear();
        self.cursor_position = 0;
        self.history_position = self.command_history.len();
    }

    pub fn cursor_left(&mut self) {
        if self.cursor_position > 0 {
            self.cursor_position -= 1;
        }
    }

    pub fn cursor_right(&mut self) {
        if self.cursor_position < self.input_buffer.len() {
            self.cursor_position += 1;
        }
    }

    pub fn backspace(&mut self) {
        if self.visible {
            if self.cursor_position > 0 {
                self.input_buffer.remove(self.cursor_position - 1);
                self.cursor_position -= 1;
            }
        }
    }

    /// Renders the Console
    pub fn render(&mut self, mut renderer: &mut Renderer) {
        if self.visible {

            renderer.set_blend_mode(BlendMode::Blend);
            self.texture.set_blend_mode(BlendMode::Blend);
            renderer.copy(&self.texture,
                      None,
                      Some(Rect::new(0, 0, self.size.0, self.size.1)))
                .unwrap();
            self.generate_backbuffer_texture(&mut renderer);
            self.render_leader(&mut renderer);

            // Insert the cursor via a dodgy vertical line
            let mut output_text = self.input_buffer.clone();
            let cursor_x =
                60 + PADDING as i16 +
                self.font.size_of(&self.input_buffer[..self.cursor_position]).unwrap().0 as i16;
            // Draw a dodgy cursor
            renderer.thick_line(cursor_x,
                            self.size.1 as i16 - FONT_SIZE as i16 - PADDING as i16,
                            cursor_x,
                            self.size.1 as i16 - PADDING as i16,
                            1,
                            FONT_COLOR)
                .unwrap();

            if output_text.len() > 0 {
                let text = Text::new(&self.ttf_context,
                                     &mut renderer,
                                     &output_text[..],
                                     Position::XY(60 + PADDING,
                                                  self.size.1 as i32 - FONT_SIZE as i32 - PADDING),
                                     FONT_SIZE,
                                     FONT_COLOR,
                                     FONT_FILE);
                text.render(&mut renderer);
            }

            self.render_border(&mut renderer);
        }
    }

    fn render_border(&self, mut renderer: &mut Renderer) {
        // Render the border
        renderer.set_draw_color(Color::RGBA(255, 255, 255, 255));
        // North
        renderer.thick_line(0, 0, self.size.0 as i16, 0, 1, BORDER_COLOR);

        // East
        renderer.thick_line(self.size.0 as i16,
                            0,
                            self.size.0 as i16,
                            self.size.1 as i16,
                            1,
                            BORDER_COLOR);

        // South
        renderer.thick_line(0,
                            self.size.1 as i16 - 1,
                            self.size.0 as i16,
                            self.size.1 as i16 - 1,
                            1,
                            BORDER_COLOR);
    }

    fn render_leader(&self, mut renderer: &mut Renderer) {
        // Render a black background behind it so the buffer scrolling looks
        // nicer.
        let rect_y = self.size.1 as i32 - FONT_SIZE as i32 - PADDING;
        renderer.set_draw_color(Color::RGBA(0, 0, 0, 255));
        renderer.fill_rect(Rect::new(0, rect_y, self.size.0, rect_y as u32));
        self.leader.render(&mut renderer);
    }

    fn generate_backbuffer_texture(&mut self, mut renderer: &mut Renderer) {
        let mut main_surface = Surface::new(self.size.0,
                                            (self.size.1 - (FONT_SIZE as u32)),
                                            PixelFormatEnum::RGBA8888)
            .unwrap();
        let mut counter = 2;
        for line in self.buffer.iter().rev().take(100) {
            let mut y_pos = self.size.1 as i32 - (FONT_SIZE as i32 * counter) + self.backbuffer_y;
            counter += 1;

            if line.trim().len() == 0 {
                continue;
            }

            let surface = self.font
                .render(&line)
                .blended(FONT_COLOR)
                .unwrap();
            surface.blit(None,
                      &mut main_surface,
                      Some(Rect::new(PADDING, y_pos - PADDING, self.size.1, FONT_SIZE as u32)))
                .unwrap();
        }
        let texture = renderer.create_texture_from_surface(&main_surface)
            .unwrap();

        let TextureQuery { width, height, .. } = texture.query();

        renderer.copy(&texture, None, Some(Rect::new(0, 0, width, height)));
    }
}
<commit_msg>Console can now be toggled with \<commit_after>use std;
use std::path::Path;

use sdl2::event::Event;
use sdl2::gfx::primitives::DrawRenderer;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Point, Rect};
use sdl2::render::{BlendMode, Renderer, Texture, TextureQuery};
use sdl2::surface::Surface;
use sdl2::ttf::{Font, Sdl2TtfContext, STYLE_BOLD};

use position::Position;
use text::Text;

const BORDER_COLOR: Color = Color::RGBA(255, 255, 255, 64);

const PADDING: i32 = 10;

const FONT_FILE: &'static str = "assets/FantasqueSansMono-Bold.ttf";
const FONT_COLOR: Color = Color::RGBA(45, 200, 45, 255);
const FONT_SIZE: u16 = 18;

pub struct Console<'a> {
    pub visible: bool,

    leader: Text,
    input_buffer: String,
    last_command: String,
    command_history: Vec<String>,
    history_position: usize,
    cursor_position: usize,
    buffer: Vec<String>,
    backbuffer_y: i32,
    texture: Texture,
    backbuffer_texture: Texture,
    ttf_context: &'a Sdl2TtfContext,
    size: (u32, u32),
    font: Font<'a>,
    line_ending: bool, // Tracks where the next print call should append to
    ctrl: bool, // Tracks the Ctrl key being pressed
}

impl<'a> Console<'a> {
    /// Creates a new empty Console
    pub fn new(ttf_context: &'a Sdl2TtfContext, mut renderer: &mut Renderer) -> Console<'a> {
        let (width, height) = renderer.window().unwrap().size();
        let mut texture =
            renderer.create_texture_streaming(PixelFormatEnum::RGBA8888, width / 2, height)
                .unwrap();
        texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for y in 0..height {
                    for x in 0..width / 2 {
                        let x = x as usize;
                        let y = y as usize;
                        let offset = y * pitch + x * 4;
                        buffer[offset + 0] = 182;
                        buffer[offset + 1] = 0;
                        buffer[offset + 2] = 0;
                        buffer[offset + 3] = 0;
                    }
                }
            })
            .unwrap();

        let mut backbuffer_texture =
            renderer.create_texture_streaming(PixelFormatEnum::RGBA8888, width / 2, height)
                .unwrap();
        backbuffer_texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for y in 0..height {
                    for x in 0..width / 2 {
                        let x = x as usize;
                        let y = y as usize;
                        let offset = y * pitch + x * 4;
                        buffer[offset + 0] = 182;
                        buffer[offset + 1] = 0;
                        buffer[offset + 2] = 0;
                        buffer[offset + 3] = 0;
                    }
                }
            })
            .unwrap();

        let mut font = ttf_context.load_font(Path::new(FONT_FILE), FONT_SIZE).unwrap();
        font.set_style(STYLE_BOLD);

        Console {
            visible: false,
            leader: Text::new(&ttf_context,
                              &mut renderer,
                              "hakka>",
                              Position::XY(PADDING, height as i32 - FONT_SIZE as i32 - PADDING),
                              FONT_SIZE,
                              FONT_COLOR,
                              FONT_FILE),
            input_buffer: "".into(),
            last_command: "".into(),
            command_history: Vec::new(),
            history_position: 0,
            cursor_position: 0,
            buffer: Vec::new(),
            backbuffer_y: 0,
            texture: texture,
            backbuffer_texture: backbuffer_texture,
            ttf_context: ttf_context,
            size: (width / 2, height),
            font: font,
            line_ending: true,
            ctrl: false,
        }
    }

    pub fn process(&mut self, event: &Event) {
        match *event {
            Event::KeyUp { keycode: Option::Some(Keycode::Backquote), .. } |
            Event::KeyUp { keycode: Option::Some(Keycode::Backslash), .. }           => {
                self.toggle();
            }
            Event::TextInput { ref text, .. } => {
                if self.visible {
                    if text == "`" || text == "\\" {
                        return;
                    }
                    self.add_text(text);
                }
            }
            Event::MouseWheel { y, .. } => {
                if self.visible {
                    if self.buffer.len() * FONT_SIZE as usize >
                       (self.size.1 - (FONT_SIZE as u32 * 2)) as usize {
                        self.backbuffer_y += y * 2;
                        if self.backbuffer_y < 0 {
                            self.backbuffer_y = 0;
                        }
                    }
                }
            }
            Event::KeyDown { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = true,
                        Some(Keycode::C) => {
                            if self.ctrl {
                                self.input_buffer.push_str("^C");
                                self.commit(false);
                            }
                        }
                        Some(Keycode::Left) => {
                            self.cursor_left();
                        }
                        Some(Keycode::Right) => {
                            self.cursor_right();
                        }
                        Some(Keycode::Backspace) => {
                            self.backspace();
                        }
                        Some(Keycode::Delete) => {
                            if self.cursor_position < self.input_buffer.len() {
                                self.cursor_position += 1;
                                self.backspace();
                            }
                        }
                        _ => (),
                    }
                }
            }
            Event::KeyUp { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = false,
                        Some(Keycode::Up) => {
                            self.history_navigate_back();
                        }
                        Some(Keycode::Down) => {
                            self.history_navigate_forward();
                        }
                        Some(Keycode::Return) => {
                            self.commit(true);
                        }
                        Some(Keycode::End) => {
                            self.cursor_position = self.input_buffer.len();
                        }
                        Some(Keycode::Home) => {
                            self.cursor_position = 0;
                        }
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }

    pub fn process_command(&mut self) {
        let command = self.input_buffer.clone();
        if command.len() > 0 {
            self.command_history.push(command.clone());
            self.last_command = command.clone();

            if command == "exit" {
                std::process::exit(0);
            }
        }
    }

    pub fn clear(&mut self) {
        self.buffer.clear();
    }

    fn history_navigate_back(&mut self) {
        if self.history_position > 0 {
            self.input_buffer = self.command_history[self.history_position - 1].clone();
            self.cursor_position = self.input_buffer.len();

            if self.history_position > 0 {
                self.history_position -= 1;
            }
        }
    }

    fn history_navigate_forward(&mut self) {
        if self.history_position < self.command_history.len() - 1 {
            self.input_buffer = self.command_history[self.history_position + 1].clone();
            self.cursor_position = self.input_buffer.len();
            if self.history_position < self.command_history.len() {
                self.history_position += 1;
            }
        }
    }

    pub fn try_process_command(&mut self) -> Option<String> {
        if self.last_command.len() > 0 {
            let cmd = self.last_command.clone();
            self.last_command.clear();
            Some(cmd)
        } else {
            None
        }
    }

    pub fn print<S>(&mut self, text: S)
        where S: Into<String>
    {
        if !self.line_ending {
            let last = self.buffer.last_mut().unwrap();
            last.push_str(&text.into());
        } else {
            self.buffer.push(text.into());
        }
        self.line_ending = false;
    }

    pub fn println<S>(&mut self, text: S)
        where S: Into<String>
    {
        self.buffer.push(text.into());
        self.line_ending = true;
    }

    pub fn print_lines<S>(&mut self, text: S)
        where S: Into<String>
    {
        for line in text.into().lines() {
            self.println(line);
        }
    }

    pub fn wrap_line(&mut self) {
        self.buffer.push("".into());
        self.line_ending = false;
    }

    /// Toggles the visibility of the Console
    pub fn toggle(&mut self) {
        self.visible = !self.visible;
    }

    pub fn add_text(&mut self, input: &str) {
        self.input_buffer.insert(self.cursor_position, input.chars().next().unwrap());
        self.cursor_position += 1;
    }

    pub fn commit(&mut self, execute: bool) {
        self.buffer.push(format!("hakka> {}", self.input_buffer.clone()));
        if execute {
            self.process_command();
        }
        self.input_buffer.clear();
        self.cursor_position = 0;
        self.history_position = self.command_history.len();
    }

    pub fn cursor_left(&mut self) {
        if self.cursor_position > 0 {
            self.cursor_position -= 1;
        }
    }

    pub fn cursor_right(&mut self) {
        if self.cursor_position < self.input_buffer.len() {
            self.cursor_position += 1;
        }
    }

    pub fn backspace(&mut self) {
        if self.visible {
            if self.cursor_position > 0 {
                self.input_buffer.remove(self.cursor_position - 1);
                self.cursor_position -= 1;
            }
        }
    }

    /// Renders the Console
    pub fn render(&mut self, mut renderer: &mut Renderer) {
        if self.visible {

            renderer.set_blend_mode(BlendMode::Blend);
            self.texture.set_blend_mode(BlendMode::Blend);
            renderer.copy(&self.texture,
                      None,
                      Some(Rect::new(0, 0, self.size.0, self.size.1)))
                .unwrap();
            self.generate_backbuffer_texture(&mut renderer);
            self.render_leader(&mut renderer);

            // Insert the cursor via a dodgy vertical line
            let mut output_text = self.input_buffer.clone();
            let cursor_x =
                60 + PADDING as i16 +
                self.font.size_of(&self.input_buffer[..self.cursor_position]).unwrap().0 as i16;
            // Draw a dodgy cursor
            renderer.thick_line(cursor_x,
                            self.size.1 as i16 - FONT_SIZE as i16 - PADDING as i16,
                            cursor_x,
                            self.size.1 as i16 - PADDING as i16,
                            1,
                            FONT_COLOR)
                .unwrap();

            if output_text.len() > 0 {
                let text = Text::new(&self.ttf_context,
                                     &mut renderer,
                                     &output_text[..],
                                     Position::XY(60 + PADDING,
                                                  self.size.1 as i32 - FONT_SIZE as i32 - PADDING),
                                     FONT_SIZE,
                                     FONT_COLOR,
                                     FONT_FILE);
                text.render(&mut renderer);
            }

            self.render_border(&mut renderer);
        }
    }

    fn render_border(&self, mut renderer: &mut Renderer) {
        // Render the border
        renderer.set_draw_color(Color::RGBA(255, 255, 255, 255));
        // North
        renderer.thick_line(0, 0, self.size.0 as i16, 0, 1, BORDER_COLOR);

        // East
        renderer.thick_line(self.size.0 as i16,
                            0,
                            self.size.0 as i16,
                            self.size.1 as i16,
                            1,
                            BORDER_COLOR);

        // South
        renderer.thick_line(0,
                            self.size.1 as i16 - 1,
                            self.size.0 as i16,
                            self.size.1 as i16 - 1,
                            1,
                            BORDER_COLOR);
    }

    fn render_leader(&self, mut renderer: &mut Renderer) {
        // Render a black background behind it so the buffer scrolling looks
        // nicer.
        let rect_y = self.size.1 as i32 - FONT_SIZE as i32 - PADDING;
        renderer.set_draw_color(Color::RGBA(0, 0, 0, 255));
        renderer.fill_rect(Rect::new(0, rect_y, self.size.0, rect_y as u32));
        self.leader.render(&mut renderer);
    }

    fn generate_backbuffer_texture(&mut self, mut renderer: &mut Renderer) {
        let mut main_surface = Surface::new(self.size.0,
                                            (self.size.1 - (FONT_SIZE as u32)),
                                            PixelFormatEnum::RGBA8888)
            .unwrap();
        let mut counter = 2;
        for line in self.buffer.iter().rev().take(100) {
            let mut y_pos = self.size.1 as i32 - (FONT_SIZE as i32 * counter) + self.backbuffer_y;
            counter += 1;

            if line.trim().len() == 0 {
                continue;
            }

            let surface = self.font
                .render(&line)
                .blended(FONT_COLOR)
                .unwrap();
            surface.blit(None,
                      &mut main_surface,
                      Some(Rect::new(PADDING, y_pos - PADDING, self.size.1, FONT_SIZE as u32)))
                .unwrap();
        }
        let texture = renderer.create_texture_from_surface(&main_surface)
            .unwrap();

        let TextureQuery { width, height, .. } = texture.query();

        renderer.copy(&texture, None, Some(Rect::new(0, 0, width, height)));
    }
}
<|endoftext|>


<commit_before>//! De-/serialization functions for `std::time::SystemTime` objects represented as milliseconds
//! since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within bounds.

use std::{
    convert::TryInto,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

use js_int::UInt;
use serde::{
    de::{self, Deserialize, Deserializer},
    ser::{self, Serialize, Serializer},
};

/// Serialize a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let time_since_epoch = time.duration_since(UNIX_EPOCH).map_err(ser::Error::custom)?;
    let uint: UInt = time_since_epoch.as_millis().try_into().map_err(ser::Error::custom)?;

    uint.serialize(serializer)
}

/// Deserializes a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
where
    D: Deserializer<'de>,
{
    let millis = UInt::deserialize(deserializer)?;
    UNIX_EPOCH
        .checked_add(Duration::from_millis(millis.into()))
        .ok_or_else(|| de::Error::custom("input too large for SystemTime"))
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    use matches::assert_matches;
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
    struct SystemTimeTest {
        #[serde(with = "super")]
        timestamp: SystemTime,
    }

    #[test]
    fn deserialize() {
        let json = json!({ "timestamp": 3000 });

        assert_matches!(
            serde_json::from_value::<SystemTimeTest>(json),
            Ok(SystemTimeTest { timestamp })
            if timestamp == UNIX_EPOCH + Duration::from_millis(3000)
        );
    }

    #[test]
    fn serialize() {
        let request = SystemTimeTest { timestamp: UNIX_EPOCH + Duration::new(2, 0) };
        assert_matches!(
            serde_json::to_value(&request),
            Ok(value) if value == json!({ "timestamp": 2000 })
        );
    }
}
<commit_msg>serde: Add test for issue 446<commit_after>//! De-/serialization functions for `std::time::SystemTime` objects represented as milliseconds
//! since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within bounds.

use std::{
    convert::TryInto,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

use js_int::UInt;
use serde::{
    de::{self, Deserialize, Deserializer},
    ser::{self, Serialize, Serializer},
};

/// Serialize a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let time_since_epoch = time.duration_since(UNIX_EPOCH).map_err(ser::Error::custom)?;
    let uint: UInt = time_since_epoch.as_millis().try_into().map_err(ser::Error::custom)?;

    uint.serialize(serializer)
}

/// Deserializes a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
where
    D: Deserializer<'de>,
{
    let millis = UInt::deserialize(deserializer)?;
    UNIX_EPOCH
        .checked_add(Duration::from_millis(millis.into()))
        .ok_or_else(|| de::Error::custom("input too large for SystemTime"))
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    use matches::assert_matches;
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
    struct SystemTimeTest {
        #[serde(with = "super")]
        timestamp: SystemTime,
    }

    #[test]
    fn deserialize() {
        let json = json!({ "timestamp": 3000 });

        assert_matches!(
            serde_json::from_value::<SystemTimeTest>(json),
            Ok(SystemTimeTest { timestamp })
            if timestamp == UNIX_EPOCH + Duration::from_millis(3000)
        );
    }

    #[test]
    fn issue_446() {
        let json = json!({ "timestamp": 15159743990000u64 });

        assert_matches!(
            serde_json::from_value::<SystemTimeTest>(json),
            Ok(SystemTimeTest { timestamp })
            if timestamp == UNIX_EPOCH + Duration::from_millis(15159743990000)
        );
    }

    #[test]
    fn serialize() {
        let request = SystemTimeTest { timestamp: UNIX_EPOCH + Duration::new(2, 0) };
        assert_matches!(
            serde_json::to_value(&request),
            Ok(value) if value == json!({ "timestamp": 2000 })
        );
    }
}
<|endoftext|>


<commit_before>use coordinates::{CoordinateSystem, Point};
use std::ops::{Index, IndexMut};
use std::marker::PhantomData;
use typenum::uint::Unsigned;
use typenum::Pow;
use generic_array::{GenericArray, ArrayLength};
use super::{CovariantIndex, ContravariantIndex, Variance, IndexType};

/// This is a struct that represents a generic tensor
pub struct Tensor<T: CoordinateSystem, U: Variance>
    where T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    p: Point<T>,
    x: GenericArray<f64, <T::Dimension as Pow<U::Rank>>::Output>,
    phantom: PhantomData<U>,
}

impl<T, U> Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    /// Returns the point at which the tensor is defined.
    pub fn get_point(&self) -> &Point<T> {
        &self.p
    }

    /// Returns a reference to a coordinate of the tensor, at indices specified by the slice.
    /// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
    pub fn get_coord(&self, i: &[usize]) -> &f64 {
        assert_eq!(i.len(), U::rank());
        let dim = T::dimension();
        let index = i.into_iter().fold(0, |res, idx| {
            assert!(*idx < dim);
            res * dim + idx
        });
        &self.x[index]
    }

    /// Returns a mutable reference to a coordinate of the tensor, at indices specified by the slice.
    /// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
    pub fn get_coord_mut(&mut self, i: &[usize]) -> &mut f64 {
        assert_eq!(i.len(), U::rank());
        let dim = T::dimension();
        let index = i.into_iter().fold(0, |res, idx| {
            assert!(*idx < dim);
            res * dim + idx
        });
        &mut self.x[index]
    }

    /// Returns the variance of the tensor, that is, the list of the index types.
    /// A vector would return vec![Contravariant], a metric tensor: vec![Covariant, Covariant].
    pub fn get_variance() -> Vec<IndexType> {
        U::variance()
    }

    /// Returns the rank of the tensor
    pub fn get_rank() -> usize {
        U::rank()
    }

    /// Returns the number of coordinates of the tensor
    pub fn get_num_coords() -> usize {
        <T::Dimension as Pow<U::Rank>>::Output::to_usize()
    }

    pub fn new(point: Point<T>) -> Tensor<T, U> {
        Tensor {
            p: point,
            x: GenericArray::new(),
            phantom: PhantomData,
        }
    }
}

impl<'a, T, U> Index<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    type Output = f64;

    fn index(&self, idx: &'a [usize]) -> &f64 {
        self.get_coord(idx)
    }
}

impl<'a, T, U> IndexMut<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    fn index_mut(&mut self, idx: &'a [usize]) -> &mut f64 {
        self.get_coord_mut(idx)
    }
}

pub type Vector<T> = Tensor<T, ContravariantIndex>;
pub type Covector<T> = Tensor<T, CovariantIndex>;
pub type Matrix<T> = Tensor<T, (ContravariantIndex, CovariantIndex)>;
<commit_msg>Removed unnecessary PhantomData<commit_after>use coordinates::{CoordinateSystem, Point};
use std::ops::{Index, IndexMut};
use typenum::uint::Unsigned;
use typenum::Pow;
use generic_array::{GenericArray, ArrayLength};
use super::{CovariantIndex, ContravariantIndex, Variance, IndexType};

/// This is a struct that represents a generic tensor
pub struct Tensor<T: CoordinateSystem, U: Variance>
    where T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    p: Point<T>,
    x: GenericArray<f64, <T::Dimension as Pow<U::Rank>>::Output>
}

impl<T, U> Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    /// Returns the point at which the tensor is defined.
    pub fn get_point(&self) -> &Point<T> {
        &self.p
    }

    /// Returns a reference to a coordinate of the tensor, at indices specified by the slice.
    /// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
    pub fn get_coord(&self, i: &[usize]) -> &f64 {
        assert_eq!(i.len(), U::rank());
        let dim = T::dimension();
        let index = i.into_iter().fold(0, |res, idx| {
            assert!(*idx < dim);
            res * dim + idx
        });
        &self.x[index]
    }

    /// Returns a mutable reference to a coordinate of the tensor, at indices specified by the slice.
    /// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
    pub fn get_coord_mut(&mut self, i: &[usize]) -> &mut f64 {
        assert_eq!(i.len(), U::rank());
        let dim = T::dimension();
        let index = i.into_iter().fold(0, |res, idx| {
            assert!(*idx < dim);
            res * dim + idx
        });
        &mut self.x[index]
    }

    /// Returns the variance of the tensor, that is, the list of the index types.
    /// A vector would return vec![Contravariant], a metric tensor: vec![Covariant, Covariant].
    pub fn get_variance() -> Vec<IndexType> {
        U::variance()
    }

    /// Returns the rank of the tensor
    pub fn get_rank() -> usize {
        U::rank()
    }

    /// Returns the number of coordinates of the tensor
    pub fn get_num_coords() -> usize {
        <T::Dimension as Pow<U::Rank>>::Output::to_usize()
    }

    pub fn new(point: Point<T>) -> Tensor<T, U> {
        Tensor {
            p: point,
            x: GenericArray::new()
        }
    }
}

impl<'a, T, U> Index<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    type Output = f64;

    fn index(&self, idx: &'a [usize]) -> &f64 {
        self.get_coord(idx)
    }
}

impl<'a, T, U> IndexMut<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem,
          U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
    fn index_mut(&mut self, idx: &'a [usize]) -> &mut f64 {
        self.get_coord_mut(idx)
    }
}

pub type Vector<T> = Tensor<T, ContravariantIndex>;
pub type Covector<T> = Tensor<T, CovariantIndex>;
pub type Matrix<T> = Tensor<T, (ContravariantIndex, CovariantIndex)>;
<|endoftext|>


<commit_before>#![no_std]

use core::fmt;
use core::fmt::Write;

mod color;
use color::Color;

const ROWS: usize = 25;
const COLS: usize = 80;
const COL_BYTES: usize = COLS * 2;

pub struct Vga<T: AsMut<[u8]>> {
    slice: T,
    buffer: [u8; ROWS * COL_BYTES],
    position: usize,
}

impl<T: AsMut<[u8]>> Vga<T> {
    pub fn new(mut slice: T) -> Vga<T> {
        // we must have enough bytes of backing storage to make this work.
        assert_eq!(slice.as_mut().len(), ROWS * COL_BYTES);

        Vga {
            slice: slice,
            buffer: [0; ROWS * COL_BYTES],
            position: 0,
        }
    }

    pub fn flush(&mut self) {
      panic!()
    }

    fn write_byte(&mut self, byte: u8) {
        let i = self.position;

        if byte == '\n' as u8 {
            let current_line = self.position / (COL_BYTES);
            self.position = (current_line + 1) * COL_BYTES;
        } else {
            self.buffer[i] = byte;
            self.buffer[i + 1] = color::colorcode(Color::Green, Color::Black);

            self.position += 2;
        }

        if self.position >= self.buffer.len() {
            self.scroll();
        }
    }

    fn scroll(&mut self) {
        for row in 1..ROWS {
            for cb in 0..COL_BYTES {
                let prev_position = ((row - 1) * COL_BYTES) + cb;
                let current_position = (row * COL_BYTES) + cb;
                self.buffer[prev_position] = self.buffer[current_position];
            }
        }

        for cb in 0..COL_BYTES/2 {
            self.buffer[((ROWS - 1) * COL_BYTES) + (cb * 2)] = ' ' as u8;
        }

        self.position = (ROWS - 1) * COL_BYTES;
    }
}

impl<T: AsMut<[u8]>> Write for Vga<T> {
    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
        for b in s.bytes() {
            self.write_byte(b);
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use Vga;
    use core::fmt::Write;

    use ROWS;
    use COL_BYTES;

    #[test]
    fn write_a_letter() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];

        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("a").unwrap();

        assert_eq!(vga.buffer[0], 'a' as u8);
        assert_eq!(vga.buffer[1], 0x02);
    }

    #[test]
    fn write_a_word() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        let word = "word";
        vga.write_str(word).unwrap();

        assert_eq!(vga.buffer[0], 'w' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'o' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'r' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'd' as u8);
        assert_eq!(vga.buffer[7], 0x02);
    }

    #[test]
    fn write_multiple_words() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("hello ").unwrap();
        vga.write_str("world").unwrap();

        assert_eq!(vga.buffer[0], 'h' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'e' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'l' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'l' as u8);
        assert_eq!(vga.buffer[7], 0x02);
        assert_eq!(vga.buffer[8], 'o' as u8);
        assert_eq!(vga.buffer[9], 0x02);
        assert_eq!(vga.buffer[10], ' ' as u8);
        assert_eq!(vga.buffer[11], 0x02);
        assert_eq!(vga.buffer[12], 'w' as u8);
        assert_eq!(vga.buffer[13], 0x02);
        assert_eq!(vga.buffer[14], 'o' as u8);
        assert_eq!(vga.buffer[15], 0x02);
        assert_eq!(vga.buffer[16], 'r' as u8);
        assert_eq!(vga.buffer[17], 0x02);
        assert_eq!(vga.buffer[18], 'l' as u8);
        assert_eq!(vga.buffer[19], 0x02);
        assert_eq!(vga.buffer[20], 'd' as u8);
        assert_eq!(vga.buffer[21], 0x02);
    }

    #[test]
    fn write_newline() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("hello\nworld\n!").unwrap();

        assert_eq!(vga.buffer[0], 'h' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'e' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'l' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'l' as u8);
        assert_eq!(vga.buffer[7], 0x02);
        assert_eq!(vga.buffer[8], 'o' as u8);
        assert_eq!(vga.buffer[9], 0x02);
        assert_eq!(vga.buffer[160], 'w' as u8);
        assert_eq!(vga.buffer[161], 0x02);
        assert_eq!(vga.buffer[162], 'o' as u8);
        assert_eq!(vga.buffer[163], 0x02);
        assert_eq!(vga.buffer[164], 'r' as u8);
        assert_eq!(vga.buffer[165], 0x02);
        assert_eq!(vga.buffer[166], 'l' as u8);
        assert_eq!(vga.buffer[167], 0x02);
        assert_eq!(vga.buffer[168], 'd' as u8);
        assert_eq!(vga.buffer[169], 0x02);
        assert_eq!(vga.buffer[320], '!' as u8);
        assert_eq!(vga.buffer[321], 0x02);
    }

    #[test]
    fn write_scroll() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        for b in "abcdefghijklmnopqrstuvwxyz".bytes() {
            vga.write_byte(b);
            vga.write_byte('\n' as u8);
        }

        assert_eq!(vga.buffer[0], 'c' as u8);
        for cb in 0..COL_BYTES/2 {
            assert_eq!(vga.buffer[(ROWS - 1) * COL_BYTES + (cb * 2)], ' ' as u8);
        }
    }

}
<commit_msg>lol just put the line your gonna add in a commment ok<commit_after>#![no_std]

use core::fmt;
use core::fmt::Write;

mod color;
use color::Color;

const ROWS: usize = 25;
const COLS: usize = 80;
const COL_BYTES: usize = COLS * 2;

pub struct Vga<T: AsMut<[u8]>> {
    slice: T,
    buffer: [u8; ROWS * COL_BYTES],
    position: usize,
}

impl<T: AsMut<[u8]>> Vga<T> {
    pub fn new(mut slice: T) -> Vga<T> {
        // we must have enough bytes of backing storage to make this work.
        assert_eq!(slice.as_mut().len(), ROWS * COL_BYTES);

        Vga {
            slice: slice,
            buffer: [0; ROWS * COL_BYTES],
            position: 0,
        }
    }

    pub fn flush(&mut self) {
      // self.slice.as_mut().clone_from_slice(&self.buffer);
      panic!()
    }

    fn write_byte(&mut self, byte: u8) {
        let i = self.position;

        if byte == '\n' as u8 {
            let current_line = self.position / (COL_BYTES);
            self.position = (current_line + 1) * COL_BYTES;
        } else {
            self.buffer[i] = byte;
            self.buffer[i + 1] = color::colorcode(Color::Green, Color::Black);

            self.position += 2;
        }

        if self.position >= self.buffer.len() {
            self.scroll();
        }
    }

    fn scroll(&mut self) {
        for row in 1..ROWS {
            for cb in 0..COL_BYTES {
                let prev_position = ((row - 1) * COL_BYTES) + cb;
                let current_position = (row * COL_BYTES) + cb;
                self.buffer[prev_position] = self.buffer[current_position];
            }
        }

        for cb in 0..COL_BYTES/2 {
            self.buffer[((ROWS - 1) * COL_BYTES) + (cb * 2)] = ' ' as u8;
        }

        self.position = (ROWS - 1) * COL_BYTES;
    }
}

impl<T: AsMut<[u8]>> Write for Vga<T> {
    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
        for b in s.bytes() {
            self.write_byte(b);
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use Vga;
    use core::fmt::Write;

    use ROWS;
    use COL_BYTES;

    #[test]
    fn write_a_letter() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];

        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("a").unwrap();

        assert_eq!(vga.buffer[0], 'a' as u8);
        assert_eq!(vga.buffer[1], 0x02);
    }

    #[test]
    fn write_a_word() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        let word = "word";
        vga.write_str(word).unwrap();

        assert_eq!(vga.buffer[0], 'w' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'o' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'r' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'd' as u8);
        assert_eq!(vga.buffer[7], 0x02);
    }

    #[test]
    fn write_multiple_words() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("hello ").unwrap();
        vga.write_str("world").unwrap();

        assert_eq!(vga.buffer[0], 'h' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'e' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'l' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'l' as u8);
        assert_eq!(vga.buffer[7], 0x02);
        assert_eq!(vga.buffer[8], 'o' as u8);
        assert_eq!(vga.buffer[9], 0x02);
        assert_eq!(vga.buffer[10], ' ' as u8);
        assert_eq!(vga.buffer[11], 0x02);
        assert_eq!(vga.buffer[12], 'w' as u8);
        assert_eq!(vga.buffer[13], 0x02);
        assert_eq!(vga.buffer[14], 'o' as u8);
        assert_eq!(vga.buffer[15], 0x02);
        assert_eq!(vga.buffer[16], 'r' as u8);
        assert_eq!(vga.buffer[17], 0x02);
        assert_eq!(vga.buffer[18], 'l' as u8);
        assert_eq!(vga.buffer[19], 0x02);
        assert_eq!(vga.buffer[20], 'd' as u8);
        assert_eq!(vga.buffer[21], 0x02);
    }

    #[test]
    fn write_newline() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        vga.write_str("hello\nworld\n!").unwrap();

        assert_eq!(vga.buffer[0], 'h' as u8);
        assert_eq!(vga.buffer[1], 0x02);
        assert_eq!(vga.buffer[2], 'e' as u8);
        assert_eq!(vga.buffer[3], 0x02);
        assert_eq!(vga.buffer[4], 'l' as u8);
        assert_eq!(vga.buffer[5], 0x02);
        assert_eq!(vga.buffer[6], 'l' as u8);
        assert_eq!(vga.buffer[7], 0x02);
        assert_eq!(vga.buffer[8], 'o' as u8);
        assert_eq!(vga.buffer[9], 0x02);
        assert_eq!(vga.buffer[160], 'w' as u8);
        assert_eq!(vga.buffer[161], 0x02);
        assert_eq!(vga.buffer[162], 'o' as u8);
        assert_eq!(vga.buffer[163], 0x02);
        assert_eq!(vga.buffer[164], 'r' as u8);
        assert_eq!(vga.buffer[165], 0x02);
        assert_eq!(vga.buffer[166], 'l' as u8);
        assert_eq!(vga.buffer[167], 0x02);
        assert_eq!(vga.buffer[168], 'd' as u8);
        assert_eq!(vga.buffer[169], 0x02);
        assert_eq!(vga.buffer[320], '!' as u8);
        assert_eq!(vga.buffer[321], 0x02);
    }

    #[test]
    fn write_scroll() {
        let mut mock_memory = [0u8; ROWS * COL_BYTES];
        let mut vga = Vga::new(&mut mock_memory[..]);

        for b in "abcdefghijklmnopqrstuvwxyz".bytes() {
            vga.write_byte(b);
            vga.write_byte('\n' as u8);
        }

        assert_eq!(vga.buffer[0], 'c' as u8);
        for cb in 0..COL_BYTES/2 {
            assert_eq!(vga.buffer[(ROWS - 1) * COL_BYTES + (cb * 2)], ' ' as u8);
        }
    }

}
<|endoftext|>


<commit_before>extern crate polydraw;

use std::cmp::Ordering;
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Segment {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   segments: Vec<Segment>,
   segments_end: usize,

   segments_min_y: Vec<i64>,
   segments_max_y: Vec<i64>,
   segments_order: Vec<usize>,
}

impl ClipRenderer {
   fn new() -> Self {
      let edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let segments = create_default_vec(65536);

      let segments_min_y = create_default_vec(65536);
      let segments_max_y = create_default_vec(65536);
      let segments_order = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: 1000,

         edges: edges,
         polys: polys,

         segments: segments,
         segments_end: 0,

         segments_min_y: segments_min_y,
         segments_max_y: segments_max_y,
         segments_order: segments_order,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_segments_min_max_y(&mut self) {
      for segment_index in 0..self.segments_end {
         let ref segment = self.segments[segment_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (segment_min_y, segment_max_y) = if segment.edge_type.reversed() {
            (segment.p2.y, segment.p1.y)
         } else {
            (segment.p1.y, segment.p2.y)
         };

         if segment_min_y < min_y  {
            min_y = segment_min_y;
         }

         if segment_max_y > max_y {
            max_y = segment_max_y;
         }

         self.segments_min_y[segment_index] = min_y;
         self.segments_max_y[segment_index] = max_y;
         self.segments_order[segment_index] = segment_index;
      }

      self.sort_segments_order();

      println!("MIN Y {:?}", &self.segments_min_y[..self.segments_end]);
      println!("MAX Y {:?}", &self.segments_max_y[..self.segments_end]);
      println!("ORDER {:?}", &self.segments_order[..self.segments_end]);

      self.iterate_segments();

      panic!("END");
   }

   fn sort_segments_order(&mut self) {
      let segments_order = &mut self.segments_order[..self.segments_end];
      let segments_min_y = &self.segments_min_y;
      let segments_max_y = &self.segments_max_y;

      segments_order.sort_by(|a, b| {
         match segments_min_y[*a].cmp(&segments_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => segments_max_y[*a].cmp(&segments_max_y[*b])
         }
      });
   }

   fn iterate_segments(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.segments_end {
         let segment_index = self.segments_order[order_index];
         let min_y = self.segments_min_y[segment_index];

         println!("I MIN Y {:?} {:?}", segment_index, min_y);

         if min_y != prev_y {
            println!("HOR {:?}", min_y);
            prev_y = min_y;
         }
      }
   }

   fn transfer_segments(&mut self) {
      self.segments_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.segments[self.segments_end] = Segment {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.segments_end += 1;
         }
      }

      println!("SEGMENTS {:?}", &self.segments[..self.segments_end]);
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_segments();

      self.eval_segments_min_max_y();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<commit_msg>Clip Segment renamed to Section<commit_after>extern crate polydraw;

use std::cmp::Ordering;
use std::i64;

use polydraw::geom::point::Point;
use polydraw::{Application, Renderer, Frame};
use polydraw::raster::{Scene, Rasterizer, EdgeType, Poly, create_default_vec};

#[derive(Debug, Clone, Copy)]
pub struct Edge {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
}

impl Edge {
   #[inline]
   pub fn new(edge_type: EdgeType, x1: i64, y1: i64, x2: i64, y2: i64) -> Self {
      Edge {
         edge_type: edge_type,
         p1: Point::new(x1, y1),
         p2: Point::new(x2, y2),
      }
   }

   #[inline]
   pub fn vert_top(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVT, x1, y1, x2, y2)
   }

   #[inline]
   pub fn vert_bottom(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LVB, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn hori_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LHL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn top_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LTL, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_right(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBR, x1, y1, x2, y2)
   }

   #[inline]
   pub fn bottom_left(x1: i64, y1: i64, x2: i64, y2: i64) -> Edge {
      Edge::new(EdgeType::LBL, x1, y1, x2, y2)
   }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct Section {
   pub edge_type: EdgeType,
   pub p1: Point,
   pub p2: Point,
   pub edge: usize,
   pub poly: usize,
}

struct ClipRenderer {
   rasterizer: Rasterizer,
   div_per_pixel: i64,

   edges: Vec<Edge>,
   polys: Vec<Poly>,

   sections: Vec<Section>,
   sections_end: usize,

   sections_min_y: Vec<i64>,
   sections_max_y: Vec<i64>,
   sections_order: Vec<usize>,
}

impl ClipRenderer {
   fn new() -> Self {
      let edges = vec![
         Edge::top_left(5, 1, 1, 6),       // 0
         Edge::top_right(1, 6, 8, 9),      // 1
         Edge::bottom_right(8, 9, 9, 6),   // 2
         Edge::bottom_left(9, 6, 5, 1),    // 3
         Edge::top_right(1, 1, 3, 8),      // 4
         Edge::bottom_right(3, 8, 10, 4),  // 5
         Edge::bottom_left(10, 4, 1, 1),   // 6
      ];

      let polys = vec![
         Poly::new(0, 4, 0),    // 0
         Poly::new(4, 7, 1),    // 1
      ];

      let sections = create_default_vec(65536);

      let sections_min_y = create_default_vec(65536);
      let sections_max_y = create_default_vec(65536);
      let sections_order = create_default_vec(65536);

      ClipRenderer {
         rasterizer: Rasterizer::new(),
         div_per_pixel: 1000,

         edges: edges,
         polys: polys,

         sections: sections,
         sections_end: 0,

         sections_min_y: sections_min_y,
         sections_max_y: sections_max_y,
         sections_order: sections_order,
      }
   }

   fn create_scene(&self) -> Scene {
      let points = vec![];

      let segments = vec![];

      let circles = vec![];

      let edges = vec![];

      let polys = vec![];

      let colors = vec![];

      Scene {
         points: points,
         segments: segments,
         circles: circles,
         edges: edges,
         polys: polys,
         colors: colors,
      }
   }

   fn eval_sections_min_max_y(&mut self) {
      for section_index in 0..self.sections_end {
         let ref section = self.sections[section_index];

         let mut min_y = i64::MAX;
         let mut max_y = i64::MIN;

         let (section_min_y, section_max_y) = if section.edge_type.reversed() {
            (section.p2.y, section.p1.y)
         } else {
            (section.p1.y, section.p2.y)
         };

         if section_min_y < min_y  {
            min_y = section_min_y;
         }

         if section_max_y > max_y {
            max_y = section_max_y;
         }

         self.sections_min_y[section_index] = min_y;
         self.sections_max_y[section_index] = max_y;
         self.sections_order[section_index] = section_index;
      }

      self.sort_sections_order();

      println!("MIN Y {:?}", &self.sections_min_y[..self.sections_end]);
      println!("MAX Y {:?}", &self.sections_max_y[..self.sections_end]);
      println!("ORDER {:?}", &self.sections_order[..self.sections_end]);

      self.iterate_sections();

      panic!("END");
   }

   fn sort_sections_order(&mut self) {
      let sections_order = &mut self.sections_order[..self.sections_end];
      let sections_min_y = &self.sections_min_y;
      let sections_max_y = &self.sections_max_y;

      sections_order.sort_by(|a, b| {
         match sections_min_y[*a].cmp(&sections_min_y[*b]) {
            Ordering::Less => Ordering::Less,
            Ordering::Greater => Ordering::Greater,
            Ordering::Equal => sections_max_y[*a].cmp(&sections_max_y[*b])
         }
      });
   }

   fn iterate_sections(&self) {
      let mut prev_y = i64::MIN;
      for order_index in 0..self.sections_end {
         let section_index = self.sections_order[order_index];
         let min_y = self.sections_min_y[section_index];

         println!("I MIN Y {:?} {:?}", section_index, min_y);

         if min_y != prev_y {
            println!("HOR {:?}", min_y);
            prev_y = min_y;
         }
      }
   }

   fn transfer_sections(&mut self) {
      self.sections_end = 0;

      for poly_index in 0..self.polys.len() {
         let ref poly = self.polys[poly_index];

         for edge_index in poly.start..poly.end {
            let ref edge = self.edges[edge_index];

            self.sections[self.sections_end] = Section {
               edge_type: edge.edge_type,
               p1: edge.p1,
               p2: edge.p2,
               edge: edge_index,
               poly: poly_index,
            };

            self.sections_end += 1;
         }
      }

      println!("SECTIONS {:?}", &self.sections[..self.sections_end]);
   }
}

impl Renderer for ClipRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();

      self.transfer_sections();

      self.eval_sections_min_max_y();

      let scene = self.create_scene();

      self.rasterizer.render(&scene, frame, self.div_per_pixel);
   }
}

fn main() {
   let mut renderer = ClipRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Clip")
      .run();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate arcball;
extern crate cgmath;

use glium::Surface;
use glium::index::PrimitiveType;
use glium::glutin::{self, ElementState, Event, MouseButton, MouseScrollDelta,
                    VirtualKeyCode, WindowEvent};
use cgmath::{Vector3, Vector2};
use arcball::ArcballCamera;

#[derive(Copy, Clone)]
struct Vertex {
    pos: [f32; 3],
    color: [f32; 3],
}
implement_vertex!(Vertex, pos, color);

fn main() {

    let window = glutin::WindowBuilder::new()
        .with_title("Arcball Camera Cube Example");
    let context = glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_depth_buffer(24);
    let mut events_loop = glutin::EventsLoop::new();

    let display =
        glium::Display::new(window, context, &events_loop).expect("failed to create display");

    // Hard-coded cube triangle strip
    let vertex_buffer = glium::VertexBuffer::new(&display,
        &[Vertex { pos: [1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 0.0, 0.0] },

            Vertex { pos: [-1.0, 1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [0.0, 1.0, 0.0] },

            Vertex { pos: [-1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, 1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },

            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },

            Vertex { pos: [1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] },
            Vertex { pos: [-1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] }
        ]
    ).unwrap();
    let index_buffer = glium::index::NoIndices(PrimitiveType::TriangleStrip);

    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 proj_view;

                in vec3 pos;
                in vec3 color;

                out vec3 vcolor;

                void main(void) {
                    gl_Position = proj_view * vec4(pos, 1.0);
                    vcolor = color;
                }
            ",
            fragment: "
                #version 140

                in vec3 vcolor;
                out vec4 color;

                void main(void) {
                    color = vec4(vcolor, 1.0);
                }
            "
        },
    ).unwrap();

    let display_dims = display.get_framebuffer_dimensions();
    let persp_proj = cgmath::perspective(cgmath::Deg(65.0), display_dims.0 as f32 / display_dims.1 as f32,
                                        1.0, 200.0);
    let mut arcball_camera = ArcballCamera::new(Vector3::new(0.0, 0.0, 0.0), 1.0,
                                                [display_dims.0 as f32, display_dims.1 as f32]);

    // Track if left/right mouse is down
    let mut mouse_pressed = [false, false];
    let mut prev_mouse: Option<(f64, f64)> = None;

    loop {
        let mut should_quit = false;
        events_loop.poll_events(|e| match e {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::Closed => should_quit = true,
                WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
                    Some(VirtualKeyCode::Escape) => should_quit = true,
                    _ => {}
                },
                WindowEvent::CursorMoved { position, .. } if prev_mouse.is_none() => {
                    prev_mouse = Some(position);
                }
                WindowEvent::CursorMoved { position, .. } => {
                    let prev = prev_mouse.unwrap();
                    if mouse_pressed[0] {
                        arcball_camera.rotate(
                            Vector2::new(prev.0 as f32, prev.1 as f32),
                            Vector2::new(position.0 as f32, position.1 as f32)
                        );
                    } else if mouse_pressed[1] {
                        let mouse_delta = Vector2::new(
                            (position.0 - prev.0) as f32,
                            (position.1 - prev.1) as f32
                        );
                        arcball_camera.pan(mouse_delta, 0.16);
                    }
                    prev_mouse = Some(position);
                }
                WindowEvent::MouseInput { state, button, .. } => {
                    if button == MouseButton::Left {
                        mouse_pressed[0] = state == ElementState::Pressed;
                    } else if button == MouseButton::Right {
                        mouse_pressed[1] = state == ElementState::Pressed;
                    }
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let y = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(_, y) => y,
                    };
                    arcball_camera.zoom(y, 0.16);
                }
                _ => {}
            },
            _ => {}
        });
        if should_quit {
            return;
        }

        let proj_view: [[f32; 4]; 4] = (persp_proj * arcball_camera.get_mat4()).into();
        let uniforms = uniform! {
            proj_view: proj_view,
        };
        let draw_params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        let mut target = display.draw();
        target.clear_color(0.1, 0.1, 0.1, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &draw_params).unwrap();
        target.finish().unwrap();
    }
}

<commit_msg>example polish<commit_after>#[macro_use]
extern crate glium;
extern crate arcball;
extern crate cgmath;

use glium::Surface;
use glium::index::PrimitiveType;
use glium::glutin::{self, ElementState, Event, MouseButton, MouseScrollDelta,
                    VirtualKeyCode, WindowEvent};
use cgmath::{Vector3, Vector2};
use arcball::ArcballCamera;

#[derive(Copy, Clone)]
struct Vertex {
    pos: [f32; 3],
    color: [f32; 3],
}
implement_vertex!(Vertex, pos, color);

fn main() {

    let window = glutin::WindowBuilder::new()
        .with_title("Arcball Camera Cube Example");
    let context = glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_depth_buffer(24);
    let mut events_loop = glutin::EventsLoop::new();

    let display =
        glium::Display::new(window, context, &events_loop).expect("failed to create display");

    // Hard-coded cube triangle strip
    let vertex_buffer = glium::VertexBuffer::new(&display,
        &[Vertex { pos: [1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 0.0, 0.0] },

            Vertex { pos: [-1.0, 1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [0.0, 1.0, 0.0] },

            Vertex { pos: [-1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, 1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },

            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },

            Vertex { pos: [1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] },
            Vertex { pos: [-1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] }
        ]
    ).unwrap();
    let index_buffer = glium::index::NoIndices(PrimitiveType::TriangleStrip);

    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 proj_view;

                in vec3 pos;
                in vec3 color;

                out vec3 vcolor;

                void main(void) {
                    gl_Position = proj_view * vec4(pos, 1.0);
                    vcolor = color;
                }
            ",
            fragment: "
                #version 140

                in vec3 vcolor;
                out vec4 color;

                void main(void) {
                    color = vec4(vcolor, 1.0);
                }
            "
        },
    ).unwrap();

    let display_dims = display.get_framebuffer_dimensions();
    let persp_proj = cgmath::perspective(cgmath::Deg(65.0), display_dims.0 as f32 / display_dims.1 as f32,
                                        1.0, 200.0);
    let mut arcball_camera = ArcballCamera::new(Vector3::new(0.0, 0.0, 0.0), 1.0,
                                                [display_dims.0 as f32, display_dims.1 as f32]);

    // Track if left/right mouse is down
    let mut mouse_pressed = [false, false];
    let mut prev_mouse = None;

    loop {
        let mut should_quit = false;
        events_loop.poll_events(|e| match e {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::Closed => should_quit = true,
                WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
                    Some(VirtualKeyCode::Escape) => should_quit = true,
                    _ => {}
                },
                WindowEvent::CursorMoved { position, .. } if prev_mouse.is_none() => {
                    prev_mouse = Some(position);
                }
                WindowEvent::CursorMoved { position, .. } => {
                    let prev = prev_mouse.unwrap();
                    if mouse_pressed[0] {
                        arcball_camera.rotate(
                            Vector2::new(prev.0 as f32, prev.1 as f32),
                            Vector2::new(position.0 as f32, position.1 as f32)
                        );
                    } else if mouse_pressed[1] {
                        let mouse_delta = Vector2::new(
                            (position.0 - prev.0) as f32,
                            (position.1 - prev.1) as f32
                        );
                        arcball_camera.pan(mouse_delta, 0.16);
                    }
                    prev_mouse = Some(position);
                }
                WindowEvent::MouseInput { state, button, .. } => {
                    if button == MouseButton::Left {
                        mouse_pressed[0] = state == ElementState::Pressed;
                    } else if button == MouseButton::Right {
                        mouse_pressed[1] = state == ElementState::Pressed;
                    }
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let y = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(_, y) => y,
                    };
                    arcball_camera.zoom(y, 0.16);
                }
                _ => {}
            },
            _ => {}
        });
        if should_quit {
            return;
        }

        let proj_view: [[f32; 4]; 4] = (persp_proj * arcball_camera.get_mat4()).into();
        let uniforms = uniform! {
            proj_view: proj_view,
        };
        let draw_params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        let mut target = display.draw();
        target.clear_color(0.1, 0.1, 0.1, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &draw_params).unwrap();
        target.finish().unwrap();
    }
}

<|endoftext|>