<commit_before>//! Contains types related to vertex data, which are used for [`VertexBuffers`]
//! (../vertex_buffer/struct.VertexBuffer.html).

use std::mem;
use std::slice;
use types::DataType;

/// A type that has vertex data.
///
/// # Safety
/// Implementors must properly implement the [`visit_attributes`]
/// (trait.VertexData.html#tymethod.visit_attributes) method. Implementing
/// this method incorrectly will lead to memory unsafety in some safe
/// API's in glitter.
///
/// # Example
/// ```
/// #[macro_use] extern crate glitter;
/// use glitter::prelude::*;
///
/// #[derive(Clone, Copy)] // `VertexData` types must implement `Copy`
/// #[repr(C)] // Use a predictable data layout (for our field offsets)
/// struct MyVertex {
///     position: [f32; 3],
///     color: [f32; 3]
/// }
///
/// // Manually implement the `VertexData` trait
/// unsafe impl glitter::VertexData for MyVertex {
///     fn visit_attributes<F>(mut f: F)
///         where F: FnMut(glitter::VertexAttribute)
///     {
///         use std::mem;
///         use glitter::{VertexAttribute, VertexAttributeType, VertexDatum};
///
///         // The vertex attribute type for an `[f32; 3]`, or `vec3`
///         let vec3 = <[f32; 3] as VertexDatum>::attrib_type();
///
///         // let vec3 = VertexAttributeType {
///         //     data: glitter::FLOAT,
///         //     components: 3,
///         //     normalize: false
///         // };
///
///         let stride = mem::size_of::<MyVertex>();
///         let position_offset = 0;
///         let position_size = mem::size_of::<[f32; 3]>();
///         let color_offset = position_offset + position_size;
///
///         let position = VertexAttribute {
///             ty: vec3.clone(),
///             name: "position".into(),
///             offset: position_offset,
///             stride: stride
///         };
///         let color = VertexAttribute {
///             ty: vec3,
///             name: "color".into(),
///             offset: color_offset,
///             stride: stride
///         };
///
///         // Call the function with the "position" and "color" attributes
///         f(position);
///         f(color);
///     }
/// }
/// # fn main() {
/// #     // TODO: Add `VertexData` implementation test
/// # }
/// ```
///
/// # See also
/// [`impl_vertx_data!`](../macro.impl_vertex_data!.html): A macro that
/// automatically implements `VertexData` for structs.
pub unsafe trait VertexData: Copy {
    /// Call the given function with each attribute that this
    /// vertex data is composed of.
    ///
    /// # Safety
    /// The function must only be called once per attribute, and
    /// the provided values of the [`VertexAttribute`]
    /// (struct.VertexAttribute.html) passed to the function *must*
    /// be correct. See the [`VertexAttribute`](struct.VertexAttribute.html)
    /// docs for more details on what each field means.
    fn visit_attributes<F>(&f: F) where F: FnMut(VertexAttribute);
}

/// A single value that can be treated as a part of a vertex. Implementors
/// should map to a GLSL primitive that can be used as a vertex attribute.
/// For example, `[f32; 2]` corresponds to `vec2` in memory layout
/// and structure.
///
/// # Safety
/// This type will be transmuted to a slice according to the value returned
/// by the [`attrib_type`](trait.VertexDatum.html#tymethod.attrib_type) method.
/// Implementing this method incorrectly will lead to memory unsafety.
pub unsafe trait VertexDatum: Copy {
    /// Return the data type this datum corresponds to.
    ///
    /// # Safety
    /// An instance of this type must match the size and memory layout
    /// specified by the returned [`VertexAttributeType`]
    /// (struct.VertexAttributeType.html).
    fn attrib_type() -> VertexAttributeType;
}

/// A single, basic value that can be composed to make a [`VertexDatum`]
/// (trait.VertexDatum.html). Scalar values are an example of a
/// `VertexPrimitive`.
///
/// # Safety
/// This type will be transmuted to a slice according to the value returned
/// by the [`data_type`](trait.VertexPrimitive.html#tymethod.data_type) method.
/// Implementing this method incorrectly will lead to memory unsafety.
pub unsafe trait VertexPrimitive: Copy {
    /// Return the data type this primitive corresponds to.
    ///
    /// # Safety
    /// An instance of this type must be the size of the [`DataType`]
    /// (../types/enum.DataType.html) returned by this function.
    fn data_type() -> DataType;
}

/// Specifies the type, name, and memory layout of a vertex attribute.
/// Generally, a "vertex attribute" corresponds to a field in a [`VertexData`]
/// (trait.VertexData.html) struct.
#[derive(Clone)]
pub struct VertexAttribute {
    /// The type of the vertex attribute. This also specifies the number
    /// of bytes that make up a vertex attribute.
    pub ty: VertexAttributeType,

    /// The name of the vertex attribute. This value is used
    /// as the `$field_name` when binding vertex attribute
    /// pointers with the [`attrib_pointers!`](macro.attrib_pointers!.html)
    /// macro.
    pub name: String,

    /// The number of bytes to "move" from the start of the vertex data
    /// to reach this vertex attribute.
    pub offset: usize,

    /// The number of bytes between consecutive vertex attributes. 0 indicates
    /// that the vertex data is tightly packed.
    pub stride: usize
}

/// Used to specify type of a vertex attribute. The size of the vertex
/// attribute is `size_of(data) * components`.
#[derive(Clone)]
pub struct VertexAttributeType {
    /// The type of data that makes up this vertex attribute.
    pub data: DataType,

    /// The number of `data` components that make up this vertex attribute.
    pub components: i8,

    /// If the `data` type is fixed-point data, indicates if the data
    /// should be normalized when being accessed. `true` indicates
    /// that the vertex attribute **should** be normalized when being
    /// accessed.
    pub normalize: bool
}

unsafe impl VertexPrimitive for i8 {
    fn data_type() -> DataType { DataType::Byte }
}

unsafe impl VertexPrimitive for u8 {
    fn data_type() -> DataType { DataType::UnsignedByte }
}

unsafe impl VertexPrimitive for i16 {
    fn data_type() -> DataType { DataType::Short }
}

unsafe impl VertexPrimitive for u16 {
    fn data_type() -> DataType { DataType::UnsignedShort }
}

unsafe impl VertexPrimitive for f32 {
    fn data_type() -> DataType { DataType::Float }
}

unsafe impl<T: VertexPrimitive> VertexDatum for T {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 1,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 1] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 1,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 2] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 2,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 3] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 3,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 4] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 4,
            normalize: false
        }
    }
}

/// Indicates that a type can be coerced to a `u8` slice that can
/// then be treated as a stream of vertex data.
pub trait VertexBytes {
    /// Create a byte slice of vertex data from `self`.
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(mem::transmute(self), mem::size_of::<Self>())
        }
    }
}

impl<T> VertexBytes for [T] where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        let size = mem::size_of::<T>() * self.len();
        unsafe {
            slice::from_raw_parts(mem::transmute(&self[0]), size)
        }
    }
}

// TODO: Use a proper compiler intrinsic/macro (when available)
// see: https://github.com/rust-lang/rust/issues/24111
/// Compute the offset of a field within a struct type.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate glitter;
/// # fn main() {
/// #[repr(C, packed)]
/// struct MyStruct {
///     foo: u32,
///     bar: u32,
///     baz: u32
/// }
///
/// assert_eq!(offset_of!(MyStruct, foo), 0);
/// assert_eq!(offset_of!(MyStruct, bar), 4);
/// assert_eq!(offset_of!(MyStruct, baz), 8);
/// # }
/// ```
#[macro_export]
macro_rules! offset_of {
    ($T:ty, $field:ident) => {
        unsafe {
            use std::mem::{uninitialized, transmute};

            let obj : $T = uninitialized();
            let obj_ptr : *const u8 = transmute(&obj);
            let member_ptr : *const u8 = transmute(&obj.$field);

            (member_ptr as usize) - (obj_ptr as usize)
        }
    }
}

