<commit_before>use crate::Key;
use combine::easy::Errors as ParseError;
use combine::stream::easy::Error;
use combine::stream::position::SourcePosition;
use itertools::Itertools;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result};

/// Type representing a TOML parse error
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TomlError {
    message: String,
}

impl TomlError {
    pub(crate) fn new(error: ParseError<u8, &[u8], usize>, input: &[u8]) -> Self {
        Self {
            message: format!("{}", FancyError::new(error, input)),
        }
    }

    pub(crate) fn from_unparsed(pos: usize, input: &[u8]) -> Self {
        Self::new(
            ParseError::new(pos, CustomError::UnparsedLine.into()),
            input,
        )
    }

    pub(crate) fn custom(message: String) -> Self {
        Self { message }
    }
}

/// Displays a TOML parse error
///
/// # Example
///
/// TOML parse error at line 1, column 10
///   |
/// 1 | 00:32:00.a999999
///   |          ^
/// Unexpected `a`
/// Expected `digit`
/// While parsing a Time
/// While parsing a Date-Time
impl Display for TomlError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "{}", self.message)
    }
}

impl StdError for TomlError {
    fn description(&self) -> &'static str {
        "TOML parse error"
    }
}

#[derive(Debug)]
pub(crate) struct FancyError<'a> {
    errors: Vec<Error<char, String>>,
    position: SourcePosition,
    input: &'a [u8],
}

impl<'a> FancyError<'a> {
    pub(crate) fn new(error: ParseError<u8, &'a [u8], usize>, input: &'a [u8]) -> Self {
        let position = translate_position(input, error.position);
        let errors: Vec<_> = error
            .errors
            .into_iter()
            .map(|e| {
                e.map_token(char::from)
                    .map_range(|s| String::from_utf8_lossy(s).into_owned())
            })
            .collect();
        Self {
            errors,
            position,
            input,
        }
    }
}

impl<'a> Display for FancyError<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        let SourcePosition { line, column } = self.position;

        let offset = line.to_string().len();
        let content = self
            .input
            .split(|b| *b == b'\n')
            .nth((line - 1) as usize)
            .expect("line");
        let content = String::from_utf8_lossy(content);

        writeln!(f, "TOML parse error at line {}, column {}", line, column)?;

        //   |
        for _ in 0..=offset {
            write!(f, " ")?;
        }
        writeln!(f, "|")?;

        // 1 | 00:32:00.a999999
        write!(f, "{} | ", line)?;
        writeln!(f, "{}", content)?;

        //   |          ^
        for _ in 0..=offset {
            write!(f, " ")?;
        }
        write!(f, "|")?;
        for _ in 0..column {
            write!(f, " ")?;
        }
        writeln!(f, "^")?;

        Error::fmt_errors(self.errors.as_ref(), f)
    }
}

fn translate_position(input: &[u8], index: usize) -> SourcePosition {
    if input.is_empty() {
        return SourcePosition {
            line: 1,
            column: (index + 1) as i32,
        };
    }

    let safe_index = index.min(input.len() - 1);
    let column_offset = index - safe_index;
    let index = safe_index;

    let nl = input[0..index]
        .iter()
        .rev()
        .enumerate()
        .find(|(_, b)| **b == b'\n')
        .map(|(nl, _)| index - nl - 1);
    let line_start = match nl {
        Some(nl) => nl + 1,
        None => 0,
    };
    let line = input[0..line_start].iter().filter(|b| **b == b'\n').count() + 1;
    let line = line as i32;

    let column = std::str::from_utf8(&input[line_start..=index])
        .map(|s| s.chars().count())
        .unwrap_or_else(|_| index - line_start + 1);
    let column = (column + column_offset) as i32;

    SourcePosition { line, column }
}

#[cfg(test)]
mod test_translate_position {
    use super::*;

    #[test]
    fn empty() {
        let input = b"";
        let index = 0;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 1 });
    }

    #[test]
    fn start() {
        let input = b"Hello";
        let index = 0;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 1 });
    }

    #[test]
    fn end() {
        let input = b"Hello";
        let index = input.len() - 1;
        let position = translate_position(&input[..], index);
        assert_eq!(
            position,
            SourcePosition {
                line: 1,
                column: input.len() as i32
            }
        );
    }

    #[test]
    fn after() {
        let input = b"Hello";
        let index = input.len();
        let position = translate_position(&input[..], index);
        assert_eq!(
            position,
            SourcePosition {
                line: 1,
                column: (input.len() + 1) as i32
            }
        );
    }

    #[test]
    fn first_line() {
        let input = b"Hello\nWorld\n";
        let index = 2;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 3 });
    }

    #[test]
    fn end_of_line() {
        let input = b"Hello\nWorld\n";
        let index = 5;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 6 });
    }

    #[test]
    fn start_of_second_line() {
        let input = b"Hello\nWorld\n";
        let index = 6;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 2, column: 1 });
    }

    #[test]
    fn second_line() {
        let input = b"Hello\nWorld\n";
        let index = 8;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 2, column: 3 });
    }
}

#[derive(Debug, Clone)]
pub(crate) enum CustomError {
    DuplicateKey {
        key: String,
        table: Option<Vec<Key>>,
    },
    DottedKeyExtendWrongType {
        key: Vec<Key>,
        actual: &'static str,
    },
    InvalidHexEscape(u32),
    UnparsedLine,
    OutOfRange,
}

impl StdError for CustomError {
    fn description(&self) -> &'static str {
        "TOML parse error"
    }
}

impl Display for CustomError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        match self {
            CustomError::DuplicateKey { key, table } => {
                if let Some(table) = table {
                    if table.is_empty() {
                        writeln!(f, "Duplicate key `{}` in document root", key)
                    } else {
                        let path = table.iter().join(".");
                        writeln!(f, "Duplicate key `{}` in table `{}`", key, path)
                    }
                } else {
                    writeln!(f, "Duplicate key `{}`", key)
                }
            }
            CustomError::DottedKeyExtendWrongType { key, actual } => {
                let path = key.iter().join(".");
                writeln!(
                    f,
                    "Dotted key `{}` attempted to extend non-table type ({})",
                    path, actual
                )
            }
            CustomError::InvalidHexEscape(h) => {
                writeln!(f, "Invalid hex escape code: {:x} ", h)
            }
            CustomError::UnparsedLine => writeln!(f, "Could not parse the line"),
            CustomError::OutOfRange => writeln!(f, "Value is out of range"),
        }
    }
}
<commit_msg>feat(parser): Expose line_col in errors<commit_after>use crate::Key;
use combine::easy::Errors as ParseError;
use combine::stream::easy::Error;
use combine::stream::position::SourcePosition;
use itertools::Itertools;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result};

/// Type representing a TOML parse error
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TomlError {
    message: String,
    line_col: Option<(usize, usize)>,
}

impl TomlError {
    pub(crate) fn new(error: ParseError<u8, &[u8], usize>, input: &[u8]) -> Self {
        let fancy = FancyError::new(error, input);
        let message = fancy.to_string();
        let line_col = Some((fancy.position.line as usize, fancy.position.column as usize));
        Self { message, line_col }
    }

    pub(crate) fn from_unparsed(pos: usize, input: &[u8]) -> Self {
        Self::new(
            ParseError::new(pos, CustomError::UnparsedLine.into()),
            input,
        )
    }

    pub(crate) fn custom(message: String) -> Self {
        Self {
            message,
            line_col: None,
        }
    }

    /// Produces a (line, column) pair of the position of the error if available
    ///
    /// All indexes are 1-based.
    pub fn line_col(&self) -> Option<(usize, usize)> {
        self.line_col
    }
}

/// Displays a TOML parse error
///
/// # Example
///
/// TOML parse error at line 1, column 10
///   |
/// 1 | 00:32:00.a999999
///   |          ^
/// Unexpected `a`
/// Expected `digit`
/// While parsing a Time
/// While parsing a Date-Time
impl Display for TomlError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "{}", self.message)
    }
}

impl StdError for TomlError {
    fn description(&self) -> &'static str {
        "TOML parse error"
    }
}

#[derive(Debug)]
pub(crate) struct FancyError<'a> {
    errors: Vec<Error<char, String>>,
    position: SourcePosition,
    input: &'a [u8],
}

impl<'a> FancyError<'a> {
    pub(crate) fn new(error: ParseError<u8, &'a [u8], usize>, input: &'a [u8]) -> Self {
        let position = translate_position(input, error.position);
        let errors: Vec<_> = error
            .errors
            .into_iter()
            .map(|e| {
                e.map_token(char::from)
                    .map_range(|s| String::from_utf8_lossy(s).into_owned())
            })
            .collect();
        Self {
            errors,
            position,
            input,
        }
    }
}

impl<'a> Display for FancyError<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        let SourcePosition { line, column } = self.position;

        let offset = line.to_string().len();
        let content = self
            .input
            .split(|b| *b == b'\n')
            .nth((line - 1) as usize)
            .expect("line");
        let content = String::from_utf8_lossy(content);

        writeln!(f, "TOML parse error at line {}, column {}", line, column)?;

        //   |
        for _ in 0..=offset {
            write!(f, " ")?;
        }
        writeln!(f, "|")?;

        // 1 | 00:32:00.a999999
        write!(f, "{} | ", line)?;
        writeln!(f, "{}", content)?;

        //   |          ^
        for _ in 0..=offset {
            write!(f, " ")?;
        }
        write!(f, "|")?;
        for _ in 0..column {
            write!(f, " ")?;
        }
        writeln!(f, "^")?;

        Error::fmt_errors(self.errors.as_ref(), f)
    }
}

