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

// The rust-book CSS in string form.

pub static STYLE: &'static str = r#"
@import url("//static.rust-lang.org/doc/master/rust.css");

body {
    max-width:none;
}

#toc {
    position: absolute;
    left: 0px;
    top: 0px;
    bottom: 0px;
    width: 250px;
    overflow-y: auto;
    border-right: 1px solid rgba(0, 0, 0, 0.07);
    padding: 10px 10px;
    font-size: 16px;
    background: none repeat scroll 0% 0% #FFF;
    box-sizing: border-box;
}

#page-wrapper {
    position: absolute;
    overflow-y: auto;
    left: 260px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    box-sizing: border-box;
    background: none repeat scroll 0% 0% #FFF;
}

#page {
    margin-left: auto;
    margin-right:auto;
    width: 750px;
}

.chapter {
    list-style: none outside none;
    padding-left: 0px;
    line-height: 30px;
}

.section {
    list-style: none outside none;
    padding-left: 20px;
    line-height: 30px;
}

.section li {
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
}

.chapter li a {
    color: #000000;
}
"#;
<commit_msg>rustbook: use a relative @import path to ensure it works offline.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The rust-book CSS in string form.

pub static STYLE: &'static str = r#"
@import url("../rust.css");

body {
    max-width:none;
}

#toc {
    position: absolute;
    left: 0px;
    top: 0px;
    bottom: 0px;
    width: 250px;
    overflow-y: auto;
    border-right: 1px solid rgba(0, 0, 0, 0.07);
    padding: 10px 10px;
    font-size: 16px;
    background: none repeat scroll 0% 0% #FFF;
    box-sizing: border-box;
}

#page-wrapper {
    position: absolute;
    overflow-y: auto;
    left: 260px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    box-sizing: border-box;
    background: none repeat scroll 0% 0% #FFF;
}

#page {
    margin-left: auto;
    margin-right:auto;
    width: 750px;
}

.chapter {
    list-style: none outside none;
    padding-left: 0px;
    line-height: 30px;
}

.section {
    list-style: none outside none;
    padding-left: 20px;
    line-height: 30px;
}

.section li {
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
}

.chapter li a {
    color: #000000;
}
"#;
<|endoftext|>


<commit_before>// no-reformat

/*!
 * A demonstration module
 *
 * Contains documentation in various forms that rustdoc understands,
 * for testing purposes. It doesn't surve any functional
 * purpose. This here, for instance, is just some filler text.
 *
 * FIXME (#1654): It would be nice if we could run some automated
 * tests on this file
 */

/// The base price of a muffin on a non-holiday
const price_of_a_muffin: float = 70f;

type waitress = {
    hair_color: ~str
};

/// The type of things that produce omnomnom
enum omnomnomy {
    /// Delicious sugar cookies
    cookie,
    /// It's pizza
    pizza_pie(~[uint])
}

fn take_my_order_please(
    _waitress: waitress,
    _order: ~[omnomnomy]
) -> uint {

    /*!
     * OMG would you take my order already?
     *
     * # Arguments
     *
     * * _waitress - The waitress that you want to bother
     * * _order - The order vector. It should be filled with food
     *
     * # Return
     *
     * The price of the order, including tax
     *
     * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
     * molestie nisl. Duis massa risus, pharetra a scelerisque a,
     * molestie eu velit. Donec mattis ligula at ante imperdiet ut
     * dapibus mauris malesuada.
     *
     * Sed gravida nisi a metus elementum sit amet hendrerit dolor
     * bibendum. Aenean sit amet neque massa, sed tempus tortor. Sed ut
     * lobortis enim. Proin a mauris quis nunc fermentum ultrices eget a
     * erat. Mauris in lectus vitae metus sodales auctor. Morbi nunc
     * quam, ultricies at venenatis non, pellentesque ac dui.
     *
     * # Failure
     *
     * This function is full of fail
     */

    fail;
}

mod fortress_of_solitude {
    /*!
     * Superman's vacation home
     *
     * The fortress of solitude is located in the Arctic and it is
     * cold. What you may not know about the fortress of solitude
     * though is that it contains two separate bowling alleys. One of
     * them features bumper-bowling and is kind of lame.
     *
     * Really, it's pretty cool.
     */

}

mod blade_runner {
    /*!
     * Blade Runner is probably the best movie ever
     *
     * I like that in the world of Blade Runner it is always
     * raining, and that it's always night time. And Aliens
     * was also a really good movie.
     *
     * Alien 3 was crap though.
     */
}

/**
 * Bored
 *
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
 * molestie nisl. Duis massa risus, pharetra a scelerisque a,
 * molestie eu velit. Donec mattis ligula at ante imperdiet ut
 * dapibus mauris malesuada. Sed gravida nisi a metus elementum sit
 * amet hendrerit dolor bibendum. Aenean sit amet neque massa, sed
 * tempus tortor. Sed ut lobortis enim. Proin a mauris quis nunc
 * fermentum ultrices eget a erat. Mauris in lectus vitae metus
 * sodales auctor. Morbi nunc quam, ultricies at venenatis non,
 * pellentesque ac dui.
 *
 * Quisque vitae est id eros placerat laoreet sit amet eu
 * nisi. Curabitur suscipit neque porttitor est euismod
 * lacinia. Curabitur non quam vitae ipsum adipiscing
 * condimentum. Mauris ut ante eget metus sollicitudin
 * blandit. Aliquam erat volutpat. Morbi sed nisl mauris. Nulla
 * facilisi. Phasellus at mollis ipsum. Maecenas sed convallis
 * sapien. Nullam in ligula turpis. Pellentesque a neque augue. Sed
 * eget ante feugiat tortor congue auctor ac quis ante. Proin
 * condimentum lacinia tincidunt.
 */
class bored {
  let bored: bool;
  new(bored: bool) { self.bored = bored; }
  drop { log(error, self.bored); }
}

/**
 * The Shunned House
 *
 * From even the greatest of horrors irony is seldom absent. Sometimes it
 * enters directly into the composition of the events, while sometimes it
 * relates only to their fortuitous position among persons and
 * places. The latter sort is splendidly exemplified by a case in the
 * ancient city of Providence, where in the late forties Edgar Allan Poe
 * used to sojourn often during his unsuccessful wooing of the gifted
 * poetess, Mrs.  Whitman. Poe generally stopped at the Mansion House in
 * Benefit Street--the renamed Golden Ball Inn whose roof has sheltered
 * Washington, Jefferson, and Lafayette--and his favorite walk led
 * northward along the same street to Mrs. Whitman's home and the
 * neighboring hillside churchyard of St. John's, whose hidden expanse of
 * Eighteenth Century gravestones had for him a peculiar fascination.
 */
iface the_shunned_house {
    /**
     * Now the irony is this. In this walk, so many times repeated, the
     * world's greatest master of the terrible and the bizarre was
     * obliged to pass a particular house on the eastern side of the
     * street; a dingy, antiquated structure perched on the abruptly
     * rising side hill, with a great unkempt yard dating from a time
     * when the region was partly open country. It does not appear that
     * he ever wrote or spoke of it, nor is there any evidence that he
     * even noticed it. And yet that house, to the two persons in
     * possession of certain information, equals or outranks in horror
     * the wildest fantasy of the genius who so often passed it
     * unknowingly, and stands starkly leering as a symbol of all that is
     * unutterably hideous.
     *
     * # Arguments
     *
     * * unkempt_yard - A yard dating from a time when the region was partly
     *                  open country
     */
    fn dingy_house(unkempt_yard: int);

    /**
     * The house was--and for that matter still is--of a kind to attract
     * the attention of the curious. Originally a farm or semi-farm
     * building, it followed the average New England colonial lines of
     * the middle Eighteenth Century--the prosperous peaked-roof sort,
     * with two stories and dormerless attic, and with the Georgian
     * doorway and interior panelling dictated by the progress of taste
     * at that time. It faced south, with one gable end buried to the
     * lower windows in the eastward rising hill, and the other exposed
     * to the foundations toward the street. Its construction, over a
     * century and a half ago, had followed the grading and straightening
     * of the road in that especial vicinity; for Benefit Street--at
     * first called Back Street--was laid out as a lane winding amongst
     * the graveyards of the first settlers, and straightened only when
     * the removal of the bodies to the North Burial Ground made it
     * decently possible to cut through the old family plots.
     */
    fn construct() -> bool;
}

/// Whatever
impl of the_shunned_house for omnomnomy {
    fn dingy_house(_unkempt_yard: int) {
    }

    fn construct() -> bool {
        fail;
    }
}<commit_msg>Make rustdoc/demo.rs less gendered<commit_after>// no-reformat

/*!
 * A demonstration module
 *
 * Contains documentation in various forms that rustdoc understands,
 * for testing purposes. It doesn't surve any functional
 * purpose. This here, for instance, is just some filler text.
 *
 * FIXME (#1654): It would be nice if we could run some automated
 * tests on this file
 */

/// The base price of a muffin on a non-holiday
const price_of_a_muffin: float = 70f;

type waitperson = {
    hair_color: ~str
};

/// The type of things that produce omnomnom
enum omnomnomy {
    /// Delicious sugar cookies
    cookie,
    /// It's pizza
    pizza_pie(~[uint])
}