/// Implement the [`VertexData`](vertex_data/trait.VertexData.html) trait
/// for a struct. Each field of the struct must that is part of the
/// `VertexData` implementation must be a type that implements [`VertexDatum`]
/// (vertex_data/trait.VertexDatum.html).
///
/// # Examples
///
/// ```
/// #[macro_use] extern crate glitter;
///
/// # fn main() {
/// // A type must implement `Copy` to implement `VertexData`
/// #[derive(Clone, Copy)]
/// struct MyVertex {
///     position: [f32; 3],
///     color: [f32; 3]
/// }
///
/// // Implement `VertexData`, using the "position" and "color" fields
/// // as vertex attributes.
/// impl_vertex_data!(MyVertex, position, color);
/// # }
/// ```
#[macro_export]
macro_rules! impl_vertex_data {
    ($name:ty, $($field_name:ident),*) => {
        unsafe impl $crate::VertexData for $name {
            fn visit_attributes<F>(mut f: F)
                where F: FnMut($crate::VertexAttribute)
            {
                // TODO: A better way of iterating over field types
                let _data: $name = unsafe { ::std::mem::uninitialized() };
                fn get_attribute_type<T: $crate::VertexDatum>(_: &T)
                    -> $crate::VertexAttributeType
                {
                    T::attrib_type()
                }
                $(
                    f($crate::VertexAttribute {
                        ty: get_attribute_type(&_data.$field_name),
                        name: stringify!($field_name).into(),
                        stride: ::std::mem::size_of::<$name>(),
                        offset: offset_of!($name, $field_name)
                    });
                )*
            }
        }
    };
}
<commit_msg>Call `mem::forget` instead of dropping uninitialized data in `offset_of!`<commit_after>//! Contains types related to vertex data, which are used for [`VertexBuffers`]
//! (../vertex_buffer/struct.VertexBuffer.html).

use std::mem;
use std::slice;
use types::DataType;

/// A type that has vertex data.
///
/// # Safety
/// Implementors must properly implement the [`visit_attributes`]
/// (trait.VertexData.html#tymethod.visit_attributes) method. Implementing
/// this method incorrectly will lead to memory unsafety in some safe
/// API's in glitter.
///
/// # Example
/// ```
/// #[macro_use] extern crate glitter;
/// use glitter::prelude::*;
///
/// #[derive(Clone, Copy)] // `VertexData` types must implement `Copy`
/// #[repr(C)] // Use a predictable data layout (for our field offsets)
/// struct MyVertex {
///     position: [f32; 3],
///     color: [f32; 3]
/// }
///
/// // Manually implement the `VertexData` trait
/// unsafe impl glitter::VertexData for MyVertex {
///     fn visit_attributes<F>(mut f: F)
///         where F: FnMut(glitter::VertexAttribute)
///     {
///         use std::mem;
///         use glitter::{VertexAttribute, VertexAttributeType, VertexDatum};
///
///         // The vertex attribute type for an `[f32; 3]`, or `vec3`
///         let vec3 = <[f32; 3] as VertexDatum>::attrib_type();
///
///         // let vec3 = VertexAttributeType {
///         //     data: glitter::FLOAT,
///         //     components: 3,
///         //     normalize: false
///         // };
///
///         let stride = mem::size_of::<MyVertex>();
///         let position_offset = 0;
///         let position_size = mem::size_of::<[f32; 3]>();
///         let color_offset = position_offset + position_size;
///
///         let position = VertexAttribute {
///             ty: vec3.clone(),
///             name: "position".into(),
///             offset: position_offset,
///             stride: stride
///         };
///         let color = VertexAttribute {
///             ty: vec3,
///             name: "color".into(),
///             offset: color_offset,
///             stride: stride
///         };
///
///         // Call the function with the "position" and "color" attributes
///         f(position);
///         f(color);
///     }
/// }
/// # fn main() {
/// #     // TODO: Add `VertexData` implementation test
/// # }
/// ```
///
/// # See also
/// [`impl_vertx_data!`](../macro.impl_vertex_data!.html): A macro that
/// automatically implements `VertexData` for structs.
pub unsafe trait VertexData: Copy {
    /// Call the given function with each attribute that this
    /// vertex data is composed of.
    ///
    /// # Safety
    /// The function must only be called once per attribute, and
    /// the provided values of the [`VertexAttribute`]
    /// (struct.VertexAttribute.html) passed to the function *must*
    /// be correct. See the [`VertexAttribute`](struct.VertexAttribute.html)
    /// docs for more details on what each field means.
    fn visit_attributes<F>(&f: F) where F: FnMut(VertexAttribute);
}

/// A single value that can be treated as a part of a vertex. Implementors
/// should map to a GLSL primitive that can be used as a vertex attribute.
/// For example, `[f32; 2]` corresponds to `vec2` in memory layout
/// and structure.
///
/// # Safety
/// This type will be transmuted to a slice according to the value returned
/// by the [`attrib_type`](trait.VertexDatum.html#tymethod.attrib_type) method.
/// Implementing this method incorrectly will lead to memory unsafety.
pub unsafe trait VertexDatum: Copy {
    /// Return the data type this datum corresponds to.
    ///
    /// # Safety
    /// An instance of this type must match the size and memory layout
    /// specified by the returned [`VertexAttributeType`]
    /// (struct.VertexAttributeType.html).
    fn attrib_type() -> VertexAttributeType;
}

/// A single, basic value that can be composed to make a [`VertexDatum`]
/// (trait.VertexDatum.html). Scalar values are an example of a
/// `VertexPrimitive`.
///
/// # Safety
/// This type will be transmuted to a slice according to the value returned
/// by the [`data_type`](trait.VertexPrimitive.html#tymethod.data_type) method.
/// Implementing this method incorrectly will lead to memory unsafety.
pub unsafe trait VertexPrimitive: Copy {
    /// Return the data type this primitive corresponds to.
    ///
    /// # Safety
    /// An instance of this type must be the size of the [`DataType`]
    /// (../types/enum.DataType.html) returned by this function.
    fn data_type() -> DataType;
}

/// Specifies the type, name, and memory layout of a vertex attribute.
/// Generally, a "vertex attribute" corresponds to a field in a [`VertexData`]
/// (trait.VertexData.html) struct.
#[derive(Clone)]
pub struct VertexAttribute {
    /// The type of the vertex attribute. This also specifies the number
    /// of bytes that make up a vertex attribute.
    pub ty: VertexAttributeType,

    /// The name of the vertex attribute. This value is used
    /// as the `$field_name` when binding vertex attribute
    /// pointers with the [`attrib_pointers!`](macro.attrib_pointers!.html)
    /// macro.
    pub name: String,

    /// The number of bytes to "move" from the start of the vertex data
    /// to reach this vertex attribute.
    pub offset: usize,

    /// The number of bytes between consecutive vertex attributes. 0 indicates
    /// that the vertex data is tightly packed.
    pub stride: usize
}

/// Used to specify type of a vertex attribute. The size of the vertex
/// attribute is `size_of(data) * components`.
#[derive(Clone)]
pub struct VertexAttributeType {
    /// The type of data that makes up this vertex attribute.
    pub data: DataType,

    /// The number of `data` components that make up this vertex attribute.
    pub components: i8,

    /// If the `data` type is fixed-point data, indicates if the data
    /// should be normalized when being accessed. `true` indicates
    /// that the vertex attribute **should** be normalized when being
    /// accessed.
    pub normalize: bool
}

unsafe impl VertexPrimitive for i8 {
    fn data_type() -> DataType { DataType::Byte }
}

unsafe impl VertexPrimitive for u8 {
    fn data_type() -> DataType { DataType::UnsignedByte }
}

unsafe impl VertexPrimitive for i16 {
    fn data_type() -> DataType { DataType::Short }
}

unsafe impl VertexPrimitive for u16 {
    fn data_type() -> DataType { DataType::UnsignedShort }
}

unsafe impl VertexPrimitive for f32 {
    fn data_type() -> DataType { DataType::Float }
}

unsafe impl<T: VertexPrimitive> VertexDatum for T {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 1,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 1] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 1,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 2] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 2,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 3] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 3,
            normalize: false
        }
    }
}

unsafe impl<T: VertexPrimitive> VertexDatum for [T; 4] {
    fn attrib_type() -> VertexAttributeType {
        VertexAttributeType {
            data: T::data_type(),
            components: 4,
            normalize: false
        }
    }
}

/// Indicates that a type can be coerced to a `u8` slice that can
/// then be treated as a stream of vertex data.
pub trait VertexBytes {
    /// Create a byte slice of vertex data from `self`.
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(mem::transmute(self), mem::size_of::<Self>())
        }
    }
}

impl<T> VertexBytes for [T] where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        let size = mem::size_of::<T>() * self.len();
        unsafe {
            slice::from_raw_parts(mem::transmute(&self[0]), size)
        }
    }
}

// TODO: Use a proper compiler intrinsic/macro (when available)
// see: https://github.com/rust-lang/rust/issues/24111
/// Compute the offset of a field within a struct type.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate glitter;
/// # fn main() {
/// #[repr(C, packed)]
/// struct MyStruct {
///     foo: u32,
///     bar: u32,
///     baz: u32
/// }
///
/// assert_eq!(offset_of!(MyStruct, foo), 0);
/// assert_eq!(offset_of!(MyStruct, bar), 4);
/// assert_eq!(offset_of!(MyStruct, baz), 8);
/// # }
/// ```
#[macro_export]
macro_rules! offset_of {
    ($T:ty, $field:ident) => {
        unsafe {
            let obj: $T = ::std::mem::uninitialized();
            let obj_ptr: *const u8 = ::std::mem::transmute(&obj);
            let member_ptr: *const u8 = ::std::mem::transmute(&obj.$field);

            ::std::mem::forget(obj);

            (member_ptr as usize) - (obj_ptr as usize)
        }
    }
}