fn translate_position(input: &[u8], index: usize) -> SourcePosition {
    if input.is_empty() {
        return SourcePosition {
            line: 1,
            column: (index + 1) as i32,
        };
    }

    let safe_index = index.min(input.len() - 1);
    let column_offset = index - safe_index;
    let index = safe_index;

    let nl = input[0..index]
        .iter()
        .rev()
        .enumerate()
        .find(|(_, b)| **b == b'\n')
        .map(|(nl, _)| index - nl - 1);
    let line_start = match nl {
        Some(nl) => nl + 1,
        None => 0,
    };
    let line = input[0..line_start].iter().filter(|b| **b == b'\n').count() + 1;
    let line = line as i32;

    let column = std::str::from_utf8(&input[line_start..=index])
        .map(|s| s.chars().count())
        .unwrap_or_else(|_| index - line_start + 1);
    let column = (column + column_offset) as i32;

    SourcePosition { line, column }
}

#[cfg(test)]
mod test_translate_position {
    use super::*;

    #[test]
    fn empty() {
        let input = b"";
        let index = 0;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 1 });
    }

    #[test]
    fn start() {
        let input = b"Hello";
        let index = 0;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 1 });
    }

    #[test]
    fn end() {
        let input = b"Hello";
        let index = input.len() - 1;
        let position = translate_position(&input[..], index);
        assert_eq!(
            position,
            SourcePosition {
                line: 1,
                column: input.len() as i32
            }
        );
    }

    #[test]
    fn after() {
        let input = b"Hello";
        let index = input.len();
        let position = translate_position(&input[..], index);
        assert_eq!(
            position,
            SourcePosition {
                line: 1,
                column: (input.len() + 1) as i32
            }
        );
    }

    #[test]
    fn first_line() {
        let input = b"Hello\nWorld\n";
        let index = 2;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 3 });
    }

    #[test]
    fn end_of_line() {
        let input = b"Hello\nWorld\n";
        let index = 5;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 1, column: 6 });
    }

    #[test]
    fn start_of_second_line() {
        let input = b"Hello\nWorld\n";
        let index = 6;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 2, column: 1 });
    }

    #[test]
    fn second_line() {
        let input = b"Hello\nWorld\n";
        let index = 8;
        let position = translate_position(&input[..], index);
        assert_eq!(position, SourcePosition { line: 2, column: 3 });
    }
}

#[derive(Debug, Clone)]
pub(crate) enum CustomError {
    DuplicateKey {
        key: String,
        table: Option<Vec<Key>>,
    },
    DottedKeyExtendWrongType {
        key: Vec<Key>,
        actual: &'static str,
    },
    InvalidHexEscape(u32),
    UnparsedLine,
    OutOfRange,
}

impl StdError for CustomError {
    fn description(&self) -> &'static str {
        "TOML parse error"
    }
}

impl Display for CustomError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        match self {
            CustomError::DuplicateKey { key, table } => {
                if let Some(table) = table {
                    if table.is_empty() {
                        writeln!(f, "Duplicate key `{}` in document root", key)
                    } else {
                        let path = table.iter().join(".");
                        writeln!(f, "Duplicate key `{}` in table `{}`", key, path)
                    }
                } else {
                    writeln!(f, "Duplicate key `{}`", key)
                }
            }
            CustomError::DottedKeyExtendWrongType { key, actual } => {
                let path = key.iter().join(".");
                writeln!(
                    f,
                    "Dotted key `{}` attempted to extend non-table type ({})",
                    path, actual
                )
            }
            CustomError::InvalidHexEscape(h) => {
                writeln!(f, "Invalid hex escape code: {:x} ", h)
            }
            CustomError::UnparsedLine => writeln!(f, "Could not parse the line"),
            CustomError::OutOfRange => writeln!(f, "Value is out of range"),
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "windows")]

use std::ptr;

use winit;

use ContextError;
use CreationError;
use GlAttributes;
use GlRequest;
use Api;
use PixelFormat;
use PixelFormatRequirements;

use winapi;

use api::wgl::Context as WglContext;
use api::egl::Context as EglContext;
use api::egl::ffi::egl::Egl;
use api::egl;

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

pub enum Context {
    Egl(EglContext),
    Wgl(WglContext),
}

impl Context {