fn take_my_order_please(
    _waitperson: waitperson,
    _order: ~[omnomnomy]
) -> uint {

    /*!
     * OMG would you take my order already?
     *
     * # Arguments
     *
     * * _waitperson - The waitperson that you want to bother
     * * _order - The order vector. It should be filled with food
     *
     * # Return
     *
     * The price of the order, including tax
     *
     * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
     * molestie nisl. Duis massa risus, pharetra a scelerisque a,
     * molestie eu velit. Donec mattis ligula at ante imperdiet ut
     * dapibus mauris malesuada.
     *
     * Sed gravida nisi a metus elementum sit amet hendrerit dolor
     * bibendum. Aenean sit amet neque massa, sed tempus tortor. Sed ut
     * lobortis enim. Proin a mauris quis nunc fermentum ultrices eget a
     * erat. Mauris in lectus vitae metus sodales auctor. Morbi nunc
     * quam, ultricies at venenatis non, pellentesque ac dui.
     *
     * # Failure
     *
     * This function is full of fail
     */

    fail;
}

mod fortress_of_solitude {
    /*!
     * Superman's vacation home
     *
     * The fortress of solitude is located in the Arctic and it is
     * cold. What you may not know about the fortress of solitude
     * though is that it contains two separate bowling alleys. One of
     * them features bumper-bowling and is kind of lame.
     *
     * Really, it's pretty cool.
     */

}

mod blade_runner {
    /*!
     * Blade Runner is probably the best movie ever
     *
     * I like that in the world of Blade Runner it is always
     * raining, and that it's always night time. And Aliens
     * was also a really good movie.
     *
     * Alien 3 was crap though.
     */
}

/**
 * Bored
 *
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec
 * molestie nisl. Duis massa risus, pharetra a scelerisque a,
 * molestie eu velit. Donec mattis ligula at ante imperdiet ut
 * dapibus mauris malesuada. Sed gravida nisi a metus elementum sit
 * amet hendrerit dolor bibendum. Aenean sit amet neque massa, sed
 * tempus tortor. Sed ut lobortis enim. Proin a mauris quis nunc
 * fermentum ultrices eget a erat. Mauris in lectus vitae metus
 * sodales auctor. Morbi nunc quam, ultricies at venenatis non,
 * pellentesque ac dui.
 *
 * Quisque vitae est id eros placerat laoreet sit amet eu
 * nisi. Curabitur suscipit neque porttitor est euismod
 * lacinia. Curabitur non quam vitae ipsum adipiscing
 * condimentum. Mauris ut ante eget metus sollicitudin
 * blandit. Aliquam erat volutpat. Morbi sed nisl mauris. Nulla
 * facilisi. Phasellus at mollis ipsum. Maecenas sed convallis
 * sapien. Nullam in ligula turpis. Pellentesque a neque augue. Sed
 * eget ante feugiat tortor congue auctor ac quis ante. Proin
 * condimentum lacinia tincidunt.
 */
class bored {
  let bored: bool;
  new(bored: bool) { self.bored = bored; }
  drop { log(error, self.bored); }
}

/**
 * The Shunned House
 *
 * From even the greatest of horrors irony is seldom absent. Sometimes it
 * enters directly into the composition of the events, while sometimes it
 * relates only to their fortuitous position among persons and
 * places. The latter sort is splendidly exemplified by a case in the
 * ancient city of Providence, where in the late forties Edgar Allan Poe
 * used to sojourn often during his unsuccessful wooing of the gifted
 * poetess, Mrs.  Whitman. Poe generally stopped at the Mansion House in
 * Benefit Street--the renamed Golden Ball Inn whose roof has sheltered
 * Washington, Jefferson, and Lafayette--and his favorite walk led
 * northward along the same street to Mrs. Whitman's home and the
 * neighboring hillside churchyard of St. John's, whose hidden expanse of
 * Eighteenth Century gravestones had for him a peculiar fascination.
 */
iface the_shunned_house {
    /**
     * Now the irony is this. In this walk, so many times repeated, the
     * world's greatest master of the terrible and the bizarre was
     * obliged to pass a particular house on the eastern side of the
     * street; a dingy, antiquated structure perched on the abruptly
     * rising side hill, with a great unkempt yard dating from a time
     * when the region was partly open country. It does not appear that
     * he ever wrote or spoke of it, nor is there any evidence that he
     * even noticed it. And yet that house, to the two persons in
     * possession of certain information, equals or outranks in horror
     * the wildest fantasy of the genius who so often passed it
     * unknowingly, and stands starkly leering as a symbol of all that is
     * unutterably hideous.
     *
     * # Arguments
     *
     * * unkempt_yard - A yard dating from a time when the region was partly
     *                  open country
     */
    fn dingy_house(unkempt_yard: int);

    /**
     * The house was--and for that matter still is--of a kind to attract
     * the attention of the curious. Originally a farm or semi-farm
     * building, it followed the average New England colonial lines of
     * the middle Eighteenth Century--the prosperous peaked-roof sort,
     * with two stories and dormerless attic, and with the Georgian
     * doorway and interior panelling dictated by the progress of taste
     * at that time. It faced south, with one gable end buried to the
     * lower windows in the eastward rising hill, and the other exposed
     * to the foundations toward the street. Its construction, over a
     * century and a half ago, had followed the grading and straightening
     * of the road in that especial vicinity; for Benefit Street--at
     * first called Back Street--was laid out as a lane winding amongst
     * the graveyards of the first settlers, and straightened only when
     * the removal of the bodies to the North Burial Ground made it
     * decently possible to cut through the old family plots.
     */
    fn construct() -> bool;
}

/// Whatever
impl of the_shunned_house for omnomnomy {
    fn dingy_house(_unkempt_yard: int) {
    }

    fn construct() -> bool {
        fail;
    }
}
<|endoftext|>


<commit_before>use basic::{Type as PhysicalType, Repetition, LogicalType};
use errors::Result;
use errors::ParquetError;

enum TypeKind {
  PRIMITIVE,
  GROUP
}

/// A trait for a logical schema type. Structs who implement
/// this needs to implement the `get_basic_info()` function.
trait Type {
  fn is_primitive(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::PRIMITIVE => true,
      _ => false
    }
  }

  fn is_group(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::GROUP => true,
      _ => false
    }
  }

  fn name(&self) -> &str {
    return &self.get_basic_info().name;
  }

  fn repetition(&self) -> Repetition {
    return self.get_basic_info().repetition;
  }

  fn logical_type(&self) -> LogicalType {
    return self.get_basic_info().logical_type;
  }

  fn id(&self) -> i32 {
    return self.get_basic_info().id;
  }

  fn get_basic_info(&self) -> &BasicTypeInfo;
}

/// Basic type info. This contains information such as the name of the type,
/// the repetition level, the logical type and the kind of the type (group, primitive).
struct BasicTypeInfo {
  kind: TypeKind,
  name: &'static str,
  repetition: Repetition,
  logical_type: LogicalType,
  id: i32
}

/// Metadata for a decimal type (scale, precision).
struct DecimalMetadata {
  scale: i32,
  precision: i32
}

/// Representation of primitive types
struct PrimitiveType {
  basic_info: BasicTypeInfo,
  physical_type: PhysicalType,
  type_length: i32,
  decimal_metadata: Option<DecimalMetadata>
}

impl PrimitiveType {
  pub fn new(name: &'static str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             precision: i32, scale: i32, id: i32) -> Result<Self> {
    let mut decimal_metadata = None;
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: name, repetition: repetition,
      logical_type: logical_type, id: id};

    // TODO: more validity checks
    match logical_type {
      LogicalType::NONE => {
        decimal_metadata = Some(DecimalMetadata{precision, scale});
      },
      LogicalType::UTF8 | LogicalType::BSON | LogicalType::JSON => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(ParquetError::Schema(String::from("can only annotate BYTE_ARRAY fields")))
        }
      },
      LogicalType::DECIMAL => {
        if precision < 0 {
          // TODO: how can we make ParquetError::Schema to accept `&'static str`?
          return Err(ParquetError::Schema(
            format!("Precision must be non-negative, but found {}", precision)))
        }
        if scale < 0 {
          return Err(ParquetError::Schema(
            format!("Scale must be non-negative, but found {}", scale)))
        }
        decimal_metadata = Some(DecimalMetadata{precision, scale})
      }
      _ => {
        return Err(ParquetError::Schema(String::from("can only annotate BYTE_ARRAY fields")))
      }
    };
    Ok(PrimitiveType{
      basic_info: basic_info,
      physical_type: physical_type,
      type_length: length,
      decimal_metadata: decimal_metadata
    })
  }
}

impl Type for PrimitiveType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }
}

/// Representation of group types
struct GroupType {
  basic_info: BasicTypeInfo,
  fields: Vec<Box<Type>>
}

impl GroupType {
  pub fn new(name: &'static str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             fields: Vec<Box<Type>>, id: i32) -> Result<Self> {
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: name, repetition: repetition,
      logical_type: logical_type, id: id};
    Ok(GroupType{
      basic_info: basic_info,
      fields: fields
    })
  }

  pub fn num_fields(&self) -> usize {
    return self.fields.len()
  }

  pub fn field(&mut self, index: usize) -> &mut Box<Type> {
    return &mut self.fields[index]
  }
}

impl Type for GroupType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }
}
<commit_msg>Adding primitive validity checks<commit_after>use basic::{Type as PhysicalType, Repetition, LogicalType};
use errors::Result;
use errors::ParquetError;

enum TypeKind {
  PRIMITIVE,
  GROUP
}

/// A trait for a logical schema type. Structs who implement
/// this needs to implement the `get_basic_info()` function.
trait Type {
  fn is_primitive(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::PRIMITIVE => true,
      _ => false
    }
  }

  fn is_group(&self) -> bool {
    return match self.get_basic_info().kind {
      TypeKind::GROUP => true,
      _ => false
    }
  }

  fn name(&self) -> &str {
    return &self.get_basic_info().name;
  }

  fn repetition(&self) -> Repetition {
    return self.get_basic_info().repetition;
  }

  fn logical_type(&self) -> LogicalType {
    return self.get_basic_info().logical_type;
  }

  fn id(&self) -> i32 {
    return self.get_basic_info().id;
  }

  fn get_basic_info(&self) -> &BasicTypeInfo;
}