/// Implement the [`VertexData`](vertex_data/trait.VertexData.html) trait
/// for a struct. Each field of the struct must that is part of the
/// `VertexData` implementation must be a type that implements [`VertexDatum`]
/// (vertex_data/trait.VertexDatum.html).
///
/// # Examples
///
/// ```
/// #[macro_use] extern crate glitter;
///
/// # fn main() {
/// // A type must implement `Copy` to implement `VertexData`
/// #[derive(Clone, Copy)]
/// struct MyVertex {
///     position: [f32; 3],
///     color: [f32; 3]
/// }
///
/// // Implement `VertexData`, using the "position" and "color" fields
/// // as vertex attributes.
/// impl_vertex_data!(MyVertex, position, color);
/// # }
/// ```
#[macro_export]
macro_rules! impl_vertex_data {
    ($name:ty, $($field_name:ident),*) => {
        unsafe impl $crate::VertexData for $name {
            fn visit_attributes<F>(mut f: F)
                where F: FnMut($crate::VertexAttribute)
            {
                // TODO: A better way of iterating over field types
                let _data: $name = unsafe { ::std::mem::uninitialized() };
                fn get_attribute_type<T: $crate::VertexDatum>(_: &T)
                    -> $crate::VertexAttributeType
                {
                    T::attrib_type()
                }
                $(
                    f($crate::VertexAttribute {
                        ty: get_attribute_type(&_data.$field_name),
                        name: stringify!($field_name).into(),
                        stride: ::std::mem::size_of::<$name>(),
                        offset: offset_of!($name, $field_name)
                    });
                )*
            }
        }
    };
}
<|endoftext|>


<commit_before>extern crate test;

use test::Bencher;

use std::fmt::{Show, Formatter, Result};
use std::iter::AdditiveIterator;

enum Node<T> {
  Cons(T, Box<Node<T>>),
  Nil
}

impl<T> Node<T> {
  fn new() -> Node<T> {
    Nil
  }

  fn prepend(self, elem: T) -> Node<T> {
    Cons(elem, box self)
  }

  fn len(&self) -> uint {
    match *self {
      Cons(_, ref tail) => tail.len() + 1,
      Nil => 0
    }
  }
}

impl<T: Show> Show for Node<T> {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Cons(ref head, ref tail) => {
        write!(f, "{}, [ ] -> {}", head, tail)
      },
      Nil => {
        write!(f, "Nil")
      },
    }
  }
}

impl<T: PartialEq> PartialEq for Node<T> {
  fn eq(&self, ys: &Node<T>) -> bool {
    match (self, ys) {
      (&Nil, &Nil) => true,
      (&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
        if x == y => next_xs == next_ys,
      _ => false
    }
  }
}
// Simple hashed wheel timer with bounded interval
// See http://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf
struct WheelTimer<T> {
  maxInterval: uint,
  currentTick: uint,

  ring: Vec<Node<T>>
}

impl<T> WheelTimer<T> {

  // Returns the number of items currently scheduled
  fn size(&self) -> uint {
    return self.ring.iter().map(|node| node.len()).sum()
  }

  // Creates a new timer with the specified max interval
  fn new(maxInterval: uint) -> WheelTimer<T> {
    // Initialize the ring with Nil values
    let mut ring = Vec::with_capacity(maxInterval);
    for _ in range(0u, maxInterval) {
      ring.push(Nil)
    }

    return WheelTimer{
      maxInterval: maxInterval,
      currentTick: 0,
      ring: ring
    }
  }

  // Schedules a new value, available after `ticks`
  fn schedule(&mut self, ticks: uint, value: T) {
    // Compute the scheduled position in the wheel
    let index = (self.currentTick + ticks) % self.maxInterval;

    // Get the current node at `index` in the wheel
    let node = std::mem::replace(self.ring.get_mut(index), Nil);

    // Set the position in the wheel with the appended node
    *self.ring.get_mut(index) = node.prepend(value);
  }

  // Tick the timer, returning the list of nodes at the spot
  fn tick(&mut self) -> Node<T> {
    // Get the node at the current tick in the wheel
    let node = std::mem::replace(self.ring.get_mut(self.currentTick), Nil);

    // Increment the timer
    self.currentTick = (self.currentTick + 1) % self.maxInterval;

    // Return the node that was in that spot
    return node
  }
}

fn main() {
  // LinkedList example
  // Create an empty linked list
  let mut list = Node::<uint>::new();

  // Append some elements
  list = list.prepend(1);
  list = list.prepend(2);
  list = list.prepend(3);

  // Show the final state of the list
  println!("linked list has length: {}", list.len());
  println!("{}", list);

  // WheelTimer example
  // Create a new timer
  let mut timer = WheelTimer::<uint>::new(3);

  // Schedule some things
  timer.schedule(1, 1);
  timer.schedule(2, 2);
  timer.schedule(3, 3);

  // Print the timer size
  println!("size: {}", timer.size());

  // Tick! Tick! Tick!
  println!("{}", timer.tick());
  println!("{}", timer.tick());
  println!("{}", timer.tick());
}

#[test]
fn wheel_timer_new_test() {
  let timer = WheelTimer::<uint>::new(3);
  assert!(timer.maxInterval == 3);
  assert!(timer.ring.capacity() == 3);
  assert!(timer.ring.len() == 3);
}

#[test]
fn wheel_timer_schedule_test() {
  let mut timer = WheelTimer::<&'static str>::new(10);
  timer.schedule(3, "tick");

  timer.tick();
  timer.tick();
  timer.tick();

  let node = timer.tick();
  assert!(node != Nil);

  let val = match node {
    Cons(val, _) => val,
    Nil => ""
  };
  assert!(val == "tick");
}

#[test]
fn wheel_timer_tick_test() {
  let mut timer = WheelTimer::<uint>::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  for i in range(0, 10) {
    let node = timer.tick();
    assert!(node != Nil);

    let val = match node {
      Cons(val, _) => val,
      Nil => -1
    };
    assert!(val == i);
  }
}

#[bench]
fn bench_wheel_timer_drain(b: &mut Bencher) {
  let maxInterval = 20;
  let mut timer = WheelTimer::<uint>::new(maxInterval);

  b.iter(|| {
    // Fill
    for j in range(0u, 100u) {
      timer.schedule(j%maxInterval, j%maxInterval);
    }

    // Drain
    for _ in range(0u, 100u) {
      timer.tick();
    }
  });
}

#[bench]
fn bench_wheel_timer_fill(b: &mut Bencher) {
  let maxInterval = 20;
  let mut timer = WheelTimer::<uint>::new(maxInterval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%maxInterval, i%maxInterval);
    i = i + 1;
  });
}

#[bench]
fn bench_wheel_timer_fast(b: &mut Bencher) {
  let maxInterval = 2;
  let mut timer = WheelTimer::<uint>::new(maxInterval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%maxInterval, i%maxInterval);
    timer.tick();
    i = i + 1;
  });
}
<commit_msg>Cleaning up the code a little and adding Iterator impl<commit_after>extern crate test;

use test::Bencher;

use std::mem;
use std::fmt::{Show, Formatter, Result};
use std::iter::AdditiveIterator;

enum Node<T> {
  Cons(T, Box<Node<T>>),
  Nil
}

impl<T> Node<T> {
  fn prepend(self, elem: T) -> Node<T> {
    Cons(elem, box self)
  }

  fn len(&self) -> uint {
    match *self {
      Cons(_, ref tail) => tail.len() + 1,
      Nil => 0
    }
  }
}

impl<T: Show> Show for Node<T> {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Cons(ref head, ref tail) => {
        write!(f, "{}, [ ] -> {}", head, tail)
      },
      Nil => {
        write!(f, "Nil")
      },
    }
  }
}

impl<T: PartialEq> PartialEq for Node<T> {
  fn eq(&self, ys: &Node<T>) -> bool {
    match (self, ys) {
      (&Nil, &Nil) => true,
      (&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
        if x == y => next_xs == next_ys,
      _ => false
    }
  }
}

// Simple hashed wheel timer with bounded interval
// See http://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf
struct WheelTimer<T> {
  maxInterval: uint,
  currentTick: uint,

  ring: Vec<Node<T>>
}

impl<T> Iterator<Node<T>> for WheelTimer<T> {
  fn next(&mut self) -> Option<Node<T>> {
    let ticked = self.tick();
    return match ticked {
      Cons(_, _) => Some(ticked),
      Nil => None
    };
  }
}

impl<T> WheelTimer<T> {