    /// See the docs in the crate root file.
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
        egl: Option<&Egl>,
    ) -> Result<(winit::Window, Self), CreationError>
    {
        let window = try!(window_builder.build(events_loop));
        let gl_attr = gl_attr.clone().map_sharing(|ctxt| {
            match *ctxt {
                Context::Wgl(ref c) => c.get_hglrc(),
                Context::Egl(_) => unimplemented!(),        // FIXME:
            }
        });
        let context_result = unsafe {
            let w = window.platform_window() as winapi::HWND;
            match gl_attr.version {
                GlRequest::Specific(Api::OpenGlEs, (_major, _minor)) => {
                    if let Some(egl) = egl {
                        if let Ok(c) =
                               EglContext::new(egl.clone(),
                                               &pf_reqs,
                                               &gl_attr.clone().map_sharing(|_| unimplemented!()),
                                               egl::NativeDisplay::Other(Some(ptr::null())))
                            .and_then(|p| p.finish(w)) {
                            Ok(Context::Egl(c))
                        } else {
                            WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl)
                        }

                    } else {
                        // falling back to WGL, which is always available
                        WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl)
                    }
                }
                _ => WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl),
            }
        };
        context_result.map(|context| (window, context))
    }

    #[inline]
    pub fn resize(&self, _width: u32, _height: u32) {
        // Method is for API consistency.
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        match *self {
            Context::Wgl(ref c) => c.make_current(),
            Context::Egl(ref c) => c.make_current(),
        }
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        match *self {
            Context::Wgl(ref c) => c.is_current(),
            Context::Egl(ref c) => c.is_current(),
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        match *self {
            Context::Wgl(ref c) => c.get_proc_address(addr),
            Context::Egl(ref c) => c.get_proc_address(addr),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        match *self {
            Context::Wgl(ref c) => c.swap_buffers(),
            Context::Egl(ref c) => c.swap_buffers(),
        }
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        match *self {
            Context::Wgl(ref c) => c.get_api(),
            Context::Egl(ref c) => c.get_api(),
        }
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        match *self {
            Context::Wgl(ref c) => c.get_pixel_format(),
            Context::Egl(ref c) => c.get_pixel_format(),
        }
    }
}
<commit_msg>Move fixme comment in windows context impl<commit_after>#![cfg(target_os = "windows")]

use std::ptr;

use winit;

use ContextError;
use CreationError;
use GlAttributes;
use GlRequest;
use Api;
use PixelFormat;
use PixelFormatRequirements;

use winapi;

use api::wgl::Context as WglContext;
use api::egl::Context as EglContext;
use api::egl::ffi::egl::Egl;
use api::egl;

unsafe impl Send for Context {}
unsafe impl Sync for Context {}

pub enum Context {
    Egl(EglContext),
    Wgl(WglContext),
}

impl Context {

    /// See the docs in the crate root file.
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
        egl: Option<&Egl>,
    ) -> Result<(winit::Window, Self), CreationError>
    {
        let window = try!(window_builder.build(events_loop));
        let gl_attr = gl_attr.clone().map_sharing(|ctxt| {
            match *ctxt {
                Context::Wgl(ref c) => c.get_hglrc(),
                // FIXME
                Context::Egl(_) => unimplemented!(),
            }
        });
        let context_result = unsafe {
            let w = window.platform_window() as winapi::HWND;
            match gl_attr.version {
                GlRequest::Specific(Api::OpenGlEs, (_major, _minor)) => {
                    if let Some(egl) = egl {
                        if let Ok(c) =
                               EglContext::new(egl.clone(),
                                               &pf_reqs,
                                               &gl_attr.clone().map_sharing(|_| unimplemented!()),
                                               egl::NativeDisplay::Other(Some(ptr::null())))
                            .and_then(|p| p.finish(w)) {
                            Ok(Context::Egl(c))
                        } else {
                            WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl)
                        }

                    } else {
                        // falling back to WGL, which is always available
                        WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl)
                    }
                }
                _ => WglContext::new(&pf_reqs, &gl_attr, w).map(Context::Wgl),
            }
        };
        context_result.map(|context| (window, context))
    }

    #[inline]
    pub fn resize(&self, _width: u32, _height: u32) {
        // Method is for API consistency.
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        match *self {
            Context::Wgl(ref c) => c.make_current(),
            Context::Egl(ref c) => c.make_current(),
        }
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        match *self {
            Context::Wgl(ref c) => c.is_current(),
            Context::Egl(ref c) => c.is_current(),
        }
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        match *self {
            Context::Wgl(ref c) => c.get_proc_address(addr),
            Context::Egl(ref c) => c.get_proc_address(addr),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        match *self {
            Context::Wgl(ref c) => c.swap_buffers(),
            Context::Egl(ref c) => c.swap_buffers(),
        }
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        match *self {
            Context::Wgl(ref c) => c.get_api(),
            Context::Egl(ref c) => c.get_api(),
        }
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        match *self {
            Context::Wgl(ref c) => c.get_pixel_format(),
            Context::Egl(ref c) => c.get_pixel_format(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::FuzzyEq;
use core::num::{NumCast, One, Zero};

pub fn Matrix4<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero>(
        m11: T, m12: T, m13: T, m14: T,
        m21: T, m22: T, m23: T, m24: T,
        m31: T, m32: T, m33: T, m34: T,
        m41: T, m42: T, m43: T, m44: T)
     -> Matrix4<T> {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

pub struct Matrix4<T> {
    m11: T, m12: T, m13: T, m14: T,
    m21: T, m22: T, m23: T, m24: T,
    m31: T, m32: T, m33: T, m34: T,
    m41: T, m42: T, m43: T, m44: T,
}

pub impl<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero> Matrix4<T> {
    fn fuzzy_eq(&self, other: &Matrix4<T>) -> bool {
        self.m11.fuzzy_eq(&other.m11) && self.m12.fuzzy_eq(&other.m12) &&
        self.m13.fuzzy_eq(&other.m13) && self.m14.fuzzy_eq(&other.m14) &&
        self.m21.fuzzy_eq(&other.m21) && self.m22.fuzzy_eq(&other.m22) &&
        self.m23.fuzzy_eq(&other.m23) && self.m24.fuzzy_eq(&other.m24) &&
        self.m31.fuzzy_eq(&other.m31) && self.m32.fuzzy_eq(&other.m32) &&
        self.m33.fuzzy_eq(&other.m33) && self.m34.fuzzy_eq(&other.m34) &&
        self.m41.fuzzy_eq(&other.m41) && self.m42.fuzzy_eq(&other.m42) &&
        self.m43.fuzzy_eq(&other.m43) && self.m44.fuzzy_eq(&other.m44)
    }

    fn mul(&self, m: &Matrix4<T>) -> Matrix4<T> {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    fn mul_s(&self, x: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    fn scale(&self, x: T, y: T, z: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12,     self.m13,     self.m14,
                self.m21,     self.m22 * y, self.m23,     self.m24,
                self.m31,     self.m32,     self.m33 * z, self.m34,
                self.m41,     self.m42,     self.m43,     self.m44)
    }

    fn to_array(&self) -> [T, ..16] {
        [
            self.m11, self.m12, self.m13, self.m14,
            self.m21, self.m22, self.m23, self.m24,
            self.m31, self.m32, self.m33, self.m34,
            self.m41, self.m42, self.m43, self.m44
        ]
    }

    fn translate(&self, x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1) = (Zero::zero(), One::one());
        let matrix = Matrix4(_1, _0, _0, _0,
                             _0, _1, _0, _0,
                             _0, _0, _1, _0,
                             x,  y,  z,  _1);

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Add<T,T> + Copy + Div<T,T> + FuzzyEq<T> + Mul<T,T> + Neg<T> + NumCast + One +
               Sub<T,T> + Zero>
        (left: T,
         right: T,
         bottom: T,
         top: T,
         near: T,
         far: T)
      -> Matrix4<T> {
    let _2: T = num::cast(2);
    let _1: T = One::one();
    let _0: T = Zero::zero();

    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(_2 / (right - left), _0,                  _0,                 _0,
            _0,                  _2 / (top - bottom), _0,                 _0,
            _0,                  _0,                  -_2 / (far - near), _0,
            tx,                  ty,                  tz,                 _1)
}

pub fn identity<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero>() -> Matrix4<T> {
    let (_0, _1) = (Zero::zero(), One::one());
    Matrix4(_1, _0, _0, _0,
            _0, _1, _0, _0,
            _0, _0, _1, _0,
            _0, _0, _0, _1)
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0, 1.0, 0.1, 1.0);
    let (near, far) = (-1.0, 1.0);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result=%? expected=%?", result, expected);
    assert!(result.fuzzy_eq(&expected));
}

<commit_msg>Change Div to Quot.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::FuzzyEq;
use core::num::{NumCast, One, Zero};

pub fn Matrix4<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero>(
        m11: T, m12: T, m13: T, m14: T,
        m21: T, m22: T, m23: T, m24: T,
        m31: T, m32: T, m33: T, m34: T,
        m41: T, m42: T, m43: T, m44: T)
     -> Matrix4<T> {
    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

pub struct Matrix4<T> {
    m11: T, m12: T, m13: T, m14: T,
    m21: T, m22: T, m23: T, m24: T,
    m31: T, m32: T, m33: T, m34: T,
    m41: T, m42: T, m43: T, m44: T,
}

pub impl<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero> Matrix4<T> {
    fn fuzzy_eq(&self, other: &Matrix4<T>) -> bool {
        self.m11.fuzzy_eq(&other.m11) && self.m12.fuzzy_eq(&other.m12) &&
        self.m13.fuzzy_eq(&other.m13) && self.m14.fuzzy_eq(&other.m14) &&
        self.m21.fuzzy_eq(&other.m21) && self.m22.fuzzy_eq(&other.m22) &&
        self.m23.fuzzy_eq(&other.m23) && self.m24.fuzzy_eq(&other.m24) &&
        self.m31.fuzzy_eq(&other.m31) && self.m32.fuzzy_eq(&other.m32) &&
        self.m33.fuzzy_eq(&other.m33) && self.m34.fuzzy_eq(&other.m34) &&
        self.m41.fuzzy_eq(&other.m41) && self.m42.fuzzy_eq(&other.m42) &&
        self.m43.fuzzy_eq(&other.m43) && self.m44.fuzzy_eq(&other.m44)
    }

    fn mul(&self, m: &Matrix4<T>) -> Matrix4<T> {
        Matrix4(m.m11*self.m11 + m.m12*self.m21 + m.m13*self.m31 + m.m14*self.m41,
                m.m11*self.m12 + m.m12*self.m22 + m.m13*self.m32 + m.m14*self.m42,
                m.m11*self.m13 + m.m12*self.m23 + m.m13*self.m33 + m.m14*self.m43,
                m.m11*self.m14 + m.m12*self.m24 + m.m13*self.m34 + m.m14*self.m44,
                m.m21*self.m11 + m.m22*self.m21 + m.m23*self.m31 + m.m24*self.m41,
                m.m21*self.m12 + m.m22*self.m22 + m.m23*self.m32 + m.m24*self.m42,
                m.m21*self.m13 + m.m22*self.m23 + m.m23*self.m33 + m.m24*self.m43,
                m.m21*self.m14 + m.m22*self.m24 + m.m23*self.m34 + m.m24*self.m44,
                m.m31*self.m11 + m.m32*self.m21 + m.m33*self.m31 + m.m34*self.m41,
                m.m31*self.m12 + m.m32*self.m22 + m.m33*self.m32 + m.m34*self.m42,
                m.m31*self.m13 + m.m32*self.m23 + m.m33*self.m33 + m.m34*self.m43,
                m.m31*self.m14 + m.m32*self.m24 + m.m33*self.m34 + m.m34*self.m44,
                m.m41*self.m11 + m.m42*self.m21 + m.m43*self.m31 + m.m44*self.m41,
                m.m41*self.m12 + m.m42*self.m22 + m.m43*self.m32 + m.m44*self.m42,
                m.m41*self.m13 + m.m42*self.m23 + m.m43*self.m33 + m.m44*self.m43,
                m.m41*self.m14 + m.m42*self.m24 + m.m43*self.m34 + m.m44*self.m44)
    }

    fn mul_s(&self, x: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
                self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
                self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
                self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x)
    }

    fn scale(&self, x: T, y: T, z: T) -> Matrix4<T> {
        Matrix4(self.m11 * x, self.m12,     self.m13,     self.m14,
                self.m21,     self.m22 * y, self.m23,     self.m24,
                self.m31,     self.m32,     self.m33 * z, self.m34,
                self.m41,     self.m42,     self.m43,     self.m44)
    }

    fn to_array(&self) -> [T, ..16] {
        [
            self.m11, self.m12, self.m13, self.m14,
            self.m21, self.m22, self.m23, self.m24,
            self.m31, self.m32, self.m33, self.m34,
            self.m41, self.m42, self.m43, self.m44
        ]
    }

    fn translate(&self, x: T, y: T, z: T) -> Matrix4<T> {
        let (_0, _1) = (Zero::zero(), One::one());
        let matrix = Matrix4(_1, _0, _0, _0,
                             _0, _1, _0, _0,
                             _0, _0, _1, _0,
                             x,  y,  z,  _1);

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Add<T,T> + Copy + Quot<T,T> + FuzzyEq<T> + Mul<T,T> + Neg<T> + NumCast + One +
               Sub<T,T> + Zero>
        (left: T,
         right: T,
         bottom: T,
         top: T,
         near: T,
         far: T)
      -> Matrix4<T> {
    let _2: T = num::cast(2);
    let _1: T = One::one();
    let _0: T = Zero::zero();

    let tx = -((right + left) / (right - left));
    let ty = -((top + bottom) / (top - bottom));
    let tz = -((far + near) / (far - near));

    Matrix4(_2 / (right - left), _0,                  _0,                 _0,
            _0,                  _2 / (top - bottom), _0,                 _0,
            _0,                  _0,                  -_2 / (far - near), _0,
            tx,                  ty,                  tz,                 _1)
}

pub fn identity<T:Add<T,T> + Copy + FuzzyEq<T> + Mul<T,T> + One + Zero>() -> Matrix4<T> {
    let (_0, _1) = (Zero::zero(), One::one());
    Matrix4(_1, _0, _0, _0,
            _0, _1, _0, _0,
            _0, _0, _1, _0,
            _0, _0, _0, _1)
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0, 1.0, 0.1, 1.0);
    let (near, far) = (-1.0, 1.0);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result=%? expected=%?", result, expected);
    assert!(result.fuzzy_eq(&expected));
}

<|endoftext|>


<commit_before>use uuid::Uuid;
use enums::*;
use std::collections::HashMap;
use traits::AlbumTrait;

#[derive(Debug, Clone)]
pub struct ReleaseGroup {
    pub title: String,
    pub release_date: String,
    pub id: Uuid,
    pub artist: Uuid,
    pub primary_type: AlbumMainType,
    pub secondary_types: Vec<AlbumSecondaryType>
}

impl ReleaseGroup {
    pub fn new(title: String, release_date: String, id: Uuid, artist: Uuid, primary_type: AlbumMainType, secondary_types: Vec<AlbumSecondaryType>) -> ReleaseGroup {
        ReleaseGroup {
            title: title,
            release_date: release_date,
            id: id,
            artist: artist,
            primary_type: primary_type,
            secondary_types: secondary_types
        }
    }
}

impl PartialEq for ReleaseGroup {
    fn eq(&self, other: &ReleaseGroup) -> bool {
        self.id == other.id && self.artist == other.artist
    }
}

impl AlbumTrait for super::MusicBrainz {
    /// Searches MusicBrainz for release groups based on the search query.
    ///
    /// Returns a `Vec` containing the release groups matching the search query.
    /// If no release groups were found, returns an empty `Vec`.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use musicbrainz::*;
    /// # use std::collections::HashMap;
    /// let musicbrainz = MusicBrainz::new();
    /// let mut query = HashMap::new();
    ///
    /// query.insert("query", "metallica");
    /// let search_results = musicbrainz.search_album(&mut query);
    ///
    /// assert_eq!(search_results[0].id.hyphenated().to_string(), "e8f70201-8899-3f0c-9e07-5d6495bc8046");
    /// ```
    fn search_album(&self, params: &mut HashMap<&str, &str>) -> Vec<ReleaseGroup> {
        let data = self.get("release-group", params).unwrap();

        let count = data["count"].as_i32().unwrap();

        if count == 0 {
            return Vec::new();
        }

        let albums = &data["release-groups"];
        let mut results: Vec<ReleaseGroup> = Vec::new();

        for album in albums.members() {
            if album["score"] == "100" {
                let id = Uuid::parse_str(album["id"].as_str()
                    .expect("failed to parse artist ID as slice"))
                    .expect("failed to parse artist ID as Uuid");
                let secondary_types: Vec<AlbumSecondaryType> = Vec::new();
                let artist_credits = &album["artist-credit"];

                results.push(ReleaseGroup::new(
                    album["title"].to_string(),
                    String::new(),
                    id,
                    Uuid::parse_str(artist_credits[0]["artist"]["id"].as_str()
                        .expect("failed to parse artist ID as slice"))
                        .expect("failed to parse artist ID as Uuid"),
                    album["primary-type"].as_str()
                        .expect("failed to parse album primary type as slice")
                        .parse::<AlbumMainType>()
                        .unwrap(),
                    secondary_types
                ))
            }
        }
        results
    }

    /// Lookup a release group by using its MusicBrainz Identifier.
    ///
    fn lookup_album(&self, album_id: Uuid, params: &mut HashMap<&str, &str>) -> Result<ReleaseGroup, String> {
        let mut album_data = self.get(&format!("release-group/{id}", id=&album_id), params).unwrap();

        if !album_data["error"].is_null() {
            let error_msg = album_data["error"].to_string();
            return Err(format!("error looking up release group: {msg}", msg=error_msg));
        }

        let album_type = album_data["primary-type"].as_str()
            .expect("failed to parse release group type as slice")
            .parse::<AlbumMainType>()
            .unwrap();

        let mut secondary_types: Vec<AlbumSecondaryType> = Vec::new();
        if !album_data["secondary-types"].is_null() && !album_data["secondary-types"].is_empty() {
            for secondary_type in album_data["secondary-types"].members() {
                secondary_types.push(
                        secondary_type.as_str()
                        .expect("failed to parse release group secondary type as slice")
                        .parse::<AlbumSecondaryType>()
                        .unwrap()
                );
            }
        }

        let mut artist: Uuid = Uuid::nil();
        if !album_data["artist-credit"].is_null() && !album_data["artist-credit"].is_empty() {
            let artist_credit = album_data["artist-credit"].pop();
            artist = Uuid::parse_str(artist_credit["artist"]["id"].as_str()
                        .expect("failed to parse artist credit ID as slice"))
                        .expect("failed to parse artist credit ID as Uuid");
        }

        Ok(ReleaseGroup::new(
            album_data["title"].to_string(),
            album_data["first-release-date"].to_string(),
            Uuid::parse_str(album_data["id"].as_str()
                .expect("failed to parse release group ID as slice"))
                .expect("failed to parse release group ID as Uuid"),
            artist,
            album_type,
            secondary_types
        ))
    }
}
<commit_msg>Implement Entity for ReleaseGroup<commit_after>use uuid::Uuid;
use enums::*;
use std::collections::HashMap;
use traits::Entity;

#[derive(Debug, Clone)]
pub struct ReleaseGroup {
    pub title: String,
    pub release_date: String,
    pub id: Uuid,
    pub artist: Uuid,
    pub primary_type: AlbumMainType,
    pub secondary_types: Vec<AlbumSecondaryType>
}

impl ReleaseGroup {
    pub fn new(title: String, release_date: String, id: Uuid, artist: Uuid, primary_type: AlbumMainType, secondary_types: Vec<AlbumSecondaryType>) -> ReleaseGroup {
        ReleaseGroup {
            title: title,
            release_date: release_date,
            id: id,
            artist: artist,
            primary_type: primary_type,
            secondary_types: secondary_types
        }
    }
}

impl PartialEq for ReleaseGroup {
    fn eq(&self, other: &ReleaseGroup) -> bool {
        self.id == other.id && self.artist == other.artist
    }
}

impl Entity for ReleaseGroup {
    fn search(&self, client: &super::MusicBrainz, params: &mut HashMap<&str, &str>) -> Vec<Self> {
        let data = client.get("release-group", params).unwrap();

        let count = data["count"].as_i32().unwrap();

        if count == 0 {
            return Vec::new();
        }

        let albums = &data["release-groups"];
        let mut results: Vec<ReleaseGroup> = Vec::new();

        for album in albums.members() {
            if album["score"] == "100" {
                let id = Uuid::parse_str(album["id"].as_str()
                    .expect("failed to parse artist ID as slice"))
                    .expect("failed to parse artist ID as Uuid");
                let secondary_types: Vec<AlbumSecondaryType> = Vec::new();
                let artist_credits = &album["artist-credit"];

                results.push(ReleaseGroup::new(
                    album["title"].to_string(),
                    String::new(),
                    id,
                    Uuid::parse_str(artist_credits[0]["artist"]["id"].as_str()
                        .expect("failed to parse artist ID as slice"))
                        .expect("failed to parse artist ID as Uuid"),
                    album["primary-type"].as_str()
                        .expect("failed to parse album primary type as slice")
                        .parse::<AlbumMainType>()
                        .unwrap(),
                    secondary_types
                ))
            }
        }
        results
    }

    fn lookup(&self, client: &super::MusicBrainz, entity_id: &Uuid, params: &mut HashMap<&str, &str>) -> Result<Self, String> {
        let mut album_data = client.get(&format!("release-group/{id}", id=entity_id), params).unwrap();

        if !album_data["error"].is_null() {
            let error_msg = album_data["error"].to_string();
            return Err(format!("error looking up release group: {msg}", msg=error_msg));
        }

        let album_type = album_data["primary-type"].as_str()
            .expect("failed to parse release group type as slice")
            .parse::<AlbumMainType>()
            .unwrap();

        let mut secondary_types: Vec<AlbumSecondaryType> = Vec::new();
        if !album_data["secondary-types"].is_null() && !album_data["secondary-types"].is_empty() {
            for secondary_type in album_data["secondary-types"].members() {
                secondary_types.push(
                        secondary_type.as_str()
                        .expect("failed to parse release group secondary type as slice")
                        .parse::<AlbumSecondaryType>()
                        .unwrap()
                );
            }
        }

        let mut artist: Uuid = Uuid::nil();
        if !album_data["artist-credit"].is_null() && !album_data["artist-credit"].is_empty() {
            let artist_credit = album_data["artist-credit"].pop();
            artist = Uuid::parse_str(artist_credit["artist"]["id"].as_str()
                        .expect("failed to parse artist credit ID as slice"))
                        .expect("failed to parse artist credit ID as Uuid");
        }

        Ok(ReleaseGroup::new(
            album_data["title"].to_string(),
            album_data["first-release-date"].to_string(),
            Uuid::parse_str(album_data["id"].as_str()
                .expect("failed to parse release group ID as slice"))
                .expect("failed to parse release group ID as Uuid"),
            artist,
            album_type,
            secondary_types
        ))
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/S-Expressions
//
// This implementation isn't based on anything in particular, although it's probably informed by a
// lot of Rust's JSON encoding code.  It should be very fast (both encoding and decoding the toy
// example here takes under a microsecond on my machine) and tries to avoid unnecessary allocation.
//
// In a real implementation, most of this would be private, with only a few visible functions, and
// there would be somewhat nicer signatures (in particular, the fact that ParseContext has to be
// mutable would get annoying in real code pretty quickly, so it would probably be split out).
//
// It supports the ability to read individual atoms, not just lists, although whether this is
// useful is questionable.
//
// Caveats: Does not support symbols vs. non-symbols (it wouldn't be hard, but it would greatly
// complicate setting up our test structure since we'd have to force it to go through functions
// that checked to make sure Symbols couldn't have spaces, or slow down our parser by checking for
// this information each time, which is obnoxious).  Does not support string escaping, because the
// decoding technique doesn't allocate extra space for strings.  Does support numbers, but only
// float types (supporting more types is possible but would complicate the code significantly).
//
extern crate arena;
extern crate test;

use arena::TypedArena;

use std::io;
use std::num;
use std::string;

#[deriving(PartialEq,Show)]
// The actual SExp structure.  Supports f64s, lists, and string literals.  Note that it takes
// everything by reference, rather than owning it--this is mostly done just so we can allocate
// SExps statically (since we don't have to call Vec).  It does complicate the code a bit,
// requiring us to have a ParseContext that holds an arena where lists are actually allocated.
enum SExp<'a> {
    F64(f64), // Float literal: 0.5
    List(&'a [SExp<'a>]), // List of SExps: ( a b c)
    Str(&'a str), // Plain old string literal: "abc"
}

// Errors that can be thrown by the parser.
#[deriving(PartialEq,Show)]
enum Error {
    NoReprForFloat, // If the float is NaN, Infinity, etc.
    UnterminatedStringLiteral, // Missing an end double quote during string parsing
    IoError(io::IoError), // Some other kind of I/O error
    IncorrectCloseDelimiter, // ) appeared where it shouldn't (usually as the first token)
    UnexpectedEOF, // Usually means a missing ), but could also mean there were no tokens at all.
    ExpectedEOF, // More tokens after the list is finished, or after a literal if there is no list.
}

// Tokens returned from the token stream.
#[deriving(PartialEq)]
enum Token<'a> {
    ListStart, // Left parenthesis
    ListEnd, // Right parenthesis
    Literal(SExp<'a>), // String or float literal, quotes removed.
    EOF, // Stream is out of tokens.
}

// An iterator over a string that yields a stream of Tokens.
// Implementation note: it probably seems weird to store first, rest, AND string, since they should
// all be derivable from string.  But see below.
struct Tokens<'a> {
    string: &'a str, // The part of the string that still needs to be parsed
    first: Option<char>, // The first character to parse
    rest: &'a str, // The rest of the string after the first character
}

impl<'a> Tokens<'a> {
    // Initialize a token stream for a given string.
    fn new(string: &str) -> Tokens {
        let (ch, s) = string.slice_shift_char();
        Tokens { string: string, first: ch, rest: s }
    }

    // Utility function to update information in the iterator.  It might not be performant to keep
    // rest cached, but there are times where we don't know exactly what string is (at least, not
    // in a way that we can *safely* reconstruct it without allocating), so we keep both here.
    // With some unsafe code we could probably get rid of one of them (and maybe first, too).
    fn update(&mut self, string: &'a str) {
        self.string = string;
        let (ch, s) = string.slice_shift_char();
        self.first = ch;
        self.rest = s;
    }

    // This is where the lexing happens.  Note that it does not handle string escaping.
    fn next(&mut self) -> Result<Token<'a>, Error> {
        loop {
            match self.first {
                // List start
                Some('(') => {
                    self.update(self.rest);
                    return Ok(ListStart)
                },
                // List end
                Some(')') => {
                    self.update(self.rest);
                    return Ok(ListEnd)
                },
                // Quoted literal start
                Some('"') => {
                    // Split the string at most once.  This lets us get a
                    // reference to the next piece of the string without having
                    // to loop through the string again.
                    let mut iter = self.rest.splitn(1, '"');
                    // The first time splitn is run it will never return None, so this is safe.
                    let str = iter.next().unwrap();
                    match iter.next() {
                        // Extract the interior of the string without allocating.  If we want to
                        // handle string escaping, we would have to allocate at some point though.
                        Some(s) => {
                            self.update(s);
                            return Ok(Literal(Str(str)))
                        },
                        None => return Err(UnterminatedStringLiteral)
                    }
                },
                // Plain old literal start
                Some(c) => {
                    // Skip whitespace.  This could probably be made more efficient.
                    if c.is_whitespace() {
                        self.update(self.rest);
                        continue
                    }
                    // Since we've exhausted all other possibilities, this must be a real literal.
                    // Unlike the quoted case, it's not an error to encounter EOF before whitespace.
                    let mut end_ch = None;
                    let str = {
                        let mut iter = self.string.splitn(1, |ch: char| {
                            let term = ch == ')' || ch == '(';
                            if term { end_ch = Some(ch) }
                            term || ch.is_whitespace()
                        });
                        // The first time splitn is run it will never return None, so this is safe.
                        let str = iter.next().unwrap();
                        self.rest = iter.next().unwrap_or("");
                        str
                    };
                    match end_ch {
                        // self.string will be incorrect in the Some(_) case.  The only reason it's
                        // okay is because the next time next() is called in this case, we know it
                        // will be '(' or ')', so it will never reach any code that actually looks
                        // at self.string.  In a real implementation this would be enforced by
                        // visibility rules.
                        Some(_) => self.first = end_ch,
                        None => self.update(self.rest)
                    }
                    return Ok(Literal(parse_literal(str)));
                }
                None => return Ok(EOF)
            }
        }
    }
}

// Convenience method to turn I/O errors into SExp Errors, inspired by the JSON encoder.
fn from_io_result<T>(res: io::IoResult<T>) -> Result<T, Error> {
    res.map_err( |err| IoError(err) )
}

// This is not the most efficient way to do this, because we end up going over numeric literals
// twice, but it avoids having to write our own number parsing logic.
fn parse_literal(literal: &str) -> SExp {
    match literal.bytes().next() {
        Some(b'0'..b'9') => match num::from_str_radix(literal, 10) {
            Some(f) => F64(f),
            None => Str(literal)
        },
        _ => Str(literal)
    }
}

// Parse context, holds information required by the parser (and owns any allocations it makes)
struct ParseContext<'a> {
    string: &'a str, // The string being parsed.  Not required, but convenient.
    arena: Option<TypedArena<Vec<SExp<'a>>>>, // Arena holding any allocations made by the parser.
    stack: Vec<Vec<SExp<'a>>>, // Stored in the parse context so it can be reused once allocated.
}

impl<'a> ParseContext<'a> {
    // Create a new parse context from a given string
    fn new(string: &'a str) -> ParseContext<'a> {
        ParseContext { string: string, arena: None, stack: Vec::new() }
    }
}

impl<'a> SExp<'a> {
    // Serialize a SExp.
    fn encode<T: io::Writer>(&self, writer: &mut T) -> Result<(), Error> {
        match *self {
            F64(f) => match f.classify() {
                // We don't want to identify NaN, Infinity, etc. as floats.
                num::FPNormal | num::FPZero => from_io_result(write!(writer, "{}", f)),
                _ => Err(NoReprForFloat)
            },
            List(ref l) => {
                // Writing a list is very straightforward--write a left parenthesis, then
                // recursively call encode on each member, and then write a right parenthesis.  The
                // only reason the logic is as long as it is is to make sure we don't write
                // unnecessary spaces between parentheses in the zero or one element cases.
                try!(from_io_result(writer.write_char('(')));
                let mut iter = l.iter();
                match iter.next() {
                    Some(sexp) => {
                        try!(sexp.encode(writer));
                        for sexp in iter {
                            try!(from_io_result(writer.write_char(' ')));
                            try!(sexp.encode(writer));
                        }
                    },
                    None => (),
                }
                from_io_result(writer.write_char(')'))
            },
            Str(s) => from_io_result(write!(writer, "\"{}\"", s)),
        }
    }

    // Deserialize a SExp.
    fn parse(ctx: &'a mut ParseContext<'a>) -> Result<SExp<'a>, Error> {
        ctx.arena = Some(TypedArena::new());
        // Hopefully this unreachable! gets optimized out, because it should literally be
        // unreachable.
        let arena = match ctx.arena {
            Some(ref mut arena) => arena,
            None => unreachable!()
        };
        let ParseContext {string, ref mut stack, .. } = *ctx;
        // Make sure the stack is cleared--we keep it in the context to avoid unnecessary
        // reallocation between parses (if you need to remember old parse information for a new
        // list, you can pass in a new context).
        stack.clear();
        let mut tokens = Tokens::new(string);
        // First, we check the very first token to see if we're parsing a full list.  It
        // simplifies parsing a lot in the subsequent code if we can assume that.
        let next = tokens.next();
        let mut list = match try!(next) {
            ListStart => Vec::new(),
            Literal(s) => return if try!(tokens.next()) == EOF { Ok(s) } else { Err(ExpectedEOF) },
            ListEnd => return Err(IncorrectCloseDelimiter),
            EOF => return Err(UnexpectedEOF),
        };

        // We know we're in a list if we got this far.
        loop {
            let tok = tokens.next();
            match try!(tok) {
                ListStart => {
                    // We push the previous context onto our stack when we start reading a new list.
                    stack.push(list);
                    list = Vec::new()
                },
                Literal(s) => list.push(s), // Plain old literal, push it onto the current list
                ListEnd => match stack.pop() { // Pop the old context off the stack on list end.
                    Some(mut l) => {
                        // We allocate a slot for the current list in our parse context (needed for
                        // safety) before pushing it onto its parent list.
                        l.push(List(arena.alloc(list)[]));
                        // Now reset the current list to the parent list
                        list = l;
                    },
                    // There was nothing on the stack, so we're at the end of the topmost list.
                    // The check to make sure there are no more tokens is required for correctness.
                    None => return match try!(tokens.next()) {
                        EOF => Ok(List(arena.alloc(list)[])),
                        _ => Err(ExpectedEOF),
                    }
                },
                // We encountered an EOF before the list ended--that's an error.
                EOF => return Err(UnexpectedEOF),
            }
        }
    }

    // Convenience method for the common case where you just want to encode a SExp as a String.
    fn buffer_encode(&self) -> Result<String, Error> {
        let mut m = io::MemWriter::new();
        try!(self.encode(&mut m));
        // Because encode() only ever writes valid UTF-8, we can safely skip the secondary check we
        // normally have to do when converting from Vec<u8> to String.  If we didn't know that the
        // buffer was already UTF-8, we'd want to call container_as_str() here.
        unsafe { Ok(string::raw::from_utf8(m.unwrap())) }
    }
}

static sexp_struct: SExp<'static> = List([
    List([Str("data"), Str("quoted data"), F64(123.), F64(4.5)]),
    List([Str("data"), List([Str("!@#"), List([F64(4.5)]), Str("(more"), Str("data)")])]),
]);

fn try_encode() -> Result<String, Error> {
    sexp_struct.buffer_encode()
}

static sexp_string_in: &'static str = r#"((data "quoted data" 123 4.5)
(data (!@# (4.5) "(more" "data)")))"#;

fn try_decode<'a>(ctx: &'a mut ParseContext<'a>) -> Result<SExp<'a>, Error> {
    SExp::parse(ctx)
}

#[cfg(not(test))]
fn main() {
    println!("{}", try_encode());
    let ref mut ctx = ParseContext::new(sexp_string_in);
    println!("{}", try_decode(ctx));
}

#[bench]
fn bench_decode(b: &mut test::Bencher)
{
    let ref mut ctx = ParseContext::new(sexp_string_in);
    b.iter(|| {
        assert!(try_decode(ctx).is_ok());
    })
}

#[bench]
fn bench_encode(b: &mut test::Bencher)
{
    b.iter(|| {
        assert!(try_encode().is_ok());
    })
}

#[test]
fn test_sexp_encode() {
    static sexp_string: &'static str =
r#"(("data" "quoted data" 123 4.5) ("data" ("!@#" (4.5) "(more" "data)")))"#;
    assert_eq!(Ok(sexp_string), try_encode().as_ref().map( |s| s[]));
}

#[test]
fn test_sexp_decode() {
    let ref mut ctx = ParseContext::new(sexp_string_in);
    assert_eq!(Ok(sexp_struct), try_decode(ctx));
}
<commit_msg>Fixing negative numbers in s-expression parser.<commit_after>// Implements http://rosettacode.org/wiki/S-Expressions
//
// This implementation isn't based on anything in particular, although it's probably informed by a
// lot of Rust's JSON encoding code.  It should be very fast (both encoding and decoding the toy
// example here takes under a microsecond on my machine) and tries to avoid unnecessary allocation.
//
// In a real implementation, most of this would be private, with only a few visible functions, and
// there would be somewhat nicer signatures (in particular, the fact that ParseContext has to be
// mutable would get annoying in real code pretty quickly, so it would probably be split out).
//
// It supports the ability to read individual atoms, not just lists, although whether this is
// useful is questionable.
//
// Caveats: Does not support symbols vs. non-symbols (it wouldn't be hard, but it would greatly
// complicate setting up our test structure since we'd have to force it to go through functions
// that checked to make sure Symbols couldn't have spaces, or slow down our parser by checking for
// this information each time, which is obnoxious).  Does not support string escaping, because the
// decoding technique doesn't allocate extra space for strings.  Does support numbers, but only
// float types (supporting more types is possible but would complicate the code significantly).
//
extern crate arena;
extern crate test;

use arena::TypedArena;

use std::io;
use std::num;
use std::string;

#[deriving(PartialEq,Show)]
// The actual SExp structure.  Supports f64s, lists, and string literals.  Note that it takes
// everything by reference, rather than owning it--this is mostly done just so we can allocate
// SExps statically (since we don't have to call Vec).  It does complicate the code a bit,
// requiring us to have a ParseContext that holds an arena where lists are actually allocated.
enum SExp<'a> {
    F64(f64), // Float literal: 0.5
    List(&'a [SExp<'a>]), // List of SExps: ( a b c)
    Str(&'a str), // Plain old string literal: "abc"
}

// Errors that can be thrown by the parser.
#[deriving(PartialEq,Show)]
enum Error {
    NoReprForFloat, // If the float is NaN, Infinity, etc.
    UnterminatedStringLiteral, // Missing an end double quote during string parsing
    IoError(io::IoError), // Some other kind of I/O error
    IncorrectCloseDelimiter, // ) appeared where it shouldn't (usually as the first token)
    UnexpectedEOF, // Usually means a missing ), but could also mean there were no tokens at all.
    ExpectedEOF, // More tokens after the list is finished, or after a literal if there is no list.
}

// Tokens returned from the token stream.
#[deriving(PartialEq)]
enum Token<'a> {
    ListStart, // Left parenthesis
    ListEnd, // Right parenthesis
    Literal(SExp<'a>), // String or float literal, quotes removed.
    EOF, // Stream is out of tokens.
}

// An iterator over a string that yields a stream of Tokens.
// Implementation note: it probably seems weird to store first, rest, AND string, since they should
// all be derivable from string.  But see below.
struct Tokens<'a> {
    string: &'a str, // The part of the string that still needs to be parsed
    first: Option<char>, // The first character to parse
    rest: &'a str, // The rest of the string after the first character
}

impl<'a> Tokens<'a> {
    // Initialize a token stream for a given string.
    fn new(string: &str) -> Tokens {
        let (ch, s) = string.slice_shift_char();
        Tokens { string: string, first: ch, rest: s }
    }

    // Utility function to update information in the iterator.  It might not be performant to keep
    // rest cached, but there are times where we don't know exactly what string is (at least, not
    // in a way that we can *safely* reconstruct it without allocating), so we keep both here.
    // With some unsafe code we could probably get rid of one of them (and maybe first, too).
    fn update(&mut self, string: &'a str) {
        self.string = string;
        let (ch, s) = string.slice_shift_char();
        self.first = ch;
        self.rest = s;
    }

    // This is where the lexing happens.  Note that it does not handle string escaping.
    fn next(&mut self) -> Result<Token<'a>, Error> {
        loop {
            match self.first {
                // List start
                Some('(') => {
                    self.update(self.rest);
                    return Ok(ListStart)
                },
                // List end
                Some(')') => {
                    self.update(self.rest);
                    return Ok(ListEnd)
                },
                // Quoted literal start
                Some('"') => {
                    // Split the string at most once.  This lets us get a
                    // reference to the next piece of the string without having
                    // to loop through the string again.
                    let mut iter = self.rest.splitn(1, '"');
                    // The first time splitn is run it will never return None, so this is safe.
                    let str = iter.next().unwrap();
                    match iter.next() {
                        // Extract the interior of the string without allocating.  If we want to
                        // handle string escaping, we would have to allocate at some point though.
                        Some(s) => {
                            self.update(s);
                            return Ok(Literal(Str(str)))
                        },
                        None => return Err(UnterminatedStringLiteral)
                    }
                },
                // Plain old literal start
                Some(c) => {
                    // Skip whitespace.  This could probably be made more efficient.
                    if c.is_whitespace() {
                        self.update(self.rest);
                        continue
                    }
                    // Since we've exhausted all other possibilities, this must be a real literal.
                    // Unlike the quoted case, it's not an error to encounter EOF before whitespace.
                    let mut end_ch = None;
                    let str = {
                        let mut iter = self.string.splitn(1, |ch: char| {
                            let term = ch == ')' || ch == '(';
                            if term { end_ch = Some(ch) }
                            term || ch.is_whitespace()
                        });
                        // The first time splitn is run it will never return None, so this is safe.
                        let str = iter.next().unwrap();
                        self.rest = iter.next().unwrap_or("");
                        str
                    };
                    match end_ch {
                        // self.string will be incorrect in the Some(_) case.  The only reason it's
                        // okay is because the next time next() is called in this case, we know it
                        // will be '(' or ')', so it will never reach any code that actually looks
                        // at self.string.  In a real implementation this would be enforced by
                        // visibility rules.
                        Some(_) => self.first = end_ch,
                        None => self.update(self.rest)
                    }
                    return Ok(Literal(parse_literal(str)));
                }
                None => return Ok(EOF)
            }
        }
    }
}

// Convenience method to turn I/O errors into SExp Errors, inspired by the JSON encoder.
fn from_io_result<T>(res: io::IoResult<T>) -> Result<T, Error> {
    res.map_err( |err| IoError(err) )
}

// This is not the most efficient way to do this, because we end up going over numeric literals
// twice, but it avoids having to write our own number parsing logic.
fn parse_literal(literal: &str) -> SExp {
    match literal.bytes().next() {
        Some(b'0'..b'9') | Some(b'-') => match num::from_str_radix(literal, 10) {
            Some(f) => F64(f),
            None => Str(literal)
        },
        _ => Str(literal)
    }
}

// Parse context, holds information required by the parser (and owns any allocations it makes)
struct ParseContext<'a> {
    string: &'a str, // The string being parsed.  Not required, but convenient.
    arena: Option<TypedArena<Vec<SExp<'a>>>>, // Arena holding any allocations made by the parser.
    stack: Vec<Vec<SExp<'a>>>, // Stored in the parse context so it can be reused once allocated.
}

impl<'a> ParseContext<'a> {
    // Create a new parse context from a given string
    fn new(string: &'a str) -> ParseContext<'a> {
        ParseContext { string: string, arena: None, stack: Vec::new() }
    }
}

impl<'a> SExp<'a> {
    // Serialize a SExp.
    fn encode<T: io::Writer>(&self, writer: &mut T) -> Result<(), Error> {
        match *self {
            F64(f) => match f.classify() {
                // We don't want to identify NaN, Infinity, etc. as floats.
                num::FPNormal | num::FPZero => from_io_result(write!(writer, "{}", f)),
                _ => Err(NoReprForFloat)
            },
            List(ref l) => {
                // Writing a list is very straightforward--write a left parenthesis, then
                // recursively call encode on each member, and then write a right parenthesis.  The
                // only reason the logic is as long as it is is to make sure we don't write
                // unnecessary spaces between parentheses in the zero or one element cases.
                try!(from_io_result(writer.write_char('(')));
                let mut iter = l.iter();
                match iter.next() {
                    Some(sexp) => {
                        try!(sexp.encode(writer));
                        for sexp in iter {
                            try!(from_io_result(writer.write_char(' ')));
                            try!(sexp.encode(writer));
                        }
                    },
                    None => (),
                }
                from_io_result(writer.write_char(')'))
            },
            Str(s) => from_io_result(write!(writer, "\"{}\"", s)),
        }
    }

    // Deserialize a SExp.
    fn parse(ctx: &'a mut ParseContext<'a>) -> Result<SExp<'a>, Error> {
        ctx.arena = Some(TypedArena::new());
        // Hopefully this unreachable! gets optimized out, because it should literally be
        // unreachable.
        let arena = match ctx.arena {
            Some(ref mut arena) => arena,
            None => unreachable!()
        };
        let ParseContext {string, ref mut stack, .. } = *ctx;
        // Make sure the stack is cleared--we keep it in the context to avoid unnecessary
        // reallocation between parses (if you need to remember old parse information for a new
        // list, you can pass in a new context).
        stack.clear();
        let mut tokens = Tokens::new(string);
        // First, we check the very first token to see if we're parsing a full list.  It
        // simplifies parsing a lot in the subsequent code if we can assume that.
        let next = tokens.next();
        let mut list = match try!(next) {
            ListStart => Vec::new(),
            Literal(s) => return if try!(tokens.next()) == EOF { Ok(s) } else { Err(ExpectedEOF) },
            ListEnd => return Err(IncorrectCloseDelimiter),
            EOF => return Err(UnexpectedEOF),
        };

        // We know we're in a list if we got this far.
        loop {
            let tok = tokens.next();
            match try!(tok) {
                ListStart => {
                    // We push the previous context onto our stack when we start reading a new list.
                    stack.push(list);
                    list = Vec::new()
                },
                Literal(s) => list.push(s), // Plain old literal, push it onto the current list
                ListEnd => match stack.pop() { // Pop the old context off the stack on list end.
                    Some(mut l) => {
                        // We allocate a slot for the current list in our parse context (needed for
                        // safety) before pushing it onto its parent list.
                        l.push(List(arena.alloc(list)[]));
                        // Now reset the current list to the parent list
                        list = l;
                    },
                    // There was nothing on the stack, so we're at the end of the topmost list.
                    // The check to make sure there are no more tokens is required for correctness.
                    None => return match try!(tokens.next()) {
                        EOF => Ok(List(arena.alloc(list)[])),
                        _ => Err(ExpectedEOF),
                    }
                },
                // We encountered an EOF before the list ended--that's an error.
                EOF => return Err(UnexpectedEOF),
            }
        }
    }

    // Convenience method for the common case where you just want to encode a SExp as a String.
    fn buffer_encode(&self) -> Result<String, Error> {
        let mut m = io::MemWriter::new();
        try!(self.encode(&mut m));
        // Because encode() only ever writes valid UTF-8, we can safely skip the secondary check we
        // normally have to do when converting from Vec<u8> to String.  If we didn't know that the
        // buffer was already UTF-8, we'd want to call container_as_str() here.
        unsafe { Ok(string::raw::from_utf8(m.unwrap())) }
    }
}

static sexp_struct: SExp<'static> = List([
    List([Str("data"), Str("quoted data"), F64(123.), F64(4.5)]),
    List([Str("data"), List([Str("!@#"), List([F64(4.5)]), Str("(more"), Str("data)")])]),
]);