/// Basic type info. This contains information such as the name of the type,
/// the repetition level, the logical type and the kind of the type (group, primitive).
struct BasicTypeInfo {
  kind: TypeKind,
  name: &'static str,
  repetition: Repetition,
  logical_type: LogicalType,
  id: i32
}

/// Metadata for a decimal type (scale, precision).
struct DecimalMetadata {
  scale: i32,
  precision: i32
}

/// Representation of primitive types
struct PrimitiveType {
  basic_info: BasicTypeInfo,
  physical_type: PhysicalType,
  type_length: i32,
  decimal_metadata: Option<DecimalMetadata>
}

impl PrimitiveType {
  pub fn new(name: &'static str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             precision: i32, scale: i32, id: i32) -> Result<Self> {
    let mut decimal_metadata = None;
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: name, repetition: repetition,
      logical_type: logical_type, id: id};

    match logical_type {
      LogicalType::NONE => {
        decimal_metadata = Some(DecimalMetadata{precision, scale});
      },
      LogicalType::UTF8 | LogicalType::BSON | LogicalType::JSON => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(ParquetError::Schema(
            format!("{} can only annotate BYTE_ARRAY fields", logical_type)))
        }
      },
      LogicalType::DECIMAL => {
        match physical_type {
          PhysicalType::INT32 | PhysicalType::INT64 | PhysicalType::BYTE_ARRAY |
          PhysicalType::FIXED_LEN_BYTE_ARRAY => (),
          _ => {
            return Err(ParquetError::Schema(
            format!("DECIMAL can only annotate INT32, INT64, BYTE_ARRAY and FIXED")))
          }
        };
        if precision < 0 {
          // TODO: how can we make ParquetError::Schema to accept `&'static str`?
          return Err(ParquetError::Schema(
            format!("Invalid DECIMAL precision: {}", precision)))
        }
        if scale < 0 {
          return Err(ParquetError::Schema(
            format!("Invalid DECIMAL scale: {}", scale)))
        }
        if scale > precision {
          return Err(ParquetError::Schema(
            format!("Invalid DECIMAL: scale {} cannot be greater than precision {}",
                    scale, precision)))
        }
        decimal_metadata = Some(DecimalMetadata{precision, scale})
      }
      LogicalType::DATE | LogicalType::TIME_MILLIS | LogicalType::UINT_8 |
      LogicalType::UINT_16 | LogicalType::UINT_32 |
      LogicalType::INT_8 | LogicalType::INT_16 | LogicalType::INT_32 => {
        if physical_type != PhysicalType::INT32 {
          return Err(ParquetError::Schema(
            format!("{} can only annotate INT32", logical_type)))
        }
      }
      LogicalType::TIME_MICROS | LogicalType::TIMESTAMP_MILLIS |
      LogicalType::TIMESTAMP_MICROS | LogicalType::UINT_64 | LogicalType::INT_64 => {
        if physical_type != PhysicalType::INT64 {
          return Err(ParquetError::Schema(
            format!("{} can only annotate INT64", logical_type)))
        }
      }
      LogicalType::INTERVAL => {
        if physical_type != PhysicalType::FIXED_LEN_BYTE_ARRAY || length != 12 {
          return Err(ParquetError::Schema(String::from("INTERVAL can only annotate FIXED(12)")))
        }
      }
      LogicalType::ENUM => {
        if physical_type != PhysicalType::BYTE_ARRAY {
          return Err(ParquetError::Schema(
            String::from("ENUM can only annotate BYTE_ARRAY fields")))
        }
      }
      _ => {
        return Err(ParquetError::Schema(
          format!("{} cannot be applied to a primitive type", logical_type)))
      }
    };
    if physical_type == PhysicalType::FIXED_LEN_BYTE_ARRAY && length < 0 {
      return Err(ParquetError::Schema(
        format!("Invalid FIXED_LEN_BYTE_ARRAY length: {}", length)
      ))
    }
    Ok(PrimitiveType{
      basic_info: basic_info,
      physical_type: physical_type,
      type_length: length,
      decimal_metadata: decimal_metadata
    })
  }
}

impl Type for PrimitiveType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }
}

/// Representation of group types
struct GroupType {
  basic_info: BasicTypeInfo,
  fields: Vec<Box<Type>>
}

impl GroupType {
  pub fn new(name: &'static str, repetition: Repetition, physical_type: PhysicalType,
             logical_type: LogicalType, length: i32,
             fields: Vec<Box<Type>>, id: i32) -> Result<Self> {
    let basic_info = BasicTypeInfo{
      kind: TypeKind::PRIMITIVE, name: name, repetition: repetition,
      logical_type: logical_type, id: id};
    Ok(GroupType{
      basic_info: basic_info,
      fields: fields
    })
  }

  pub fn num_fields(&self) -> usize {
    return self.fields.len()
  }

  pub fn field(&mut self, index: usize) -> &mut Box<Type> {
    return &mut self.fields[index]
  }
}

impl Type for GroupType {
  fn get_basic_info(&self) -> &BasicTypeInfo {
    return &self.basic_info;
  }
}
<|endoftext|>


<commit_before>use common::memory::*;
use common::scheduler::*;

use drivers::disk::*;

use programs::common::*;

#[derive(Copy, Clone)]
#[repr(packed)]
pub struct Extent{
    pub block: u64,
    pub length: u64
}

#[repr(packed)]
pub struct Header {
    pub signature: [u8; 8],
    pub version: u32,
    pub name: [u8; 244],
    pub extents: [Extent; 16]
}

#[repr(packed)]
pub struct Node {
    pub name: [u8; 256],
    pub extents: [Extent; 16]
}

impl Clone for Node {
    fn clone(&self) -> Node {
        return Node {
            name: self.name,
            extents: self.extents
        };
    }
}

pub struct FileSystem {
    pub disk: Disk,
    pub header: Header,
    pub nodes: Vec<Node>
}

impl FileSystem {
    pub fn from_disk(disk: Disk) -> FileSystem{
        unsafe{
            let header_ptr: *const Header = alloc_type();
            disk.read(1, 1, header_ptr as usize);
            let header = ptr::read(header_ptr);
            unalloc(header_ptr as usize);

            let mut nodes = Vec::new();
            let node_ptr: *const Node = alloc_type();
            for extent in &header.extents {
                if extent.block > 0 {
                    for node_address in extent.block..extent.block + (extent.length + 511)/512 {
                        disk.read(node_address, 1, node_ptr as usize);
                        nodes.push(ptr::read(node_ptr));
                    }
                }
            }
            unalloc(node_ptr as usize);

            return FileSystem {
                disk:disk,
                header: header,
                nodes: nodes
            };
        }
    }

    pub fn valid(&self) -> bool {
        return self.header.signature[0] == 'R' as u8
            && self.header.signature[1] == 'E' as u8
            && self.header.signature[2] == 'D' as u8
            && self.header.signature[3] == 'O' as u8
            && self.header.signature[4] == 'X' as u8
            && self.header.signature[5] == 'F' as u8
            && self.header.signature[6] == 'S' as u8
            && self.header.signature[7] == '\0' as u8
            && self.header.version == 0xFFFFFFFF;
    }

    pub fn node(&self, filename: &String) -> Option<Node>{
        for node in self.nodes.iter() {
            if String::from_c_slice(&node.name) == *filename {
                return Option::Some(node.clone());
            }
        }

        return Option::None;
    }

    pub fn list(&self, directory: &String) -> Vec<String> {
        let mut ret = Vec::<String>::new();

        for node in self.nodes.iter() {
            let node_name = String::from_c_slice(&node.name);
            if node_name.starts_with(directory.clone()) {
                ret.push(node_name.substr(directory.len(), node_name.len() - directory.len()));
            }
        }

        return ret;
    }
}

pub struct FileResource {
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize
}

impl Resource for FileResource {
    fn url(&self) -> URL {
        return URL::from_string(&String::from_c_slice(&self.node.name));
    }

    fn stat(&self) -> ResourceType {
        return ResourceType::File;
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Option::Some(b) => buf[i] = *b,
                Option::None => ()
            }
            self.seek += 1;
            i += 1;
        }
        return Option::Some(i);
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec.set(self.seek, buf[i]);
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        return Option::Some(i);
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) => self.seek = max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) => self.seek = max(0, self.vec.len() as isize + offset) as usize
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        return Option::Some(self.seek);
    }

    fn flush(&mut self) -> bool {
        return false;
    }
}

pub struct FileScheme {
    pub fs: FileSystem
}

impl SessionItem for FileScheme {
    fn scheme(&self) -> String {
        return "file".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource>{
        let path = url.path();
        if path.len() == 0 || path.ends_with("/".to_string()) {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in self.fs.list(&path).iter() {
                let line;
                match file.find("/".to_string()) {
                    Option::Some(index) => {
                        let dirname = file.substr(0, index + 1);
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line = String::new();
                        }else{
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    },
                    Option::None => line = file.clone()
                }
                if line.len() > 0 {
                    if list.len() > 0 {
                        list = list + '\n' + line;
                    }else{
                        list = line;
                    }
                }
            }

            return box VecResource::new(url.clone(), ResourceType::Dir, list.to_utf8());
        }else{
            match self.fs.node(&path) {
                Option::Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    if node.extents[0].block > 0 && node.extents[0].length > 0 {
                        unsafe {
                            let data = alloc(node.extents[0].length as usize);
                            if data > 0 {
                                let reenable = start_no_ints();

                                self.fs.disk.read(node.extents[0].block, ((node.extents[0].length + 511)/512) as u16, data);

                                end_no_ints(reenable);

                                vec = Vec {
                                    data: data as *mut u8,
                                    length: node.extents[0].length as usize
                                };
                            }
                        }
                    }

                    return box FileResource {
                        node: node,
                        vec: vec,
                        seek: 0
                    };
                },
                Option::None => return box NoneResource
            }
        }
    }
}
<commit_msg>WIP Insert nodes<commit_after>use common::memory::*;
use common::scheduler::*;