  // Creates a new timer with the specified max interval
  fn new(maxInterval: uint) -> WheelTimer<T> {
    // Initialize the ring with Nil values
    let mut ring = Vec::with_capacity(maxInterval);
    for _ in range(0u, maxInterval) {
      ring.push(Nil)
    }

    return WheelTimer{
      maxInterval: maxInterval,
      currentTick: 0,
      ring: ring
    }
  }

  // Returns the number of items currently scheduled
  fn size(&self) -> uint {
    return self.ring.iter().map(|node| node.len()).sum()
  }

  // Schedules a new value, available after `ticks`
  fn schedule(&mut self, ticks: uint, value: T) {
    // Compute the scheduled position in the wheel
    let index = (self.currentTick + ticks) % self.maxInterval;

    // Get the current node at `index` in the wheel
    let node = mem::replace(self.ring.get_mut(index), Nil);

    // Set the position in the wheel with the appended node
    *self.ring.get_mut(index) = node.prepend(value);
  }

  // Tick the timer, returning the list of nodes at the spot
  fn tick(&mut self) -> Node<T> {
    // Get the node at the current tick in the wheel
    let node = mem::replace(self.ring.get_mut(self.currentTick), Nil);

    // Increment the timer
    self.currentTick = (self.currentTick + 1) % self.maxInterval;

    // Return the node that was in that spot
    return node
  }
}

#[test]
fn wheel_timer_new_test() {
  let timer = WheelTimer::<uint>::new(3);
  assert!(timer.maxInterval == 3);
  assert!(timer.ring.capacity() == 3);
  assert!(timer.ring.len() == 3);
}

#[test]
fn wheel_timer_schedule_test() {
  let mut timer = WheelTimer::<&'static str>::new(10);
  timer.schedule(3, "tick");

  timer.tick();
  timer.tick();
  timer.tick();

  let node = timer.tick();
  assert!(node != Nil);

  let val = match node {
    Cons(val, _) => val,
    Nil => ""
  };
  assert!(val == "tick");
}

#[test]
fn wheel_timer_tick_test() {
  let mut timer = WheelTimer::<uint>::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  for i in range(0, 10) {
    let node = timer.tick();
    assert!(node != Nil);

    let val = match node {
      Cons(val, _) => val,
      Nil => -1
    };
    assert!(val == i);
  }
}

#[test]
fn wheel_timer_size_test() {
  let mut timer = WheelTimer::<uint>::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  assert!(timer.size() == 10);

  for _ in timer {
  }

  assert!(timer.size() == 0);
}

#[bench]
fn bench_wheel_timer_drain(b: &mut Bencher) {
  let maxInterval = 20;
  let mut timer = WheelTimer::<uint>::new(maxInterval);

  b.iter(|| {
    // Fill
    for j in range(0u, 100u) {
      timer.schedule(j%maxInterval, j%maxInterval);
    }

    // Drain
    for k in timer {
      continue;
    }
  });
}

#[bench]
fn bench_wheel_timer_fill(b: &mut Bencher) {
  let maxInterval = 20;
  let mut timer = WheelTimer::<uint>::new(maxInterval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%maxInterval, i%maxInterval);
    i = i + 1;
  });
}

#[bench]
fn bench_wheel_timer_fast(b: &mut Bencher) {
  let maxInterval = 2;
  let mut timer = WheelTimer::<uint>::new(maxInterval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%maxInterval, i%maxInterval);
    timer.tick();
    i = i + 1;
  });
}
<|endoftext|>


<commit_before>/// For types which have adjacent values.
pub trait AdjacentBound: Ord {
    /// Determines whether `self` and `other` are adjacent.
    fn is_adjacent(&self, other: &Self) -> bool {
        self.is_immediately_before(other) || self.is_immediately_after(other)
    }

    /// Determines whether `self` is immediately before `other`.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert!(5u32.is_immediately_before(&6));
    /// assert_eq!(5u32.is_immediately_before(&7), false);
    /// ```
    fn is_immediately_before(&self, other: &Self) -> bool;

    /// Determines whether `self` is immediately after `other`.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert!(6u32.is_immediately_after(&5));
    /// assert_eq!(7u32.is_immediately_after(&5), false);
    /// ```
    fn is_immediately_after(&self, other: &Self) -> bool;

    /// Returns a new value which is `self` incremented.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert_eq!(6u32.increment(), 7);
    /// ```
    fn increment(&self) -> Self;

    /// Returns a new value which is `self` decremented.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert_eq!(6u32.decrement(), 5);
    /// ```
    fn decrement(&self) -> Self;

    /// Increments `self` in place.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// let mut value = 6u32;
    /// value.increment_ref();
    /// assert_eq!(value, 7);
    /// ```
    fn increment_ref(&mut self);

    /// Decrements `self` in place.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// let mut value = 6u32;
    /// value.decrement_ref();
    /// assert_eq!(value, 5);
    /// ```
    fn decrement_ref(&mut self);
}

/// Implements `AdjacentBound` for a type using the specified value to
/// represent an increment of "one".
///
/// For numeric types $one should be 1, however for other types this
/// will be up the implementor, for dates $one may be a single day.
#[macro_export]
macro_rules! adjacent_bound_impl {
    ($type:ty, $one:expr) => {
        impl ::AdjacentBound for $type {
            fn is_immediately_before(&self, other: &Self) -> bool {
                *self == (*other - $one)
            }

            fn is_immediately_after(&self, other: &Self) -> bool {
                *self == (*other + $one)
            }

            fn increment(&self) -> Self {
                *self + $one
            }

            fn decrement(&self) -> Self {
                *self - $one
            }

            fn increment_ref(&mut self) {
                *self = *self + $one;
            }

            fn decrement_ref(&mut self) {
                *self = *self - $one;
            }
        }
    }
}

macro_rules! adjacent_bound_impl_and_wrapping {
    ($type:ty, $one:expr) => {
        adjacent_bound_impl!($type, $one);
        adjacent_bound_impl!(::std::num::Wrapping<$type>, ::std::num::Wrapping($one));
    }
}

adjacent_bound_impl_and_wrapping!(u8, 1u8);
adjacent_bound_impl_and_wrapping!(i8, 1i8);

adjacent_bound_impl_and_wrapping!(u16, 1u16);
adjacent_bound_impl_and_wrapping!(i16, 1i16);

adjacent_bound_impl_and_wrapping!(u32, 1u32);
adjacent_bound_impl_and_wrapping!(i32, 1i32);

adjacent_bound_impl_and_wrapping!(u64, 1u64);
adjacent_bound_impl_and_wrapping!(i64, 1i64);

adjacent_bound_impl_and_wrapping!(usize, 1usize);
adjacent_bound_impl_and_wrapping!(isize, 1isize);

#[cfg(test)]
mod tests {
    use std::num::Wrapping;

    #[test]
    fn overflow_wrapping_tests() {
        assert!(Wrapping(u32::max_value()).is_immediately_before(&Wrapping(0)));
        assert!(Wrapping(0).is_immediately_after(&Wrapping(u32::max_value())));
    }
}

#[cfg(feature = "chrono")]
mod chrono_impl {
    use chrono::{Date, DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime,
                 NaiveTime, Utc};

    adjacent_bound_impl!(NaiveDate, Duration::days(1));
    adjacent_bound_impl!(NaiveDateTime, Duration::min_value());
    adjacent_bound_impl!(NaiveTime, Duration::min_value());

    adjacent_bound_impl!(Date<Utc>, Duration::days(1));
    adjacent_bound_impl!(Date<FixedOffset>, Duration::days(1));
    adjacent_bound_impl!(Date<Local>, Duration::days(1));

    adjacent_bound_impl!(DateTime<Utc>, Duration::min_value());
    adjacent_bound_impl!(DateTime<FixedOffset>, Duration::min_value());
    adjacent_bound_impl!(DateTime<Local>, Duration::min_value());

}

#[cfg(feature = "chrono")]
pub use self::chrono_impl::*;

#[cfg(feature = "extprim")]
mod extprim_impl {
    use extprim::i128::i128;
    use extprim::u128::u128;

    adjacent_bound_impl!(i128, i128::one());
    adjacent_bound_impl!(u128, u128::one());
}

#[cfg(feature = "extprim")]
pub use self::extprim_impl::*;

#[cfg(feature = "nightly")]
mod nightly_impl {
    adjacent_bound_impl_and_wrapping!(u128, 1u128);
    adjacent_bound_impl_and_wrapping!(i128, 1i128);
}