fn try_encode() -> Result<String, Error> {
    sexp_struct.buffer_encode()
}

static sexp_string_in: &'static str = r#"((data "quoted data" 123 4.5)
(data (!@# (4.5) "(more" "data)")))"#;

fn try_decode<'a>(ctx: &'a mut ParseContext<'a>) -> Result<SExp<'a>, Error> {
    SExp::parse(ctx)
}

#[cfg(not(test))]
fn main() {
    println!("{}", try_encode());
    let ref mut ctx = ParseContext::new(sexp_string_in);
    println!("{}", try_decode(ctx));
}

#[bench]
fn bench_decode(b: &mut test::Bencher)
{
    let ref mut ctx = ParseContext::new(sexp_string_in);
    b.iter(|| {
        assert!(try_decode(ctx).is_ok());
    })
}

#[bench]
fn bench_encode(b: &mut test::Bencher)
{
    b.iter(|| {
        assert!(try_encode().is_ok());
    })
}

#[test]
fn test_sexp_encode() {
    static sexp_string: &'static str =
r#"(("data" "quoted data" 123 4.5) ("data" ("!@#" (4.5) "(more" "data)")))"#;
    assert_eq!(Ok(sexp_string), try_encode().as_ref().map( |s| s[]));
}

#[test]
fn test_sexp_decode() {
    let ref mut ctx = ParseContext::new(sexp_string_in);
    assert_eq!(Ok(sexp_struct), try_decode(ctx));
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::ops::{Add, Range, Sub};

use take_mut;

#[derive(Debug)]
pub struct ScheduleTree<'a, T: 'a, D: 'a> {
    root: Option<Node<'a, T, D>>,
    scope: Option<Range<T>>,
}

#[derive(Debug, PartialEq)]
enum Node<'a, T: 'a, D: 'a> {
    Leaf { start: T, end: T, data: &'a D },
    Intermediate {
        left: Box<Node<'a, T, D>>,
        right: Box<Node<'a, T, D>>,
        free: Range<T>,
    },
}

impl<'a, T: Copy + Clone + Ord + Debug, D: Debug> ScheduleTree<'a, T, D> {
    pub fn new() -> Self {
        ScheduleTree {
            root: None,
            scope: None,
        }
    }

    pub fn schedule_exact<W>(&mut self, start: T, duration: W, data: &'a D) -> bool
        where T: Add<W, Output = T> + Sub<T, Output = W> + Sub<W, Output = T>,
              W: Add<W, Output = W> + Add<T, Output = T> + Sub<W, Output = W>
    {
        let end = start + duration;

        if let None = self.root {
            self.root = Some(Node::Leaf {
                start: start,
                end: end,
                data: data,
            });
            self.scope = Some(start..end);
            return true;
        }

        let scope = self.scope.as_ref().cloned().unwrap();
        if end <= scope.start {
            let new_node = Node::Leaf {
                start: start,
                end: end,
                data: data,
            };
            let root = self.root.take().unwrap();
            self.root = Some(Node::Intermediate {
                left: Box::new(new_node),
                right: Box::new(root),
                free: end..scope.start,
            });
            self.scope = Some(start..scope.end);
            return true;
        } else if scope.end <= start {
            let new_node = Node::Leaf {
                start: start,
                end: end,
                data: data,
            };
            let root = self.root.take().unwrap();
            self.root = Some(Node::Intermediate {
                left: Box::new(root),
                right: Box::new(new_node),
                free: scope.end..start,
            });
            self.scope = Some(scope.start..end);
            return true;
        }

        self.root.as_mut().unwrap().insert(start, end, data)
    }

    pub fn schedule_after<W>(&self, start: T, duration: W, max_end: Option<T>, data: &'a D) -> bool
        where T: Add<W, Output = T> + Sub<T, Output = W> + Sub<W, Output = T>,
              W: Add<W, Output = W> + Add<T, Output = T> + Sub<W, Output = W> + Copy
    {
        assert!(max_end.map_or(true, |max_end| start + duration <= max_end));
        // TODO schedule
        true
    }
}

impl<'a, T: Copy + Ord + Debug, D> Node<'a, T, D> {
    fn insert(&mut self, start: T, end: T, data: &'a D) -> bool {
        match *self {
            Node::Intermediate { ref mut left, ref mut right, ref mut free } => {
                if end <= free.start {
                    left.insert(start, end, data)
                } else if free.end <= start {
                    right.insert(start, end, data)
                } else if free.start <= start && end <= free.end {
                    // [start, end] completely within self.free
                    let new_node = Node::Leaf {
                        start: start,
                        end: end,
                        data: data,
                    };
                    take_mut::take(right, |right_value| {
                        Box::new(Node::Intermediate {
                            left: new_node.into(),
                            right: right_value,
                            free: end..free.end,
                        })
                    });
                    *free = free.start..start;
                    true
                } else {
                    // Overlap between [start, end] and self.free
                    false
                }
            }
            Node::Leaf { .. } => false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    const DATA: &i8 = &9;

    #[test]
    fn test_schedule_exact() {
        let mut tree: ScheduleTree<i8, i8> = ScheduleTree::new();
        let scheduled = tree.schedule_exact(5, 5, DATA);
        assert!(scheduled);
        assert!(tree.scope == Some(5..10));
        assert_matches!(tree.root, Some(Node::Leaf { start: 5, end: 10, ..}));

        let scheduled = tree.schedule_exact(12, 5, DATA);
        assert!(scheduled);
        assert!(tree.scope == Some(5..17));
        assert_matches!(tree.root, Some(Node::Intermediate { free: Range { start: 10, end: 12 }, .. }));
    }
}
<commit_msg>Refactoring<commit_after>use std::fmt::Debug;
use std::ops::{Add, Range, Sub};

use take_mut;

#[derive(Debug)]
pub struct ScheduleTree<'a, T: 'a, D: 'a> {
    root: Option<Node<'a, T, D>>,
    scope: Option<Range<T>>,
}

#[derive(Debug, PartialEq)]
enum Node<'a, T: 'a, D: 'a> {
    Leaf { start: T, end: T, data: &'a D },
    Intermediate {
        left: Box<Node<'a, T, D>>,
        right: Box<Node<'a, T, D>>,
        free: Range<T>,
    },
}

impl<'a, T: Copy + Clone + Ord + Debug, D: Debug> ScheduleTree<'a, T, D> {
    pub fn new() -> Self {
        ScheduleTree {
            root: None,
            scope: None,
        }
    }

    pub fn schedule_exact<W>(&mut self, start: T, duration: W, data: &'a D) -> bool
        where T: Add<W, Output = T> + Sub<T, Output = W> + Sub<W, Output = T>,
              W: Add<W, Output = W> + Add<T, Output = T> + Sub<W, Output = W>
    {
        let end = start + duration;
        let new_node = Node::Leaf {
            start: start,
            end: end,
            data: data,
        };

        if self.root.is_none() {
            self.root = Some(new_node);
            self.scope = Some(start..end);
            return true;
        }

        let scope = self.scope.as_ref().cloned().unwrap();
        if end <= scope.start {
            let root = self.root.take().unwrap();
            self.root = Some(Node::Intermediate {
                left: Box::new(new_node),
                right: Box::new(root),
                free: end..scope.start,
            });
            self.scope = Some(start..scope.end);
            return true;
        } else if scope.end <= start {
            let root = self.root.take().unwrap();
            self.root = Some(Node::Intermediate {
                left: Box::new(root),
                right: Box::new(new_node),
                free: scope.end..start,
            });
            self.scope = Some(scope.start..end);
            return true;
        }

        self.root.as_mut().unwrap().insert(start, end, new_node)
    }

    pub fn schedule_after<W>(&self, start: T, duration: W, max_end: Option<T>, data: &'a D) -> bool
        where T: Add<W, Output = T> + Sub<T, Output = W> + Sub<W, Output = T>,
              W: Add<W, Output = W> + Add<T, Output = T> + Sub<W, Output = W> + Copy
    {
        assert!(max_end.map_or(true, |max_end| start + duration <= max_end));
        // TODO schedule
        true
    }
}

impl<'a, T: Copy + Ord + Debug, D> Node<'a, T, D> {
    fn insert(&mut self, start: T, end: T, sub_tree: Node<'a, T, D>) -> bool {
        match *self {
            Node::Intermediate { ref mut left, ref mut right, ref mut free } => {
                if end <= free.start {
                    left.insert(start, end, sub_tree)
                } else if free.end <= start {
                    right.insert(start, end, sub_tree)
                } else if free.start <= start && end <= free.end {
                    // [start, end] completely within self.free
                    take_mut::take(right, |right_value| {
                        Box::new(Node::Intermediate {
                            left: Box::new(sub_tree),
                            right: right_value,
                            free: end..free.end,
                        })
                    });
                    *free = free.start..start;
                    true
                } else {
                    // Overlap between [start, end] and self.free
                    false
                }
            }
            Node::Leaf { .. } => false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    const DATA: &i8 = &9;

    #[test]
    fn test_schedule_exact() {
        let mut tree: ScheduleTree<i8, i8> = ScheduleTree::new();

        // 5..10
        let scheduled = tree.schedule_exact(5, 5, DATA);
        assert!(scheduled);
        assert!(tree.scope == Some(5..10));
        assert_matches!(tree.root, Some(Node::Leaf { start: 5, end: 10, .. }));

        //   free:10..13
        //    /        \
        // 5..10      13..18
        let scheduled = tree.schedule_exact(13, 5, DATA);
        assert!(scheduled);
        assert!(tree.scope == Some(5..18));
        assert_matches!(tree.root, Some(Node::Intermediate {
            free: Range { start: 10, end: 13 },
            right: box Node::Leaf { start: 13, end: 18, .. },
        .. }));

        //   free:10..10
        //    /        \
        // 5..10     free:12..13
        //             /     \
        //          10..12  13..18
        let scheduled = tree.schedule_exact(10, 2, DATA);
        assert!(scheduled);
        assert!(tree.scope == Some(5..18));
        assert_matches!(tree.root, Some(Node::Intermediate {
            free: Range { start: 10, end: 10 },
            right: box Node::Intermediate {
                free: Range { start: 12, end: 13 },
                left: box Node::Leaf { start: 10, end: 12, .. },
            .. },
        .. }));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::intrinsics::{type_id, type_name};
use std::convert::From;
use core::nonzero::NonZero;

#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ShortTypeId(NonZero<u16>);

impl ShortTypeId {
    pub fn new(id: u16) -> Self {
        ShortTypeId(unsafe { NonZero::new(id) })
    }

    pub fn as_usize(&self) -> usize {
        self.0.get() as usize
    }
}

impl Default for ShortTypeId {
    fn default() -> Self {
        ShortTypeId::new(<u16>::max_value())
    }
}

impl From<ShortTypeId> for u16 {
    fn from(id: ShortTypeId) -> Self {
        id.0.get()
    }
}

pub struct TypeRegistry {
    next_short_id: ShortTypeId,
    long_to_short_ids: HashMap<u64, ShortTypeId>,
    short_ids_to_names: HashMap<ShortTypeId, String>,
}

impl TypeRegistry {
    pub fn new() -> TypeRegistry {
        TypeRegistry {
            next_short_id: ShortTypeId::new(1), // Non nullable optimization
            long_to_short_ids: HashMap::new(),
            short_ids_to_names: HashMap::new(),
        }
    }

    pub fn register_new<T: 'static>(&mut self) -> ShortTypeId {
        let short_id = self.next_short_id;
        let long_id = unsafe { type_id::<T>() };
        assert!(self.long_to_short_ids.get(&long_id).is_none());
        self.long_to_short_ids.insert(long_id, short_id);
        self.short_ids_to_names.insert(
            short_id,
            unsafe { type_name::<T>() }.into(),
        );
        self.next_short_id = ShortTypeId::new(u16::from(self.next_short_id) + 1);
        short_id
    }

    pub fn get<T: 'static>(&self) -> ShortTypeId {
        if let Some(&short_id) = self.long_to_short_ids.get(&unsafe { type_id::<T>() }) {
            short_id
        } else {
            panic!("{:?} not known.", &unsafe { type_name::<T>() })
        }
    }

    pub fn get_or_register<T: 'static>(&mut self) -> ShortTypeId {
        self.long_to_short_ids
            .get(&unsafe { type_id::<T>() })
            .cloned()
            .unwrap_or_else(|| self.register_new::<T>())
    }

    pub fn get_name(&self, short_id: ShortTypeId) -> &String {
        &self.short_ids_to_names[&short_id]
    }
}

impl Default for TypeRegistry {
    fn default() -> Self {
        Self::new()
    }
}
<commit_msg>default is not needed for ShortTypeId<commit_after>use std::collections::HashMap;
use std::intrinsics::{type_id, type_name};
use std::convert::From;
use core::nonzero::NonZero;

#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct ShortTypeId(NonZero<u16>);

impl ShortTypeId {
    pub fn new(id: u16) -> Self {
        ShortTypeId(unsafe { NonZero::new(id) })
    }

    pub fn as_usize(&self) -> usize {
        self.0.get() as usize
    }
}

impl From<ShortTypeId> for u16 {
    fn from(id: ShortTypeId) -> Self {
        id.0.get()
    }
}

pub struct TypeRegistry {
    next_short_id: ShortTypeId,
    long_to_short_ids: HashMap<u64, ShortTypeId>,
    short_ids_to_names: HashMap<ShortTypeId, String>,
}

impl TypeRegistry {
    pub fn new() -> TypeRegistry {
        TypeRegistry {
            next_short_id: ShortTypeId::new(1), // Non nullable optimization
            long_to_short_ids: HashMap::new(),
            short_ids_to_names: HashMap::new(),
        }
    }

    pub fn register_new<T: 'static>(&mut self) -> ShortTypeId {
        let short_id = self.next_short_id;
        let long_id = unsafe { type_id::<T>() };
        assert!(self.long_to_short_ids.get(&long_id).is_none());
        self.long_to_short_ids.insert(long_id, short_id);
        self.short_ids_to_names.insert(
            short_id,
            unsafe { type_name::<T>() }.into(),
        );
        self.next_short_id = ShortTypeId::new(u16::from(self.next_short_id) + 1);
        short_id
    }

    pub fn get<T: 'static>(&self) -> ShortTypeId {
        if let Some(&short_id) = self.long_to_short_ids.get(&unsafe { type_id::<T>() }) {
            short_id
        } else {
            panic!("{:?} not known.", &unsafe { type_name::<T>() })
        }
    }

    pub fn get_or_register<T: 'static>(&mut self) -> ShortTypeId {
        self.long_to_short_ids
            .get(&unsafe { type_id::<T>() })
            .cloned()
            .unwrap_or_else(|| self.register_new::<T>())
    }

    pub fn get_name(&self, short_id: ShortTypeId) -> &String {
        &self.short_ids_to_names[&short_id]
    }
}

impl Default for TypeRegistry {
    fn default() -> Self {
        Self::new()
    }
}
<|endoftext|>