use drivers::disk::*;

use programs::common::*;

#[derive(Copy, Clone)]
#[repr(packed)]
pub struct Extent{
    pub block: u64,
    pub length: u64
}

#[repr(packed)]
pub struct Header {
    pub signature: [u8; 8],
    pub version: u32,
    pub name: [u8; 244],
    pub extents: [Extent; 16]
}

#[repr(packed)]
pub struct Node {
    pub name: [u8; 256],
    pub extents: [Extent; 16]
}

impl Clone for Node {
    fn clone(&self) -> Node {
        return Node {
            name: self.name,
            extents: self.extents
        };
    }
}

pub struct FileSystem {
    pub disk: Disk,
    pub header: Header,
    pub nodes: Vec<Node>
}

impl FileSystem {
    pub fn from_disk(disk: Disk) -> FileSystem{
        unsafe{
            let header_ptr: *const Header = alloc_type();
            disk.read(1, 1, header_ptr as usize);
            let header = ptr::read(header_ptr);
            unalloc(header_ptr as usize);

            let mut nodes = Vec::new();
            let node_ptr: *const Node = alloc_type();
            for extent in &header.extents {
                if extent.block > 0 {
                    for node_address in extent.block..extent.block + (extent.length + 511)/512 {
                        disk.read(node_address, 1, node_ptr as usize);
                        nodes.push(ptr::read(node_ptr));
                    }
                }
            }
            unalloc(node_ptr as usize);

            return FileSystem {
                disk:disk,
                header: header,
                nodes: nodes
            };
        }
    }

    pub fn valid(&self) -> bool {
        return self.header.signature[0] == 'R' as u8
            && self.header.signature[1] == 'E' as u8
            && self.header.signature[2] == 'D' as u8
            && self.header.signature[3] == 'O' as u8
            && self.header.signature[4] == 'X' as u8
            && self.header.signature[5] == 'F' as u8
            && self.header.signature[6] == 'S' as u8
            && self.header.signature[7] == '\0' as u8
            && self.header.version == 0xFFFFFFFF;
    }

    pub fn node(&self, filename: &String) -> Option<Node>{
        for node in self.nodes.iter() {
            if String::from_c_slice(&node.name) == *filename {
                return Option::Some(node.clone());
            }
        }

        return Option::None;
    }

    pub fn list(&self, directory: &String) -> Vec<String> {
        let mut ret = Vec::<String>::new();

        for node in self.nodes.iter() {
            let node_name = String::from_c_slice(&node.name);
            if node_name.starts_with(directory.clone()) {
                ret.push(node_name.substr(directory.len(), node_name.len() - directory.len()));
            }
        }

        return ret;
    }
}

pub struct FileResource {
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize
}

impl Resource for FileResource {
    fn url(&self) -> URL {
        return URL::from_string(&String::from_c_slice(&self.node.name));
    }

    fn stat(&self) -> ResourceType {
        return ResourceType::File;
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Option::Some(b) => buf[i] = *b,
                Option::None => ()
            }
            self.seek += 1;
            i += 1;
        }
        return Option::Some(i);
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec.set(self.seek, buf[i]);
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        return Option::Some(i);
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) => self.seek = max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) => self.seek = max(0, self.vec.len() as isize + offset) as usize
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        return Option::Some(self.seek);
    }

    fn flush(&mut self) -> bool {
        return false;
    }
}

pub struct FileScheme {
    pub fs: FileSystem
}

impl SessionItem for FileScheme {
    fn scheme(&self) -> String {
        return "file".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource>{
        let path = url.path();
        if path.len() == 0 || path.ends_with("/".to_string()) {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in self.fs.list(&path).iter() {
                let line;
                match file.find("/".to_string()) {
                    Option::Some(index) => {
                        let dirname = file.substr(0, index + 1);
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line = String::new();
                        }else{
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    },
                    Option::None => line = file.clone()
                }
                if line.len() > 0 {
                    if list.len() > 0 {
                        list = list + '\n' + line;
                    }else{
                        list = line;
                    }
                }
            }

            return box VecResource::new(url.clone(), ResourceType::Dir, list.to_utf8());
        }else{
            match self.fs.node(&path) {
                Option::Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    if node.extents[0].block > 0 && node.extents[0].length > 0 {
                        unsafe {
                            let data = alloc(node.extents[0].length as usize);
                            if data > 0 {
                                let reenable = start_no_ints();

                                self.fs.disk.read(node.extents[0].block, ((node.extents[0].length + 511)/512) as u16, data);

                                end_no_ints(reenable);

                                vec = Vec {
                                    data: data as *mut u8,
                                    length: node.extents[0].length as usize
                                };
                            }
                        }
                    }

                    return box FileResource {
                        node: node,
                        vec: vec,
                        seek: 0
                    };
                },
                Option::None => {
                    d("Creating ");
                    path.d();
                    dl();

                    let mut name = [0; 256];
                    for i in 0..256 {
                        //TODO: UTF8
                        let b = path[i] as u8;
                        name[i] = b;
                        if b == 0 {
                            break;
                        }
                    }

                    let node = Node {
                        name: name,
                        extents: [Extent { block: 0, length: 0 }; 16]
                    };

                    //TODO: Sync to disk
                    let mut node_i = 0;
                    while node_i < self.fs.nodes.len() {
                        let mut cmp = 0;

                        if let Option::Some(other_node) = self.fs.nodes.get(node_i) {
                            for i in 0..256 {
                                if other_node.name[i] != node.name[i] {
                                    cmp = other_node.name[i] as isize - node.name[i] as isize;
                                    break;
                                }
                            }
                        }

                        if cmp >= 0 {
                            break;
                        }

                        node_i += 1;
                    }
                    d("Insert at ");
                    dd(node_i);
                    dl();
                    self.fs.nodes.insert(node_i, node.clone());

                    return box FileResource {
                        node: node,
                        vec: Vec::new(),
                        seek: 0
                    };
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::cast;
use rect::Rect;
use get_error;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *c_void,
        pub userdata: *c_void,
        pub locked: c_int,
        pub lock_data: *c_void,
        pub clip_rect: SDL_Rect,
        pub map: *SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_FreeSurface(surface: *SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *SDL_Surface, palette: *SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *SDL_RWops, freesrc: c_int) ->  *SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *SDL_Surface, dst: *SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *SDL_Surface, key: *uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *SDL_Surface, r: *uint8_t, g: *uint8_t, b: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
        pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    }
}

flag_type!(SurfaceFlag {
    SWSurface = ll::SDL_SWSURFACE,
    PreAlloc = ll::SDL_PREALLOC,
    RLEAccel = ll::SDL_RLEACCEL,
    DontFree = ll::SDL_DONTFREE
})

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Surface {
    pub raw: *ll::SDL_Surface,
    pub owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> Result<Surface, ~str> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.get(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> u16 {
        unsafe { (*self.raw).w as u16 }
    }

    pub fn get_height(&self) -> u16 {
        unsafe { (*self.raw).h as u16 }
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        pixels::PixelFormat {
            raw: unsafe { (*self.raw).format }
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = cast::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> Result<Surface, ~str> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw, 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> Result<(), ~str> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw, 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw) == 0
        }
    }

    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> Result<(), ~str> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, ::std::bool::to_bit(enable), key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> Result<pixels::Color, ~str> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> Result<pixels::Color, ~str> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }

    pub fn upper_blit( &self, src: &Surface, dstrect: Option<Rect>, srcrect: Option<Rect> ) -> bool {
        unsafe {
            match( srcrect, dstrect ) {
                (Some( srcrect ), Some( dstrect )) =>
                    ll::SDL_UpperBlit( src.raw, &srcrect, self.raw, &dstrect ) == 0,
                (Some( srcrect ), None) =>
                    ll::SDL_UpperBlit( src.raw, &srcrect, self.raw, ptr::null() ) == 0,
                (None, Some( dstrect )) =>
                    ll::SDL_UpperBlit( src.raw, ptr::null(), self.raw, &dstrect ) == 0,
                (None, None) =>
                    ll::SDL_UpperBlit( src.raw, ptr::null(), self.raw, ptr::null() ) == 0
            }
        }
    }

    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<commit_msg>Make upper_blit use transmute instead of match<commit_after>use std::cast;
use rect::Rect;
use get_error;
use std::ptr;
use libc::c_int;
use pixels;
use rwops;

#[allow(non_camel_case_types)]
pub mod ll {
    use pixels::ll::SDL_PixelFormat;
    use pixels::ll::SDL_Palette;
    use render::ll::SDL_BlendMode;
    use rwops::ll::SDL_RWops;
    use rect::Rect;
    use libc::{c_int, c_void, uint32_t, uint8_t};
    pub type SDL_Rect = Rect;
    pub type SDL_bool = c_int;

    pub type SDL_SurfaceFlag = c_int;

    pub static SDL_SWSURFACE: SDL_SurfaceFlag = 0;
    pub static SDL_PREALLOC: SDL_SurfaceFlag = 0x00000001;
    pub static SDL_RLEACCEL: SDL_SurfaceFlag = 0x00000002;
    pub static SDL_DONTFREE: SDL_SurfaceFlag = 0x00000004;

    //SDL_surface.h
    pub struct SDL_BlitMap;

    pub struct SDL_Surface {
        pub flags: uint32_t,
        pub format: *SDL_PixelFormat,
        pub w: c_int,
        pub h: c_int,
        pub pitch: c_int,
        pub pixels: *c_void,
        pub userdata: *c_void,
        pub locked: c_int,
        pub lock_data: *c_void,
        pub clip_rect: SDL_Rect,
        pub map: *SDL_BlitMap,
        pub refcount: c_int
    }

    extern "C" {
        pub fn SDL_CreateRGBSurface(flags: uint32_t, width: c_int, height: c_int, depth: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_CreateRGBSurfaceFrom(pixels: *c_void, width: c_int, height: c_int, depth: c_int, pitch: c_int, Rmask: uint32_t, Gmask: uint32_t, Bmask: uint32_t, Amask: uint32_t) ->  *SDL_Surface;
        pub fn SDL_FreeSurface(surface: *SDL_Surface);
        pub fn SDL_SetSurfacePalette(surface: *SDL_Surface, palette: *SDL_Palette) -> c_int;
        pub fn SDL_LockSurface(surface: *SDL_Surface) -> c_int;
        pub fn SDL_UnlockSurface(surface: *SDL_Surface);
        pub fn SDL_LoadBMP_RW(src: *SDL_RWops, freesrc: c_int) ->  *SDL_Surface;
        pub fn SDL_SaveBMP_RW(surface: *SDL_Surface, dst: *SDL_RWops, freedst: c_int) -> c_int;
        pub fn SDL_SetSurfaceRLE(surface: *SDL_Surface, flag: c_int) -> c_int;
        pub fn SDL_SetColorKey(surface: *SDL_Surface, flag: c_int, key: uint32_t) -> c_int;
        pub fn SDL_GetColorKey(surface: *SDL_Surface, key: *uint32_t) -> c_int;
        pub fn SDL_SetSurfaceColorMod(surface: *SDL_Surface, r: uint8_t, g: uint8_t, b: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceColorMod(surface: *SDL_Surface, r: *uint8_t, g: *uint8_t, b: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
        pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
        pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
        pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
        pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
        pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
        pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
        pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
        pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
        pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
        pub fn SDL_UpperBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
        pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    }
}

flag_type!(SurfaceFlag {
    SWSurface = ll::SDL_SWSURFACE,
    PreAlloc = ll::SDL_PREALLOC,
    RLEAccel = ll::SDL_RLEACCEL,
    DontFree = ll::SDL_DONTFREE
})

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Surface {
    pub raw: *ll::SDL_Surface,
    pub owned: bool
}

impl Drop for Surface {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeSurface(self.raw);
            }
        }
    }
}

impl Surface {
    pub fn new(surface_flags: SurfaceFlag, width: int, height: int, bpp: int,
               rmask: u32, gmask: u32, bmask: u32, amask: u32) -> Result<Surface, ~str> {
        unsafe {
            let raw = ll::SDL_CreateRGBSurface(surface_flags.get(), width as c_int, height as c_int, bpp as c_int,
                                               rmask, gmask, bmask, amask);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Surface { raw: raw, owned: true })
            }
        }
    }

    //TODO: From Data
    pub fn get_width(&self) -> u16 {
        unsafe { (*self.raw).w as u16 }
    }

    pub fn get_height(&self) -> u16 {
        unsafe { (*self.raw).h as u16 }
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.get_width(), self.get_height())
    }