#[cfg(feature = "nightly")]
pub use self::nightly_impl::*;
<commit_msg>Fixed broken AdjacentBound tests<commit_after>/// For types which have adjacent values.
pub trait AdjacentBound: Ord {
    /// Determines whether `self` and `other` are adjacent.
    fn is_adjacent(&self, other: &Self) -> bool {
        self.is_immediately_before(other) || self.is_immediately_after(other)
    }

    /// Determines whether `self` is immediately before `other`.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert!(5u32.is_immediately_before(&6));
    /// assert_eq!(5u32.is_immediately_before(&7), false);
    /// ```
    fn is_immediately_before(&self, other: &Self) -> bool;

    /// Determines whether `self` is immediately after `other`.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert!(6u32.is_immediately_after(&5));
    /// assert_eq!(7u32.is_immediately_after(&5), false);
    /// ```
    fn is_immediately_after(&self, other: &Self) -> bool;

    /// Returns a new value which is `self` incremented.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert_eq!(6u32.increment(), 7);
    /// ```
    fn increment(&self) -> Self;

    /// Returns a new value which is `self` decremented.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// assert_eq!(6u32.decrement(), 5);
    /// ```
    fn decrement(&self) -> Self;

    /// Increments `self` in place.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// let mut value = 6u32;
    /// value.increment_ref();
    /// assert_eq!(value, 7);
    /// ```
    fn increment_ref(&mut self);

    /// Decrements `self` in place.
    ///
    /// ```
    /// use lz_diet::AdjacentBound;
    ///
    /// let mut value = 6u32;
    /// value.decrement_ref();
    /// assert_eq!(value, 5);
    /// ```
    fn decrement_ref(&mut self);
}

/// Implements `AdjacentBound` for a type using the specified value to
/// represent an increment of "one".
///
/// For numeric types $one should be 1, however for other types this
/// will be up the implementor, for dates $one may be a single day.
#[macro_export]
macro_rules! adjacent_bound_impl {
    ($type:ty, $one:expr) => {
        impl ::AdjacentBound for $type {
            fn is_immediately_before(&self, other: &Self) -> bool {
                *self == (*other - $one)
            }

            fn is_immediately_after(&self, other: &Self) -> bool {
                *self == (*other + $one)
            }

            fn increment(&self) -> Self {
                *self + $one
            }

            fn decrement(&self) -> Self {
                *self - $one
            }

            fn increment_ref(&mut self) {
                *self = *self + $one;
            }

            fn decrement_ref(&mut self) {
                *self = *self - $one;
            }
        }
    }
}

macro_rules! adjacent_bound_impl_and_wrapping {
    ($type:ty, $one:expr) => {
        adjacent_bound_impl!($type, $one);
        adjacent_bound_impl!(::std::num::Wrapping<$type>, ::std::num::Wrapping($one));
    }
}

adjacent_bound_impl_and_wrapping!(u8, 1u8);
adjacent_bound_impl_and_wrapping!(i8, 1i8);

adjacent_bound_impl_and_wrapping!(u16, 1u16);
adjacent_bound_impl_and_wrapping!(i16, 1i16);

adjacent_bound_impl_and_wrapping!(u32, 1u32);
adjacent_bound_impl_and_wrapping!(i32, 1i32);

adjacent_bound_impl_and_wrapping!(u64, 1u64);
adjacent_bound_impl_and_wrapping!(i64, 1i64);

adjacent_bound_impl_and_wrapping!(usize, 1usize);
adjacent_bound_impl_and_wrapping!(isize, 1isize);

#[cfg(test)]
mod tests {
    use std::num::Wrapping;
    use AdjacentBound;

    #[test]
    fn overflow_wrapping_tests() {
        assert!(Wrapping(u32::max_value()).is_immediately_before(&Wrapping(0)));
        assert!(Wrapping(0).is_immediately_after(&Wrapping(u32::max_value())));
    }
}

#[cfg(feature = "chrono")]
mod chrono_impl {
    use chrono::{Date, DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime,
                 NaiveTime, Utc};

    adjacent_bound_impl!(NaiveDate, Duration::days(1));
    adjacent_bound_impl!(NaiveDateTime, Duration::min_value());
    adjacent_bound_impl!(NaiveTime, Duration::min_value());

    adjacent_bound_impl!(Date<Utc>, Duration::days(1));
    adjacent_bound_impl!(Date<FixedOffset>, Duration::days(1));
    adjacent_bound_impl!(Date<Local>, Duration::days(1));

    adjacent_bound_impl!(DateTime<Utc>, Duration::min_value());
    adjacent_bound_impl!(DateTime<FixedOffset>, Duration::min_value());
    adjacent_bound_impl!(DateTime<Local>, Duration::min_value());

}

#[cfg(feature = "chrono")]
pub use self::chrono_impl::*;

#[cfg(feature = "extprim")]
mod extprim_impl {
    use extprim::i128::i128;
    use extprim::u128::u128;

    adjacent_bound_impl!(i128, i128::one());
    adjacent_bound_impl!(u128, u128::one());
}

#[cfg(feature = "extprim")]
pub use self::extprim_impl::*;

#[cfg(feature = "nightly")]
mod nightly_impl {
    adjacent_bound_impl_and_wrapping!(u128, 1u128);
    adjacent_bound_impl_and_wrapping!(i128, 1i128);
}

#[cfg(feature = "nightly")]
pub use self::nightly_impl::*;
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::CORE_CODE_ADDRESS;
use anyhow::Result;
use move_core_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag, TypeTag},
};
use once_cell::sync::Lazy;

pub const LIBRA_MODULE_NAME: &str = "Libra";
static COIN_MODULE_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("Libra").unwrap());
static COIN_STRUCT_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("T").unwrap());
pub static COIN_MODULE: Lazy<ModuleId> =
    Lazy::new(|| ModuleId::new(CORE_CODE_ADDRESS, COIN_MODULE_NAME.clone()));

pub fn coin_module_name() -> &'static IdentStr {
    &*COIN_MODULE_NAME
}

pub fn coin_struct_name() -> &'static IdentStr {
    &*COIN_STRUCT_NAME
}

// TODO: This imposes a few implied restrictions:
//   1) The currency module must be published under the core code address.
//   2) The module name must be the same as the gas specifier.
//   3) The struct name must be "T"
// We need to consider whether we want to switch to a more or fully qualified name.
pub fn type_tag_for_currency_code(currency_code: Identifier) -> TypeTag {
    TypeTag::Struct(StructTag {
        address: CORE_CODE_ADDRESS,
        module: currency_code,
        name: coin_struct_name().to_owned(),
        type_params: vec![],
    })
}

pub fn from_currency_code_string(currency_code_string: &str) -> Result<Identifier> {
    Identifier::new(currency_code_string)
}
<commit_msg>Removing coin_module_name from types/src/account_config/constants/libra.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::CORE_CODE_ADDRESS;
use anyhow::Result;
use move_core_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag, TypeTag},
};
use once_cell::sync::Lazy;

pub const LIBRA_MODULE_NAME: &str = "Libra";
static COIN_MODULE_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("Libra").unwrap());
static COIN_STRUCT_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("T").unwrap());
pub static COIN_MODULE: Lazy<ModuleId> =
    Lazy::new(|| ModuleId::new(CORE_CODE_ADDRESS, COIN_MODULE_NAME.clone()));

pub fn coin_struct_name() -> &'static IdentStr {
    &*COIN_STRUCT_NAME
}

// TODO: This imposes a few implied restrictions:
//   1) The currency module must be published under the core code address.
//   2) The module name must be the same as the gas specifier.
//   3) The struct name must be "T"
// We need to consider whether we want to switch to a more or fully qualified name.
pub fn type_tag_for_currency_code(currency_code: Identifier) -> TypeTag {
    TypeTag::Struct(StructTag {
        address: CORE_CODE_ADDRESS,
        module: currency_code,
        name: coin_struct_name().to_owned(),
        type_params: vec![],
    })
}

pub fn from_currency_code_string(currency_code_string: &str) -> Result<Identifier> {
    Identifier::new(currency_code_string)
}
<|endoftext|>


<commit_before>use std::collections;
use std::env;
use std::fs;
use std::io::Write;
use std::path;

use clap;
use cobalt::cobalt_model;

use args;
use error::*;

pub fn init_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("init")
        .about("create a new cobalt project")
        .arg(
            clap::Arg::with_name("DIRECTORY")
                .help("Target directory")
                .default_value("./")
                .index(1),
        )
}

pub fn init_command(matches: &clap::ArgMatches) -> Result<()> {
    let directory = matches.value_of("DIRECTORY").unwrap();

    create_new_project(&directory.to_string())
        .chain_err(|| "Could not create a new cobalt project")?;
    info!("Created new project at {}", directory);

    Ok(())
}

pub fn new_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("new")
        .about("Create a document")
        .args(&args::get_config_args())
        .arg(
            clap::Arg::with_name("TITLE")
                .required(true)
                .help("Title of the post")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("file")
                .short("f")
                .long("file")
                .value_name("DIR_OR_FILE")
                .help("New document's parent directory or file (default: `<CWD>/title.ext`)")
                .takes_value(true),
        )
}

pub fn new_command(matches: &clap::ArgMatches) -> Result<()> {
    let config = args::get_config(matches)?;
    let config = config.build()?;

    let title = matches.value_of("TITLE").unwrap();

    let mut file = env::current_dir().expect("How does this fail?");
    if let Some(rel_file) = matches.value_of("file") {
        file.push(path::Path::new(rel_file))
    }

    create_new_document(&config, title, file)
        .chain_err(|| format!("Could not create `{}`", title))?;

    Ok(())
}

pub fn publish_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("publish")
        .about("Publish a document")
        .arg(
            clap::Arg::with_name("FILENAME")
                .required(true)
                .help("Document path to publish")
                .takes_value(true),
        )
}

pub fn publish_command(matches: &clap::ArgMatches) -> Result<()> {
    let file = matches
        .value_of("FILENAME")
        .expect("required parameters are present");
    let file = path::Path::new(file);

    publish_document(file).chain_err(|| format!("Could not publish `{:?}`", file))?;

    Ok(())
}

const COBALT_YML: &str = "
site:
  title: cobalt blog
  description: Blog Posts Go Here
  base_url: http://example.com
posts:
  rss: rss.xml
";

const DEFAULT_LAYOUT: &str = "<!DOCTYPE html>

        <meta charset=\"utf-8\">
        <title>{{ page.title }}</title>

{{ page.title }}

      {{ page.content }}

";

const POST_MD: &str = "layout: default.liquid

title: First Post
is_draft: true
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const INDEX_MD: &str = "layout: default.liquid
---
## Blog!

{% for post in collections.posts.pages %}
#### {{post.title}}

[{{ post.title }}]({{ post.permalink }})
{% endfor %}
";

lazy_static! {
    static ref DEFAULT: collections::HashMap<&'static str, &'static str> = [("pages", INDEX_MD), ("posts", POST_MD)].iter().map(|e| e.clone()).collect();
}

pub fn create_new_project<P: AsRef<path::Path>>(dest: P) -> Result<()> {
    create_new_project_for_path(dest.as_ref())
}

pub fn create_new_project_for_path(dest: &path::Path) -> Result<()> {
    fs::create_dir_all(dest)?;

    create_file(&dest.join("_cobalt.yml"), COBALT_YML)?;
    create_file(&dest.join("index.md"), INDEX_MD)?;

    fs::create_dir_all(&dest.join("_layouts"))?;
    create_file(&dest.join("_layouts/default.liquid"), DEFAULT_LAYOUT)?;

    fs::create_dir_all(&dest.join("posts"))?;
    create_file(&dest.join("posts/post-1.md"), POST_MD)?;

    fs::create_dir_all(&dest.join("_defaults"))?;
    create_file(&dest.join("_defaults/pages.md"), INDEX_MD)?;
    create_file(&dest.join("_defaults/posts.md"), POST_MD)?;

    Ok(())
}

pub fn create_new_document(
    config: &cobalt_model::Config,
    title: &str,
    file: path::PathBuf,
) -> Result<()> {
    let file = if file.extension().is_none() || file.is_dir() {
        let file_name = format!("{}.md", cobalt_model::slug::slugify(title));
        let mut file = file;
        file.push(path::Path::new(&file_name));
        file
    } else {
        file
    };

    let rel_file = file.strip_prefix(&config.source).map_err(|_| {
        format!(
            "New file {:?} not project directory ({:?})",
            file, config.source
        )
    })?;

    let pages = config.pages.clone().build()?;
    let posts = config.posts.clone().build()?;
    let file_type = if posts.pages.includes_file(&file)
        || posts
            .drafts
            .map(|d| d.includes_file(&file))
            .unwrap_or_default()
    {
        posts.slug.as_str()
    } else if pages.pages.includes_file(&file)
        || pages
            .drafts
            .map(|d| d.includes_file(&file))
            .unwrap_or_default()
    {
        pages.slug.as_str()
    } else {
        bail!(
            "Target file wouldn't be a member of any collection: {:?}",
            file
        );
    };

    let extension = file.extension()
        .unwrap_or_default()
        .to_str()
        .unwrap_or_default();
    let source_path = config
        .source
        .join(format!("_defaults/{}.{}", file_type, extension));
    let source = if source_path.is_file() {
        cobalt_model::files::read_file(&source_path)
            .chain_err(|| format!("Failed to read default: {:?}", source_path))?
    } else {
        debug!(
            "No custom default provided ({:?}), falling back to built-in",
            source_path
        );
        if extension != "md" {
            bail!(
                "No builtin default for `{}` files, only `md`: {:?}",
                extension,
                file
            );
        }
        // For custom collections, use a post default.
        DEFAULT.get(file_type).unwrap_or(&POST_MD).to_string()
    };

    let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&source)?;
    let (front, content) = doc.parts();
    let front = front.set_title(title.to_owned());
    let doc =
        cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::new(front, content);
    let doc = doc.to_string();

    create_file(&file, &doc)?;
    info!("Created new {} {:?}", file_type, rel_file);

    Ok(())
}

fn create_file<P: AsRef<path::Path>>(path: P, content: &str) -> Result<()> {
    create_file_for_path(path.as_ref(), content)
}

fn create_file_for_path(path: &path::Path, content: &str) -> Result<()> {
    trace!("Creating file {:?}", path);

    let mut file = fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(path)
        .chain_err(|| format!("Failed to create file {:?}", path))?;

    file.write_all(content.as_bytes())?;

    Ok(())
}

pub fn publish_document(file: &path::Path) -> Result<()> {
    let doc = cobalt_model::files::read_file(file)?;
    let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&doc)?;
    let (front, content) = doc.parts();

    let date = cobalt_model::DateTime::now();
    let front = front.set_draft(false).set_published_date(date);

    let doc =
        cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::new(front, content);
    let doc = doc.to_string();

    cobalt_model::files::write_document_file(doc, file)?;

    Ok(())
}
<commit_msg>feat(new): --with-ext to specify type without --file<commit_after>use std::borrow;
use std::collections;
use std::env;
use std::fs;
use std::io::Write;
use std::path;

use clap;
use cobalt::cobalt_model;

use args;
use error::*;

pub fn init_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("init")
        .about("create a new cobalt project")
        .arg(
            clap::Arg::with_name("DIRECTORY")
                .help("Target directory")
                .default_value("./")
                .index(1),
        )
}

pub fn init_command(matches: &clap::ArgMatches) -> Result<()> {
    let directory = matches.value_of("DIRECTORY").unwrap();

    create_new_project(&directory.to_string())
        .chain_err(|| "Could not create a new cobalt project")?;
    info!("Created new project at {}", directory);

    Ok(())
}

pub fn new_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("new")
        .about("Create a document")
        .args(&args::get_config_args())
        .arg(
            clap::Arg::with_name("TITLE")
                .required(true)
                .help("Title of the post")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("file")
                .short("f")
                .long("file")
                .value_name("DIR_OR_FILE")
                .help("New document's parent directory or file (default: `<CWD>/title.ext`)")
                .takes_value(true),
        )
        .arg(
            clap::Arg::with_name("with-ext")
                .long("with-ext")
                .value_name("EXT")
                .help("The default file's extension (e.g. `liquid`)")
                .takes_value(true),
        )
}

pub fn new_command(matches: &clap::ArgMatches) -> Result<()> {
    let config = args::get_config(matches)?;
    let config = config.build()?;

    let title = matches.value_of("TITLE").unwrap();

    let mut file = env::current_dir().expect("How does this fail?");
    if let Some(rel_file) = matches.value_of("file") {
        file.push(path::Path::new(rel_file))
    }

    let ext = matches.value_of("with-ext");

    create_new_document(&config, title, file, ext)
        .chain_err(|| format!("Could not create `{}`", title))?;

    Ok(())
}

pub fn publish_command_args() -> clap::App<'static, 'static> {
    clap::SubCommand::with_name("publish")
        .about("Publish a document")
        .arg(
            clap::Arg::with_name("FILENAME")
                .required(true)
                .help("Document path to publish")
                .takes_value(true),
        )
}

pub fn publish_command(matches: &clap::ArgMatches) -> Result<()> {
    let file = matches
        .value_of("FILENAME")
        .expect("required parameters are present");
    let file = path::Path::new(file);

    publish_document(file).chain_err(|| format!("Could not publish `{:?}`", file))?;

    Ok(())
}