    pub fn get_rect(&self) -> Rect {
        Rect {
            x: 0,
            y: 0,
            w: self.get_width() as i32,
            h: self.get_height() as i32
        }
    }

    pub fn get_pixel_format(&self) -> pixels::PixelFormat {
        pixels::PixelFormat {
            raw: unsafe { (*self.raw).format }
        }
    }

    pub fn lock(&self) -> bool {
        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
    }

    /// Locks a surface so that the pixels can be directly accessed safely.
    pub fn with_lock<R>(&self, f: |pixels: &mut [u8]| -> R) -> R {
        unsafe {
            if ll::SDL_LockSurface(self.raw) != 0 { fail!("could not lock surface"); }
            let len = (*self.raw).pitch as uint * ((*self.raw).h as uint);
            let pixels: &mut [u8] = cast::transmute(((*self.raw).pixels, len));
            let rv = f(pixels);
            ll::SDL_UnlockSurface(self.raw);
            rv
        }
    }

    pub fn unlock(&self) {
        unsafe { ll::SDL_UnlockSurface(self.raw); }
    }

    pub fn from_bmp(path: &Path) -> Result<Surface, ~str> {
        let raw = unsafe {
            ll::SDL_LoadBMP_RW(try!(rwops::RWops::from_file(path, "rb")).raw, 0)
        };

        if raw.is_null() { Err(get_error()) }
        else { Ok(Surface{raw: raw, owned: true}) }
    }

    pub fn save_bmp(&self, path: &Path) -> Result<(), ~str> {
	let ret = unsafe {
            ll::SDL_SaveBMP_RW(self.raw, try!(rwops::RWops::from_file(path, "rb")).raw, 0)
	};
        if ret == 0 { Ok(()) }
        else { Err(get_error()) }
    }

    pub fn set_palette(&self, palette: &pixels::Palette) -> bool {
        unsafe {
            ll::SDL_SetSurfacePalette(self.raw, palette.raw) == 0
        }
    }

    pub fn enable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 1) == 0
        }
    }

    pub fn disable_RLE(&self) -> bool {
        unsafe {
            ll::SDL_SetSurfaceRLE(self.raw, 0) == 0
        }
    }

    pub fn set_color_key(&self, enable: bool, color: pixels::Color) -> Result<(), ~str> {
        let key = color.to_u32(&self.get_pixel_format());
        let result = unsafe {
            ll::SDL_SetColorKey(self.raw, ::std::bool::to_bit(enable), key)
        };
        if result == 0 {
            Ok(())
        } else {
            Err(get_error())
        }
    }

    pub fn get_color_key(&self) -> Result<pixels::Color, ~str> {
        let key: u32 = 0;
        let result = unsafe {
            ll::SDL_GetColorKey(self.raw, &key)
        };

        if result == 0 {
            Ok(pixels::Color::from_u32(&self.get_pixel_format(), key))
        } else {
            Err(get_error())
        }
    }

    pub fn set_color_mod(&self, color: pixels::Color) -> bool {
        let (r, g, b) = match color {
            pixels::RGB(r, g, b) => (r, g, b),
            pixels::RGBA(r, g, b, _) => (r, g, b)
        };

        unsafe {
            ll::SDL_SetSurfaceColorMod(self.raw, r, g, b) == 0
        }
    }

    pub fn get_color_mod(&self) -> Result<pixels::Color, ~str> {
        let r: u8 = 0;
        let g: u8 = 0;
        let b: u8 = 0;

        let result = unsafe {
            ll::SDL_GetSurfaceColorMod(self.raw, &r, &g, &b) == 0
        };

        if result {
            Ok(pixels::RGB(r,g,b))
        } else {
            Err(get_error())
        }
    }

    pub fn upper_blit( &self, src: &Surface, dstrect: Option<Rect>, srcrect: Option<Rect> ) -> bool {
        unsafe {
            let dstrect_ptr = mem::transmute( dstrect.as_ref() );
            let srcrect_ptr = mem::transmute( srcrect.as_ref() );
            ll::SDL_UpperBlit( src.raw, srcrect_ptr, self.raw, dstrect_ptr ) == 0
        }
    }

    /*
    pub fn SDL_SetSurfaceAlphaMod(surface: *SDL_Surface, alpha: uint8_t) -> c_int;
    pub fn SDL_GetSurfaceAlphaMod(surface: *SDL_Surface, alpha: *uint8_t ) -> c_int;
    pub fn SDL_SetSurfaceBlendMode(surface: *SDL_Surface, blendMode: SDL_BlendMode) -> c_int;
    pub fn SDL_GetSurfaceBlendMode(surface: *SDL_Surface, blendMode: *SDL_BlendMode) -> c_int;
    pub fn SDL_SetClipRect(surface: *SDL_Surface, rect: *SDL_Rect) ->  SDL_bool;
    pub fn SDL_GetClipRect(surface: *SDL_Surface, rect: *SDL_Rect);
    pub fn SDL_ConvertSurface(src: *SDL_Surface, fmt: *SDL_PixelFormat, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertSurfaceFormat(src: *SDL_Surface, pixel_format: uint32_t, flags: uint32_t) ->  *SDL_Surface;
    pub fn SDL_ConvertPixels(width: c_int, height: c_int, src_format: uint32_t, src: *c_void, src_pitch: c_int, dst_format: uint32_t, dst: *c_void, dst_pitch: c_int) -> c_int;
    pub fn SDL_FillRect(dst: *SDL_Surface, rect: *SDL_Rect, color: uint32_t) -> c_int;
    pub fn SDL_FillRects(dst: *SDL_Surface, rects: *SDL_Rect, count: c_int, color: uint32_t) -> c_int;
    pub fn SDL_LowerBlit(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_SoftStretch(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_UpperBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int;
    pub fn SDL_LowerBlitScaled(src: *SDL_Surface, srcrect: *SDL_Rect, dst: *SDL_Surface, dstrect: *SDL_Rect) -> c_int)*/
}
<|endoftext|>


<commit_before>use failure::{format_err, Error};
use log::error;
use nalgebra::{Point2, Vector2};
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;

use super::{GameInputMessage, PlayerColor};

const ARENA_WIDTH: usize = 800;
const ARENA_HEIGHT: usize = 800;
const LIGHTCYCLE_SPEED: isize = 120;