const COBALT_YML: &str = "
site:
  title: cobalt blog
  description: Blog Posts Go Here
  base_url: http://example.com
posts:
  rss: rss.xml
";

const DEFAULT_LAYOUT: &str = "<!DOCTYPE html>

        <meta charset=\"utf-8\">
        <title>{{ page.title }}</title>

{{ page.title }}

      {{ page.content }}

";

const POST_MD: &str = "layout: default.liquid

title: First Post
is_draft: true
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const INDEX_MD: &str = "layout: default.liquid
---
## Blog!

{% for post in collections.posts.pages %}
#### {{post.title}}

[{{ post.title }}]({{ post.permalink }})
{% endfor %}
";

lazy_static! {
    static ref DEFAULT: collections::HashMap<&'static str, &'static str> = [("pages", INDEX_MD), ("posts", POST_MD)].iter().map(|e| e.clone()).collect();
}

pub fn create_new_project<P: AsRef<path::Path>>(dest: P) -> Result<()> {
    create_new_project_for_path(dest.as_ref())
}

pub fn create_new_project_for_path(dest: &path::Path) -> Result<()> {
    fs::create_dir_all(dest)?;

    create_file(&dest.join("_cobalt.yml"), COBALT_YML)?;
    create_file(&dest.join("index.md"), INDEX_MD)?;

    fs::create_dir_all(&dest.join("_layouts"))?;
    create_file(&dest.join("_layouts/default.liquid"), DEFAULT_LAYOUT)?;

    fs::create_dir_all(&dest.join("posts"))?;
    create_file(&dest.join("posts/post-1.md"), POST_MD)?;

    fs::create_dir_all(&dest.join("_defaults"))?;
    create_file(&dest.join("_defaults/pages.md"), INDEX_MD)?;
    create_file(&dest.join("_defaults/posts.md"), POST_MD)?;

    Ok(())
}

pub fn create_new_document(
    config: &cobalt_model::Config,
    title: &str,
    file: path::PathBuf,
    extension: Option<&str>,
) -> Result<()> {
    let (file, extension) = if file.extension().is_none() || file.is_dir() {
        let extension = extension.unwrap_or("md");
        let file_name = format!("{}.{}", cobalt_model::slug::slugify(title), extension);
        let mut file = file;
        file.push(path::Path::new(&file_name));
        (file, borrow::Cow::Borrowed(extension))
    } else {
        // The user-provided extension will be used for selecting a template
        let extension = extension.map(borrow::Cow::Borrowed).unwrap_or_else(|| {
            borrow::Cow::Owned(
                file.extension()
                    .unwrap_or_default()
                    .to_str()
                    .unwrap_or_default()
                    .to_string(),
            )
        });
        (file, extension)
    };

    let rel_file = file.strip_prefix(&config.source).map_err(|_| {
        format!(
            "New file {:?} not project directory ({:?})",
            file, config.source
        )
    })?;

    let pages = config.pages.clone().build()?;
    let posts = config.posts.clone().build()?;
    let file_type = if posts.pages.includes_file(&file)
        || posts
            .drafts
            .map(|d| d.includes_file(&file))
            .unwrap_or_default()
    {
        posts.slug.as_str()
    } else if pages.pages.includes_file(&file)
        || pages
            .drafts
            .map(|d| d.includes_file(&file))
            .unwrap_or_default()
    {
        pages.slug.as_str()
    } else {
        bail!(
            "Target file wouldn't be a member of any collection: {:?}",
            file
        );
    };

    let source_path = config
        .source
        .join(format!("_defaults/{}.{}", file_type, extension));
    let source = if source_path.is_file() {
        cobalt_model::files::read_file(&source_path)
            .chain_err(|| format!("Failed to read default: {:?}", source_path))?
    } else {
        debug!(
            "No custom default provided ({:?}), falling back to built-in",
            source_path
        );
        if extension != "md" {
            bail!(
                "No builtin default for `{}` files, only `md`: {:?}",
                extension,
                file
            );
        }
        // For custom collections, use a post default.
        DEFAULT.get(file_type).unwrap_or(&POST_MD).to_string()
    };

    let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&source)?;
    let (front, content) = doc.parts();
    let front = front.set_title(title.to_owned());
    let doc =
        cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::new(front, content);
    let doc = doc.to_string();

    create_file(&file, &doc)?;
    info!("Created new {} {:?}", file_type, rel_file);

    Ok(())
}

fn create_file<P: AsRef<path::Path>>(path: P, content: &str) -> Result<()> {
    create_file_for_path(path.as_ref(), content)
}

fn create_file_for_path(path: &path::Path, content: &str) -> Result<()> {
    trace!("Creating file {:?}", path);

    let mut file = fs::OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(path)
        .chain_err(|| format!("Failed to create file {:?}", path))?;

    file.write_all(content.as_bytes())?;

    Ok(())
}

pub fn publish_document(file: &path::Path) -> Result<()> {
    let doc = cobalt_model::files::read_file(file)?;
    let doc = cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::parse(&doc)?;
    let (front, content) = doc.parts();

    let date = cobalt_model::DateTime::now();
    let front = front.set_draft(false).set_published_date(date);

    let doc =
        cobalt_model::DocumentBuilder::<cobalt_model::FrontmatterBuilder>::new(front, content);
    let doc = doc.to_string();

    cobalt_model::files::write_document_file(doc, file)?;

    Ok(())
}
<|endoftext|>


<commit_before>extern mod std;
extern mod encoding;

use std::net::ip;
use std::net::tcp;
use std::uv_global_loop;

use encoding::{Codec};
use io::{ReaderUtil, WriterUtil};
use tcp::{TcpErrData, TcpNewConnection, TcpSocket};
use task::{SingleThreaded, task};

type KillChan = comm::Chan<Option<TcpErrData>>;
type ContChan = comm::Chan<()>;

fn main() {
    let iotask = uv_global_loop::get();

    let addr = "127.0.0.1";
    let port = 1337;

    let backlog = 128;
    let ip_addr = ip::get_addr(addr, iotask);
    let ip_addr = copy result::unwrap(ip_addr)[0];

    tcp::listen(ip_addr, port, backlog, iotask,
        |kill_ch| on_established(kill_ch),
        |conn, kill_ch| on_new_connection(conn, kill_ch));
}

fn on_established(_kill_ch: KillChan) {
    io::println("running at 127.0.0.1:1337");
}

fn on_new_connection(conn: TcpNewConnection, kill_ch: KillChan) {
    do comm::listen |cont_ch| {
        // Spawn new child which doesn't propagate errors to parent.
        do task().unlinked().sched_mode(SingleThreaded).spawn {
            accept(conn, kill_ch, cont_ch);
        }
        // Wait `tcp::accept(conn)' complete.
        cont_ch.recv();
    }
}

fn accept(conn: TcpNewConnection, kill_ch: KillChan, cont_ch: ContChan) {
    match tcp::accept(conn) {
        Ok(move socket) => {
            cont_ch.send(());
            encode(socket);
        }
        Err(move err_data) => {
            kill_ch.send(Some(err_data));
            cont_ch.send(());
        }
    }
}

fn encode(socket: TcpSocket) {
    let socket = tcp::socket_buf(socket);

    let mut chunk = ~[];
    let mut buf = [mut 0, ..1024];

    loop {
        let nread = socket.read(buf, buf.len());
        if nread == 0 {
            break;
        }
        chunk.push_all(buf.view(0, nread));
    }

    let encoded_bytes = chunk.encode(encoding::Base64);

    socket.write(encoded_bytes);
}
<commit_msg>examples: Make moves explicit<commit_after>extern mod std;
extern mod encoding;

use std::net::ip;
use std::net::tcp;
use std::uv_global_loop;

use encoding::{Codec};
use io::{ReaderUtil, WriterUtil};
use tcp::{TcpErrData, TcpNewConnection, TcpSocket};
use task::{SingleThreaded, task};

type KillChan = comm::Chan<Option<TcpErrData>>;
type ContChan = comm::Chan<()>;

fn main() {
    let iotask = uv_global_loop::get();

    let addr = "127.0.0.1";
    let port = 1337;

    let backlog = 128;
    let ip_addr = ip::get_addr(addr, iotask);
    let ip_addr = copy result::unwrap(move ip_addr)[0];

    tcp::listen(move ip_addr, port, backlog, iotask,
        |kill_ch| on_established(kill_ch),
        |conn, kill_ch| on_new_connection(conn, kill_ch));
}

fn on_established(_kill_ch: KillChan) {
    io::println("running at 127.0.0.1:1337");
}