#[derive(Debug, Default, Serialize)]
pub struct Arena {
    width: usize,
    height: usize,

    lightcycles: HashMap<Uuid, Lightcycle>,
    trails: HashMap<Uuid, Trail>,
}

#[derive(Debug, Serialize)]
pub struct Lightcycle {
    position: Point2<isize>,
    rotation: Direction,
    speed: isize,
    color: PlayerColor,
    dead: bool,
}

impl Default for Lightcycle {
    fn default() -> Self {
        Self {
            position: Point2::origin(),
            rotation: Direction::Up,
            speed: LIGHTCYCLE_SPEED,
            color: Default::default(),
            dead: Default::default(),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub enum Direction {
    Up,
    Left,
    Right,
    Down,
}

impl Direction {
    pub fn as_velocity(&self) -> Vector2<isize> {
        match self {
            Direction::Up => Vector2::new(0, 1),
            Direction::Down => Vector2::new(0, -1),
            Direction::Left => Vector2::new(-1, 0),
            Direction::Right => Vector2::new(1, 0),
        }
    }
}

#[derive(Debug, Serialize)]
pub struct Trail {
    points: Vec<Point2<isize>>,
    color: PlayerColor,
}

impl Arena {
    pub fn new() -> Self {
        Self {
            width: ARENA_WIDTH,
            height: ARENA_HEIGHT,
            ..Default::default()
        }
    }

    pub fn process_input(&mut self, input_events: Vec<(Uuid, GameInputMessage)>) {
        for (client_id, input_event) in input_events {
            match input_event {
                // TODO: Make new GameInput type that is specific to arena input
                // GameInputMessage::StartGame is not relevant here, should be
                // consumed by the game or match system
                GameInputMessage::StartGame => unimplemented!(),
                GameInputMessage::Turn(direction) => {
                    self.turn_lightcycle(client_id, direction)
                        .unwrap_or_else(|error| error!("Failed to turn lightcycle: {}", error));
                }
            }
        }
    }

    pub fn update(&mut self) {
        self.update_lightcycle_positions()
            .update_trail_positions()
            .calculate_lightcycle_collisions();
    }

    //
    // process_input helpers
    //

    fn turn_lightcycle(&mut self, id: Uuid, direction: Direction) -> Result<(), Error> {
        let lightcycle = self
            .lightcycles
            .get_mut(&id)
            .ok_or_else(|| format_err!("No lightcycle with id {}", id))?;

        // TODO: Prevent turning 180° in one update (will immediately crash into own trail)
        lightcycle.rotation = direction;

        Ok(())
    }

    //
    // update helpers
    //

    fn update_lightcycle_positions(&mut self) -> &mut Self {
        for lightcycle in self.lightcycles.values_mut() {
            if lightcycle.dead {
                continue;
            };

            lightcycle.position += lightcycle.rotation.as_velocity() * lightcycle.speed;
        }
        self
    }

    fn update_trail_positions(&mut self) -> &mut Self {
        for (id, trail) in self.trails.iter_mut() {
            let latest_point = match self.lightcycles.get(id) {
                Some(lightcycle) => {
                    if lightcycle.dead {
                        continue;
                    };

                    lightcycle.position
                }
                None => {
                    error!(
                        "Failed to update trail position: No lightcycle with id {}",
                        id
                    );
                    continue;
                }
            };

            trail.points.pop();
            trail.points.push(latest_point.clone());
        }
        self
    }

    fn calculate_lightcycle_collisions(&mut self) -> &mut Self {
        for lightcycle in self.lightcycles.values_mut() {
            if lightcycle.dead {
                continue;
            };

            for trail in self.trails.values() {
                for line in trail.points.windows(2) {
                    let start = line[0];
                    let end = line[1];

                    if is_point_on_line_2d(lightcycle.position, (start, end)) {
                        lightcycle.dead = true;
                        continue;
                    }
                }
            }
        }

        self
    }
}

fn is_point_on_line_2d(point: Point2<isize>, line: (Point2<isize>, Point2<isize>)) -> bool {
    let (start, end) = line;

    if start.x == end.x {
        if point.x != start.x {
            return false;
        }

        return is_point_on_line_1d(point.y, (start.y, end.y));
    }

    if start.y == end.y {
        if point.y != start.y {
            return false;
        }

        return is_point_on_line_1d(point.x, (start.x, end.x));
    }

    false
}

fn is_point_on_line_1d(point: isize, line: (isize, isize)) -> bool {
    let (low, high) = if line.0 <= line.1 {
        (line.0, line.1)
    } else {
        (line.1, line.0)
    };

    if point < low || high < point {
        return false;
    }

    true
}
<commit_msg>fixed collisions calculation bug: unecessary checks against dead lightcycles<commit_after>use failure::{format_err, Error};
use log::error;
use nalgebra::{Point2, Vector2};
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;

use super::{GameInputMessage, PlayerColor};

const ARENA_WIDTH: usize = 800;
const ARENA_HEIGHT: usize = 800;
const LIGHTCYCLE_SPEED: isize = 120;

#[derive(Debug, Default, Serialize)]
pub struct Arena {
    width: usize,
    height: usize,

    lightcycles: HashMap<Uuid, Lightcycle>,
    trails: HashMap<Uuid, Trail>,
}

#[derive(Debug, Serialize)]
pub struct Lightcycle {
    position: Point2<isize>,
    rotation: Direction,
    speed: isize,
    color: PlayerColor,
    dead: bool,
}

impl Default for Lightcycle {
    fn default() -> Self {
        Self {
            position: Point2::origin(),
            rotation: Direction::Up,
            speed: LIGHTCYCLE_SPEED,
            color: Default::default(),
            dead: Default::default(),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub enum Direction {
    Up,
    Left,
    Right,
    Down,
}

impl Direction {
    pub fn as_velocity(&self) -> Vector2<isize> {
        match self {
            Direction::Up => Vector2::new(0, 1),
            Direction::Down => Vector2::new(0, -1),
            Direction::Left => Vector2::new(-1, 0),
            Direction::Right => Vector2::new(1, 0),
        }
    }
}

#[derive(Debug, Serialize)]
pub struct Trail {
    points: Vec<Point2<isize>>,
    color: PlayerColor,
}

impl Arena {
    pub fn new() -> Self {
        Self {
            width: ARENA_WIDTH,
            height: ARENA_HEIGHT,
            ..Default::default()
        }
    }

    pub fn process_input(&mut self, input_events: Vec<(Uuid, GameInputMessage)>) {
        for (client_id, input_event) in input_events {
            match input_event {
                // TODO: Make new GameInput type that is specific to arena input
                // GameInputMessage::StartGame is not relevant here, should be
                // consumed by the game or match system
                GameInputMessage::StartGame => unimplemented!(),
                GameInputMessage::Turn(direction) => {
                    self.turn_lightcycle(client_id, direction)
                        .unwrap_or_else(|error| error!("Failed to turn lightcycle: {}", error));
                }
            }
        }
    }

    pub fn update(&mut self) {
        self.update_lightcycle_positions()
            .update_trail_positions()
            .calculate_lightcycle_collisions();
    }

    //
    // process_input helpers
    //

    fn turn_lightcycle(&mut self, id: Uuid, direction: Direction) -> Result<(), Error> {
        let lightcycle = self
            .lightcycles
            .get_mut(&id)
            .ok_or_else(|| format_err!("No lightcycle with id {}", id))?;

        // TODO: Prevent turning 180° in one update (will immediately crash into own trail)
        lightcycle.rotation = direction;

        Ok(())
    }

    //
    // update helpers
    //

    fn update_lightcycle_positions(&mut self) -> &mut Self {
        for lightcycle in self.lightcycles.values_mut() {
            if lightcycle.dead {
                continue;
            };

            lightcycle.position += lightcycle.rotation.as_velocity() * lightcycle.speed;
        }
        self
    }

    fn update_trail_positions(&mut self) -> &mut Self {
        for (id, trail) in self.trails.iter_mut() {
            let latest_point = match self.lightcycles.get(id) {
                Some(lightcycle) => {
                    if lightcycle.dead {
                        continue;
                    };

                    lightcycle.position
                }
                None => {
                    error!(
                        "Failed to update trail position: No lightcycle with id {}",
                        id
                    );
                    continue;
                }
            };

            trail.points.pop();
            trail.points.push(latest_point.clone());
        }
        self
    }

    fn calculate_lightcycle_collisions(&mut self) -> &mut Self {
        'next_lightcycle: for lightcycle in self.lightcycles.values_mut() {
            if lightcycle.dead {
                continue 'next_lightcycle;
            };

            for trail in self.trails.values() {
                for line in trail.points.windows(2) {
                    let start = line[0];
                    let end = line[1];

                    if is_point_on_line_2d(lightcycle.position, (start, end)) {
                        lightcycle.dead = true;
                        continue 'next_lightcycle;
                    }
                }
            }
        }

        self
    }
}

fn is_point_on_line_2d(point: Point2<isize>, line: (Point2<isize>, Point2<isize>)) -> bool {
    let (start, end) = line;

    if start.x == end.x {
        if point.x != start.x {
            return false;
        }

        return is_point_on_line_1d(point.y, (start.y, end.y));
    }

    if start.y == end.y {
        if point.y != start.y {
            return false;
        }

        return is_point_on_line_1d(point.x, (start.x, end.x));
    }

    false
}

fn is_point_on_line_1d(point: isize, line: (isize, isize)) -> bool {
    let (low, high) = if line.0 <= line.1 {
        (line.0, line.1)
    } else {
        (line.1, line.0)
    };

    if point < low || high < point {
        return false;
    }

    true
}
<|endoftext|>


<commit_before>use std::{cell::RefCell, rc::Rc};

use smithay::{
    reexports::{
        wayland_protocols::xdg_shell::server::xdg_toplevel,
        wayland_server::{
            protocol::{
                wl_output,
                wl_surface::{self, WlSurface},
            },
            Display, Global, UserDataMap,
        },
    },
    utils::{Logical, Point, Rectangle, Size, Raw},
    wayland::{
        compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
        output::{self, Mode, PhysicalProperties},
    },
};

// The minimum DPI at which we turn on a scale of 2
const HIDPI_DPI_STEP: f32 = 2.0 * 96.0;
// The minimum screen height at which we turn on a scale of 2
const HIDPI_MIN_HEIGHT: i32 = 1200;
// 1 inch = 25.4 mm
const MM_PER_INCH: f32 = 25.4;

#[derive(Debug)]
pub struct Output {
    name: String,
    output: output::Output,
    global: Option<Global<wl_output::WlOutput>>,
    surfaces: Vec<WlSurface>,
    layer_surfaces: RefCell<Vec<wl_surface::WlSurface>>,
    current_mode: Mode,
    scale: f32,
    output_scale: i32,
    location: Point<i32, Logical>,
    userdata: UserDataMap,
}

// Some manufacturers hardcode the aspect-ratio of the output in the physical size field.
fn phys_size_is_aspect_ratio(size: &Size<i32, Raw>) -> bool {
    (size.w == 1600 && size.h == 900) ||
    (size.w == 1600 && size.h == 1000) ||
    (size.w == 160 && size.h == 90) ||
    (size.w == 160 && size.h == 100) ||
    (size.w == 16 && size.h == 9) ||
    (size.w == 16 && size.h == 10)
}

impl Output {
    pub fn new<N>(
        name: N,
        location: Point<i32, Logical>,
        display: &mut Display,
        physical: PhysicalProperties,
        mode: Mode,
    ) -> Self
    where
        N: AsRef<str>,
    {
        let physical_size = physical.size.clone();
        let (output, global) = output::Output::new(display, name.as_ref().into(), physical, None);

        let (width, height) = mode.size.into();
        let scale = if height < HIDPI_MIN_HEIGHT { 1.0 }
            else if phys_size_is_aspect_ratio(&physical_size) { 1.0 }
            else if physical_size.h == 0 || physical_size.w == 0 { 1.0 }
            else {
                let dpi_x = width as f32 / (physical_size.w as f32 / MM_PER_INCH);
                let dpi_y = height as f32 / (physical_size.h as f32 / MM_PER_INCH);
                slog_scope::debug!("Output DPI: {}x{}", dpi_x, dpi_y);
                    (((dpi_x / HIDPI_DPI_STEP) * 4.0).floor() / 4.0)
                    .min(((dpi_y / HIDPI_DPI_STEP) * 4.0).floor() / 4.0)
            };
        let output_scale = scale.ceil() as i32;

        output.change_current_state(Some(mode), None, Some(output_scale), Some(location));
        output.set_preferred(mode);

        Self {
            name: name.as_ref().to_owned(),
            global: Some(global),
            output,
            location,
            surfaces: Vec::new(),
            layer_surfaces: Default::default(),
            current_mode: mode,
            scale,
            output_scale,
            userdata: Default::default(),
        }
    }

    pub fn userdata(&self) -> &UserDataMap {
        &self.userdata
    }

    pub fn geometry(&self) -> Rectangle<i32, Logical> {
        let loc = self.location();
        let size = self.size();

        Rectangle { loc, size }
    }

    pub fn size(&self) -> Size<i32, Logical> {
        self.current_mode
            .size
            .to_f64()
            .to_logical(self.scale as f64)
            .to_i32_round()
    }

    pub fn location(&self) -> Point<i32, Logical> {
        self.location
    }

    pub fn set_location(&mut self, to: Point<i32, Logical>) {
        self.location = to;
        self.output.change_current_state(None, None, None, Some(to));
    }

    pub fn scale(&self) -> f32 {
        self.scale
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    pub fn current_mode(&self) -> Mode {
        self.current_mode
    }

    pub fn set_mode(&mut self, mode: Mode) {
        self.output.delete_mode(self.current_mode);
        self
            .output
            .change_current_state(Some(mode), None, Some(self.output_scale), None);
        self.output.set_preferred(mode);
        self.current_mode = mode;
    }

    pub fn owns(&self, wl: &wl_output::WlOutput) -> bool {
        self.output.owns(wl)
    }

    /// Add a layer surface to this output
    pub fn add_layer_surface(&self, layer: wl_surface::WlSurface) {
        self.layer_surfaces.borrow_mut().push(layer);
    }

    /// Get all layer surfaces assigned to this output
    pub fn layer_surfaces(&self) -> Vec<wl_surface::WlSurface> {
        self.layer_surfaces.borrow().iter().cloned().collect()
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        self.global.take().unwrap().destroy();
    }
}

/*
pub struct OutputMap {
    display: Rc<RefCell<Display>>,
    outputs: Vec<Output>,
    window_map: Rc<RefCell<crate::state::WindowMap>>,
    logger: slog::Logger,
}

impl OutputMap {
    pub fn new(
        display: Rc<RefCell<Display>>,
        window_map: Rc<RefCell<crate::state::WindowMap>>,
        logger: ::slog::Logger,
    ) -> Self {
        Self {
            display,
            outputs: Vec::new(),
            window_map,
            logger,
        }
    }

    pub fn arrange(&mut self) {
        // First recalculate the outputs location
        let mut output_x = 0;
        for output in self.outputs.iter_mut() {
            let output_x_shift = output_x - output.location.x;

            // If the scale changed we shift all windows on that output
            // so that the location of the window will stay the same on screen
            if output_x_shift != 0 {
                let mut window_map = self.window_map.borrow_mut();

                for surface in output.surfaces.iter() {
                    let toplevel = window_map.find(surface);

                    if let Some(toplevel) = toplevel {
                        let current_location = window_map.location(&toplevel);

                        if let Some(mut location) = current_location {
                            if output.geometry().contains(location) {
                                location.x += output_x_shift;
                                window_map.set_location(&toplevel, location);
                            }
                        }
                    }
                }
            }

            output.location.x = output_x;
            output.location.y = 0;

            output
                .output
                .change_current_state(None, None, None, Some(output.location));

            output_x += output.size().w;
        }

        // Check if any windows are now out of outputs range
        // and move them to the primary output
        let primary_output_location = self.with_primary().map(|o| o.location()).unwrap_or_default();
        let mut window_map = self.window_map.borrow_mut();

        // TODO: This is a bit unfortunate, we save the windows in a temp vector
        // cause we can not call window_map.set_location within the closure.
        let mut windows_to_move = Vec::new();
        window_map.with_windows_from_bottom_to_top(|kind, _, &bbox| {
            let within_outputs = self.outputs.iter().any(|o| o.geometry().overlaps(bbox));

            if !within_outputs {
                windows_to_move.push((kind.to_owned(), primary_output_location));
            }
        });
        for (window, location) in windows_to_move.drain(..) {
            window_map.set_location(&window, location);
        }

        // Update the size and location for maximized and fullscreen windows
        window_map.with_windows_from_bottom_to_top(|kind, location, _| {
            if let crate::window_map::Kind::Xdg(xdg) = kind {
                if let Some(state) = xdg.current_state() {
                    if state.states.contains(xdg_toplevel::State::Maximized)
                        || state.states.contains(xdg_toplevel::State::Fullscreen)
                    {
                        let output_geometry = if let Some(output) = state.fullscreen_output.as_ref() {
                            self.find_by_output(output).map(|o| o.geometry())
                        } else {
                            self.find_by_position(location).map(|o| o.geometry())
                        };

                        if let Some(geometry) = output_geometry {
                            if location != geometry.loc {
                                windows_to_move.push((kind.to_owned(), geometry.loc));
                            }

                            let res = xdg.with_pending_state(|pending_state| {
                                pending_state.size = Some(geometry.size);
                            });

                            if res.is_ok() {
                                xdg.send_configure();
                            }
                        }
                    }
                }
            }
        });
        for (window, location) in windows_to_move.drain(..) {
            window_map.set_location(&window, location);
        }

        for output in self.outputs.iter() {
            window_map.layers.arange_layers(output);
        }
    }

    pub fn is_empty(&self) -> bool {
        self.outputs.is_empty()
    }

    pub fn with_primary(&self) -> Option<&Output> {
        self.outputs.get(0)
    }

    pub fn find_by_layer_surface(&self, surface: &wl_surface::WlSurface) -> Option<&Output> {
        self.find(|o| {
            o.layer_surfaces
                .borrow()
                .iter()
                .any(|s| s.as_ref().equals(surface.as_ref()))
        })
    }

    pub fn find_by_name<N>(&self, name: N) -> Option<&Output>
    where
        N: AsRef<str>,
    {
        self.find(|o| o.name == name.as_ref())
    }

    pub fn find_by_position(&self, position: Point<i32, Logical>) -> Option<&Output> {
        self.find(|o| o.geometry().contains(position))
    }

    pub fn find_by_index(&self, index: usize) -> Option<&Output> {
        self.outputs.get(index)
    }

    pub fn update<F>(&mut self, mode: Option<Mode>, scale: Option<f32>, mut f: F)
    where
        F: FnMut(&Output) -> bool,
    {
        let output = self.outputs.iter_mut().find(|o| f(&**o));

        if let Some(output) = output {
            if let Some(mode) = mode {
                output.output.delete_mode(output.current_mode);
                output
                    .output
                    .change_current_state(Some(mode), None, Some(output.output_scale), None);
                output.output.set_preferred(mode);
                output.current_mode = mode;
            }

            if let Some(scale) = scale {
                // Calculate in which direction the scale changed
                let rescale = output.scale() / scale;

                {
                    // We take the current location of our toplevels and move them
                    // to the same location using the new scale
                    let mut window_map = self.window_map.borrow_mut();
                    for surface in output.surfaces.iter() {
                        let toplevel = window_map.find(surface);

                        if let Some(toplevel) = toplevel {
                            let current_location = window_map.location(&toplevel);

                            if let Some(location) = current_location {
                                let output_geometry = output.geometry();

                                if output_geometry.contains(location) {
                                    let mut toplevel_output_location =
                                        (location - output_geometry.loc).to_f64();
                                    toplevel_output_location.x *= rescale as f64;
                                    toplevel_output_location.y *= rescale as f64;
                                    window_map.set_location(
                                        &toplevel,
                                        output_geometry.loc + toplevel_output_location.to_i32_round(),
                                    );
                                }
                            }
                        }
                    }
                }

                let output_scale = scale.round() as i32;
                output.scale = scale;

                if output.output_scale != output_scale {
                    output.output_scale = output_scale;
                    output.output.change_current_state(
                        Some(output.current_mode),
                        None,
                        Some(output_scale),
                        None,
                    );
                }
            }
        }

        self.arrange();
    }

    pub fn update_by_name<N: AsRef<str>>(&mut self, mode: Option<Mode>, scale: Option<f32>, name: N) {
        self.update(mode, scale, |o| o.name() == name.as_ref())
    }

    pub fn update_scale_by_name<N: AsRef<str>>(&mut self, scale: f32, name: N) {
        self.update_by_name(None, Some(scale), name)
    }

    pub fn update_mode_by_name<N: AsRef<str>>(&mut self, mode: Mode, name: N) {
        self.update_by_name(Some(mode), None, name)
    }

    pub fn refresh(&mut self) {
        // Clean-up dead surfaces
        self.outputs.iter_mut().for_each(|o| {
            o.surfaces.retain(|s| s.as_ref().is_alive());
            o.layer_surfaces.borrow_mut().retain(|s| s.as_ref().is_alive());
        });

        let window_map = self.window_map.clone();

        window_map
            .borrow()
            .with_windows_from_bottom_to_top(|kind, location, &bbox| {
                for output in self.outputs.iter_mut() {
                    // Check if the bounding box of the toplevel intersects with
                    // the output, if not no surface in the tree can intersect with
                    // the output.
                    if !output.geometry().overlaps(bbox) {
                        if let Some(surface) = kind.get_surface() {
                            with_surface_tree_downward(
                                surface,
                                (),
                                |_, _, _| TraversalAction::DoChildren(()),
                                |wl_surface, _, _| {
                                    if output.surfaces.contains(wl_surface) {
                                        output.output.leave(wl_surface);
                                        output.surfaces.retain(|s| s != wl_surface);
                                    }
                                },
                                |_, _, _| true,
                            )
                        }
                        continue;
                    }

                    if let Some(surface) = kind.get_surface() {
                        with_surface_tree_downward(
                            surface,
                            location,
                            |_, states, location| {
                                let mut location = *location;
                                let data = states.data_map.get::<RefCell<SurfaceData>>();

                                if data.is_some() {
                                    if states.role == Some("subsurface") {
                                        let current = states.cached_state.current::<SubsurfaceCachedState>();
                                        location += current.location;
                                    }

                                    TraversalAction::DoChildren(location)
                                } else {
                                    // If the parent surface is unmapped, then the child surfaces are hidden as
                                    // well, no need to consider them here.
                                    TraversalAction::SkipChildren
                                }
                            },
                            |wl_surface, states, &loc| {
                                let data = states.data_map.get::<RefCell<SurfaceData>>();

                                if let Some(size) = data.and_then(|d| d.borrow().size()) {
                                    let surface_rectangle = Rectangle { loc, size };

                                    if output.geometry().overlaps(surface_rectangle) {
                                        // We found a matching output, check if we already sent enter
                                        if !output.surfaces.contains(wl_surface) {
                                            output.output.enter(wl_surface);
                                            output.surfaces.push(wl_surface.clone());
                                        }
                                    } else {
                                        // Surface does not match output, if we sent enter earlier
                                        // we should now send leave
                                        if output.surfaces.contains(wl_surface) {
                                            output.output.leave(wl_surface);
                                            output.surfaces.retain(|s| s != wl_surface);
                                        }
                                    }
                                } else {
                                    // Maybe the the surface got unmapped, send leave on output
                                    if output.surfaces.contains(wl_surface) {
                                        output.output.leave(wl_surface);
                                        output.surfaces.retain(|s| s != wl_surface);
                                    }
                                }
                            },
                            |_, _, _| true,
                        )
                    }
                }
            });
    }
}
*/<commit_msg>output: remove unnecessary output_map code<commit_after>use std::{cell::RefCell, rc::Rc};

use smithay::{
    reexports::{
        wayland_protocols::xdg_shell::server::xdg_toplevel,
        wayland_server::{
            protocol::{
                wl_output,
                wl_surface::{self, WlSurface},
            },
            Display, Global, UserDataMap,
        },
    },
    utils::{Logical, Point, Rectangle, Size, Raw},
    wayland::{
        compositor::{with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
        output::{self, Mode, PhysicalProperties},
    },
};

// The minimum DPI at which we turn on a scale of 2
const HIDPI_DPI_STEP: f32 = 2.0 * 96.0;
// The minimum screen height at which we turn on a scale of 2
const HIDPI_MIN_HEIGHT: i32 = 1200;
// 1 inch = 25.4 mm
const MM_PER_INCH: f32 = 25.4;

#[derive(Debug)]
pub struct Output {
    name: String,
    output: output::Output,
    global: Option<Global<wl_output::WlOutput>>,
    surfaces: Vec<WlSurface>,
    layer_surfaces: RefCell<Vec<wl_surface::WlSurface>>,
    current_mode: Mode,
    scale: f32,
    output_scale: i32,
    location: Point<i32, Logical>,
    userdata: UserDataMap,
}

// Some manufacturers hardcode the aspect-ratio of the output in the physical size field.
fn phys_size_is_aspect_ratio(size: &Size<i32, Raw>) -> bool {
    (size.w == 1600 && size.h == 900) ||
    (size.w == 1600 && size.h == 1000) ||
    (size.w == 160 && size.h == 90) ||
    (size.w == 160 && size.h == 100) ||
    (size.w == 16 && size.h == 9) ||
    (size.w == 16 && size.h == 10)
}

impl Output {
    pub fn new<N>(
        name: N,
        location: Point<i32, Logical>,
        display: &mut Display,
        physical: PhysicalProperties,
        mode: Mode,
    ) -> Self
    where
        N: AsRef<str>,
    {
        let physical_size = physical.size.clone();
        let (output, global) = output::Output::new(display, name.as_ref().into(), physical, None);

        let (width, height) = mode.size.into();
        let scale = if height < HIDPI_MIN_HEIGHT { 1.0 }
            else if phys_size_is_aspect_ratio(&physical_size) { 1.0 }
            else if physical_size.h == 0 || physical_size.w == 0 { 1.0 }
            else {
                let dpi_x = width as f32 / (physical_size.w as f32 / MM_PER_INCH);
                let dpi_y = height as f32 / (physical_size.h as f32 / MM_PER_INCH);
                slog_scope::debug!("Output DPI: {}x{}", dpi_x, dpi_y);
                    (((dpi_x / HIDPI_DPI_STEP) * 4.0).floor() / 4.0)
                    .min(((dpi_y / HIDPI_DPI_STEP) * 4.0).floor() / 4.0)
            };
        let output_scale = scale.ceil() as i32;

        output.change_current_state(Some(mode), None, Some(output_scale), Some(location));
        output.set_preferred(mode);

        Self {
            name: name.as_ref().to_owned(),
            global: Some(global),
            output,
            location,
            surfaces: Vec::new(),
            layer_surfaces: Default::default(),
            current_mode: mode,
            scale,
            output_scale,
            userdata: Default::default(),
        }
    }

    pub fn userdata(&self) -> &UserDataMap {
        &self.userdata
    }

    pub fn geometry(&self) -> Rectangle<i32, Logical> {
        let loc = self.location();
        let size = self.size();

        Rectangle { loc, size }
    }

    pub fn size(&self) -> Size<i32, Logical> {
        self.current_mode
            .size
            .to_f64()
            .to_logical(self.scale as f64)
            .to_i32_round()
    }

    pub fn location(&self) -> Point<i32, Logical> {
        self.location
    }

    pub fn set_location(&mut self, to: Point<i32, Logical>) {
        self.location = to;
        self.output.change_current_state(None, None, None, Some(to));
    }

    pub fn scale(&self) -> f32 {
        self.scale
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    pub fn current_mode(&self) -> Mode {
        self.current_mode
    }

    pub fn set_mode(&mut self, mode: Mode) {
        self.output.delete_mode(self.current_mode);
        self
            .output
            .change_current_state(Some(mode), None, Some(self.output_scale), None);
        self.output.set_preferred(mode);
        self.current_mode = mode;
    }

    pub fn owns(&self, wl: &wl_output::WlOutput) -> bool {
        self.output.owns(wl)
    }

    /// Add a layer surface to this output
    pub fn add_layer_surface(&self, layer: wl_surface::WlSurface) {
        self.layer_surfaces.borrow_mut().push(layer);
    }

    /// Get all layer surfaces assigned to this output
    pub fn layer_surfaces(&self) -> Vec<wl_surface::WlSurface> {
        self.layer_surfaces.borrow().iter().cloned().collect()
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        self.global.take().unwrap().destroy();
    }
}
<|endoftext|>