fn on_new_connection(conn: TcpNewConnection, kill_ch: KillChan) {
    do comm::listen |cont_ch| {
        // Spawn new child which doesn't propagate errors to parent.
        do task().unlinked().sched_mode(SingleThreaded).spawn {
            accept(conn, kill_ch, cont_ch);
        }
        // Wait `tcp::accept(conn)' complete.
        cont_ch.recv();
    }
}

fn accept(conn: TcpNewConnection, kill_ch: KillChan, cont_ch: ContChan) {
    match tcp::accept(conn) {
        Ok(move socket) => {
            cont_ch.send(());
            encode(move socket);
        }
        Err(move err_data) => {
            kill_ch.send(Some(move err_data));
            cont_ch.send(());
        }
    }
}

fn encode(socket: TcpSocket) {
    let socket = tcp::socket_buf(move socket);

    let mut chunk = ~[];
    let mut buf = [mut 0, ..1024];

    loop {
        let nread = socket.read(buf, buf.len());
        if nread == 0 {
            break;
        }
        chunk.push_all(buf.view(0, nread));
    }

    let encoded_bytes = chunk.encode(encoding::Base64);

    socket.write(encoded_bytes);
}
<|endoftext|>


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

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

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

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

const PADDING: i32 = 10;

const FONT_COLOR: Color = Color::RGBA(45, 200, 45, 255);
const FONT_SIZE: u16 = 18;

pub struct Console<'a> {
    pub visible: bool,
    visible_start_time: u32, // Used to ensure that the KeyDown event that opens the console does not trigger text input

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

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

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

        Console {
            visible: false,
            visible_start_time: 0,

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

    pub fn process(&mut self, event: &Event) {
        match *event {
            Event::TextInput { ref text, timestamp, .. } => {
                if self.visible && timestamp != self.visible_start_time {
                    self.add_text(text);
                }
            }
            Event::MouseWheel { y, .. } => {
                if self.visible {
                    if self.buffer.len() * FONT_SIZE as usize >
                       (self.size.1 - (FONT_SIZE as u32 * 2)) as usize {
                        self.backbuffer_y += y * 6;
                        if self.backbuffer_y < 0 {
                            self.backbuffer_y = 0;
                        }
                    }
                }
            }
            Event::KeyDown { keycode, scancode, timestamp, keymod, .. } => {
                if self.visible {
                    if !keymod.intersects(LALTMOD | LCTRLMOD | LSHIFTMOD | RALTMOD | RCTRLMOD | RSHIFTMOD) {
                        // The 'Grave' scancode coresponds to the key in the top-left corner of the
                        // keyboard, bellow escape, on (hopefully) all keyboard layouts.
                        if let Some(Scancode::Grave) = scancode {
                            self.toggle(timestamp);
                            return;
                        }
                    }

                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = true,
                        Some(Keycode::LShift) |
                        Some(Keycode::RShift) => self.shift = true,
                        Some(Keycode::C) => {
                            if self.ctrl {
                                self.input_buffer.push_str("^C");
                                self.commit();
                            }
                        }
                        Some(Keycode::Left) => {
                            self.cursor_left();
                        }
                        Some(Keycode::Right) => {
                            self.cursor_right();
                        }
                        Some(Keycode::Backspace) => {
                            self.backspace();
                        }
                        Some(Keycode::Delete) => {
                            if self.cursor_position < self.input_buffer.len() {
                                self.cursor_position += 1;
                                self.backspace();
                            }
                        }
                        _ => (),
                    }
                }
            }
            Event::KeyUp { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = false,
                        Some(Keycode::LShift) |
                        Some(Keycode::RShift) => self.shift = false,
                        Some(Keycode::Up) => {
                            self.history_navigate_back();
                        }
                        Some(Keycode::Down) => {
                            self.history_navigate_forward();
                        }
                        Some(Keycode::Return) => {
                            self.commit();
                        }
                        Some(Keycode::End) => {
                            self.cursor_position = self.input_buffer.len();
                        }
                        Some(Keycode::Home) => {
                            self.cursor_position = 0;
                        }
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }

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

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

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

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

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

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

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

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

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

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

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

    /// Toggles the visibility of the Console
    pub fn toggle(&mut self, time: u32) {
        self.visible = !self.visible;
        if self.visible {
            self.visible_start_time = time;
        }
    }

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

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

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

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

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

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

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

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

            if !self.input_buffer.is_empty() {
                let text = Text::new(self.ttf_context,
                                     &mut renderer,
                                     &self.input_buffer[..],
                                     Position::XY(60 + PADDING,
                                                  self.size.1 as i32 - FONT_SIZE as i32 - PADDING),
                                     FONT_SIZE,
                                     FONT_COLOR,
                                     self.font_file);
                text.render(&mut renderer);
            }

            self.render_border(&mut renderer);
        }
    }

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

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

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

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

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

            if line.trim().is_empty() {
                continue;
            }

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

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

        renderer.copy(&texture, None, Some(Rect::new(0, 0, width, height))).unwrap();
    }
}
<commit_msg>Add 50ms to timestamp check to prevent backticks<commit_after>use std;
use std::path::Path;

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

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

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

const PADDING: i32 = 10;

const FONT_COLOR: Color = Color::RGBA(45, 200, 45, 255);
const FONT_SIZE: u16 = 18;

pub struct Console<'a> {
    pub visible: bool,
    visible_start_time: u32, /* Used to ensure that the KeyDown event that opens the console does not trigger text input */

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

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

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

        Console {
            visible: false,
            visible_start_time: 0,

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

    pub fn process(&mut self, event: &Event) {
        match *event {
            Event::TextInput { ref text, timestamp, .. } => {
                if self.visible && timestamp > self.visible_start_time + 50 {
                    self.add_text(text);
                }
            }
            Event::MouseWheel { y, .. } => {
                if self.visible {
                    if self.buffer.len() * FONT_SIZE as usize >
                       (self.size.1 - (FONT_SIZE as u32 * 2)) as usize {
                        self.backbuffer_y += y * 6;
                        if self.backbuffer_y < 0 {
                            self.backbuffer_y = 0;
                        }
                    }
                }
            }
            Event::KeyDown { keycode, scancode, timestamp, keymod, .. } => {
                if self.visible {
                    if !keymod.intersects(LALTMOD | LCTRLMOD | LSHIFTMOD | RALTMOD | RCTRLMOD |
                                          RSHIFTMOD) {
                        // The 'Grave' scancode coresponds to the key in the top-left corner of the
                        // keyboard, below escape, on (hopefully) all keyboard layouts.
                        if let Some(Scancode::Grave) = scancode {
                            self.toggle(timestamp);
                            return;
                        }
                    }

                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = true,
                        Some(Keycode::LShift) |
                        Some(Keycode::RShift) => self.shift = true,
                        Some(Keycode::C) => {
                            if self.ctrl {
                                self.input_buffer.push_str("^C");
                                self.commit();
                            }
                        }
                        Some(Keycode::Left) => {
                            self.cursor_left();
                        }
                        Some(Keycode::Right) => {
                            self.cursor_right();
                        }
                        Some(Keycode::Backspace) => {
                            self.backspace();
                        }
                        Some(Keycode::Delete) => {
                            if self.cursor_position < self.input_buffer.len() {
                                self.cursor_position += 1;
                                self.backspace();
                            }
                        }
                        _ => (),
                    }
                }
            }
            Event::KeyUp { keycode, .. } => {
                if self.visible {
                    match keycode {
                        Some(Keycode::LCtrl) |
                        Some(Keycode::RCtrl) => self.ctrl = false,
                        Some(Keycode::LShift) |
                        Some(Keycode::RShift) => self.shift = false,
                        Some(Keycode::Up) => {
                            self.history_navigate_back();
                        }
                        Some(Keycode::Down) => {
                            self.history_navigate_forward();
                        }
                        Some(Keycode::Return) => {
                            self.commit();
                        }
                        Some(Keycode::End) => {
                            self.cursor_position = self.input_buffer.len();
                        }
                        Some(Keycode::Home) => {
                            self.cursor_position = 0;
                        }
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }

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

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

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

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

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

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

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

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

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

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

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

    /// Toggles the visibility of the Console
    pub fn toggle(&mut self, time: u32) {
        self.visible = !self.visible;
        if self.visible {
            self.visible_start_time = time;
        }
    }

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

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

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

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

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

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

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

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

            if !self.input_buffer.is_empty() {
                let text = Text::new(self.ttf_context,
                                     &mut renderer,
                                     &self.input_buffer[..],
                                     Position::XY(60 + PADDING,
                                                  self.size.1 as i32 - FONT_SIZE as i32 - PADDING),
                                     FONT_SIZE,
                                     FONT_COLOR,
                                     self.font_file);
                text.render(&mut renderer);
            }

            self.render_border(&mut renderer);
        }
    }

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

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

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

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

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

            if line.trim().is_empty() {
                continue;
            }

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

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

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