<commit_before>use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use physics::{Dimensions, get_orientation};
use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use specs;
use gfx_app::graphics::load_texture;
use character::gfx_macros::{pipe, VertexData, CharacterSheet, Position};
use game::gfx_macros::Projection;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE};
use gfx_app::mouse_controls::MouseInputState;
use terrain::controls::TerrainInputState;
use character::controls::CharacterInputState;
use data;
use character::orientation::Orientation;
use character::character::{CharacterSprite, CharacterData};

pub mod gfx_macros;
pub mod character;
pub mod orientation;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("character.f.glsl");

impl VertexData {
  fn new(pos: [f32; 3], buf_pos: [f32; 2]) -> VertexData {
    VertexData {
      pos,
      buf_pos,
    }
  }
}

#[derive(Debug)]
pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  direction: Orientation,
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, VIEW_DISTANCE),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      direction: Orientation::Right,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mi: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    get_orientation(&self.position, mi);

    let dx = new_position.position[0] - self.position.position[0];
    let dy = new_position.position[1] - self.position.position[1];
    self.orientation =
    if dx == 0.0 && dy < 0.0       { Orientation::Down }
    else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
    else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
    else if dx == 0.0 && dy == 0.0 { Orientation::Still }
    else if dx > 0.0 && dy == 0.0  { Orientation::Right }
    else if dx < 0.0 && dy == 0.0  { Orientation::Left }
    else if dx == 0.0 && dy > 0.0  { Orientation::Up }
    else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
    else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
    else { unreachable!() };
    self.position = new_position;
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CharacterData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> DrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let tilesheet_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, tilesheet_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, orientation: &Orientation, direction: &mut Orientation) -> CharacterSheet {
    let charsheet_total_width = 12544f32;
    let offset = 2.0;
    if *orientation == Orientation::Still {
      let sprite_idx = (*direction as usize * 28) as usize;
      let char_sprite = &self.data[sprite_idx];
      let elements_x = charsheet_total_width / (char_sprite.data[2] + offset);
      let char = CharacterSheet {
        div: elements_x,
        index: sprite_idx as f32
      };
      char
    } else {
      *direction = *orientation;
      let sprite_idx = (*orientation as usize * 28 + character_idx) as usize;
      let char_sprite = &self.data[sprite_idx];
      let elements_x = charsheet_total_width / (char_sprite.data[2] + offset);
      let char = CharacterSheet {
        div: elements_x,
        index: sprite_idx as f32
      };
      char
    }
  }

  pub fn draw<C>(&mut self,
                 drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb, &mut self.get_next_sprite(character.character_idx, &drawable.orientation, &mut drawable.direction));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<TerrainInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<MouseInputState>()));

    for (c, i, ci, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(i);
      c.update(&world_to_clip, ci, mi);
    }
  }
}
<commit_msg>Add shooting animation while mouse left is pressed<commit_after>use gfx;
use gfx_app::{ColorFormat, DepthFormat};
use physics::Dimensions;
use cgmath;
use cgmath::{Matrix4, Point3, Vector3};
use specs;
use gfx_app::graphics::load_texture;
use character::gfx_macros::{pipe, VertexData, CharacterSheet, Position};
use game::gfx_macros::Projection;
use game::constants::{ASPECT_RATIO, VIEW_DISTANCE, RUN_SPRITE_OFFSET};
use gfx_app::mouse_controls::MouseInputState;
use terrain::controls::TerrainInputState;
use character::controls::CharacterInputState;
use data;
use character::orientation::{Orientation, Stance};
use character::character::{CharacterSprite, CharacterData};

pub mod gfx_macros;
pub mod character;
pub mod orientation;
pub mod controls;

const SHADER_VERT: &'static [u8] = include_bytes!("character.v.glsl");
const SHADER_FRAG: &'static [u8] = include_bytes!("character.f.glsl");

impl VertexData {
  fn new(pos: [f32; 3], buf_pos: [f32; 2]) -> VertexData {
    VertexData {
      pos,
      buf_pos,
    }
  }
}

#[derive(Debug)]
pub struct CharacterDrawable {
  projection: Projection,
  position: Position,
  orientation: Orientation,
  stance: Stance,
  direction: Orientation,
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view: Matrix4<f32> = Matrix4::look_at(
      Point3::new(0.0, 0.0, VIEW_DISTANCE),
      Point3::new(0.0, 0.0, 0.0),
      Vector3::unit_y(),
    );

    let aspect_ratio: f32 = ASPECT_RATIO;

    CharacterDrawable {
      projection: Projection {
        model: Matrix4::from(view).into(),
        view: view.into(),
        proj: cgmath::perspective(cgmath::Deg(60.0f32), aspect_ratio, 0.1, 4000.0).into(),
      },
      position: Position {
        position: [0.0, 0.0],
      },
      orientation: Orientation::Right,
      stance: Stance::Normal,
      direction: Orientation::Right,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mouse_input: &mut MouseInputState) {
    self.projection = *world_to_clip;
    let new_position = Position {
      position: [ci.x_movement, ci.y_movement]
    };

    if let Some(_) = mouse_input.left_click_point {
      self.stance = Stance::Firing;
    } else {
      self.stance = Stance::Normal;
    }

    let dx = new_position.position[0] - self.position.position[0];
    let dy = new_position.position[1] - self.position.position[1];
    self.orientation =
    if dx == 0.0 && dy < 0.0       { Orientation::Down }
    else if dx > 0.0 && dy < 0.0   { Orientation::DownRight }
    else if dx < 0.0 && dy < 0.0   { Orientation::DownLeft }
    else if dx == 0.0 && dy == 0.0 { Orientation::Still }
    else if dx > 0.0 && dy == 0.0  { Orientation::Right }
    else if dx < 0.0 && dy == 0.0  { Orientation::Left }
    else if dx == 0.0 && dy > 0.0  { Orientation::Up }
    else if dx > 0.0 && dy > 0.0   { Orientation::UpRight }
    else if dx < 0.0 && dy > 0.0   { Orientation::UpLeft }
    else { unreachable!() };
    self.position = new_position;
  }
}

impl specs::Component for CharacterDrawable {
  type Storage = specs::VecStorage<CharacterDrawable>;
}

pub struct DrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, pipe::Data<R>>,
  data: Vec<CharacterData>,
}

impl<R: gfx::Resources> DrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> DrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let tilesheet_bytes = &include_bytes!("../../assets/character.png")[..];

    let vertex_data: Vec<VertexData> =
      vec![
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, -28.0, 0.0], [1.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, -28.0, 0.0], [0.0, 1.0]),
        VertexData::new([20.0, 28.0, 0.0], [1.0, 0.0]),
        VertexData::new([-20.0, 28.0, 0.0], [0.0, 0.0]),
      ];

    let (vertex_buf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());

    let char_texture = load_texture(factory, tilesheet_bytes).unwrap();
    let pso = factory
      .create_pipeline_simple(SHADER_VERT,
                              SHADER_FRAG,
                              pipe::new())
      .unwrap();

    let pipeline_data = pipe::Data {
      vbuf: vertex_buf,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (char_texture, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    DrawSystem {
      bundle: gfx::Bundle::new(slice, pso, pipeline_data),
      data
    }
  }

  fn get_next_sprite(&self, character_idx: usize, mut drawable: &mut CharacterDrawable) -> CharacterSheet {
    let charsheet_total_width = 16128f32;
    let offset = 2.0;

    if drawable.orientation == Orientation::Still && drawable.stance == Stance::Normal {
      let sprite_idx = (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET) as usize;
      let char_sprite = &self.data[sprite_idx];
      let elements_x = charsheet_total_width / (char_sprite.data[2] + offset);
      let char = CharacterSheet {
        div: elements_x,
        index: sprite_idx as f32
      };
      char
    } else if drawable.stance == Stance::Normal {
      drawable.direction = drawable.orientation;
      let sprite_idx = (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET) as usize;
      let char_sprite = &self.data[sprite_idx];
      let elements_x = charsheet_total_width / (char_sprite.data[2] + offset);
      let char = CharacterSheet {
        div: elements_x,
        index: sprite_idx as f32
      };
      char
    } else {
      let idx = (character_idx as f32 * 4.0 / 14.0).floor() as usize;
      let sprite_idx = (drawable.orientation as usize * 8 + idx) as usize;
      let char_sprite = &self.data[sprite_idx];
      let elements_x = charsheet_total_width / (char_sprite.data[2] + offset);
      let char = CharacterSheet {
        div: elements_x,
        index: sprite_idx as f32
      };
      char
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb, &mut self.get_next_sprite(character.character_idx, &mut drawable));
    self.bundle.encode(encoder);
  }
}

#[derive(Debug)]
pub struct PreDrawSystem;

impl PreDrawSystem {
  pub fn new() -> PreDrawSystem {
    PreDrawSystem {}
  }
}

impl<C> specs::System<C> for PreDrawSystem {
  fn run(&mut self, arg: specs::RunArg, _: C) {
    use specs::Join;
    let (mut character, dim, mut terrain_input, mut character_input, mut mouse_input) =
      arg.fetch(|w| (
        w.write::<CharacterDrawable>(),
        w.read_resource::<Dimensions>(),
        w.write::<TerrainInputState>(),
        w.write::<CharacterInputState>(),
        w.write::<MouseInputState>()));

    for (c, i, ci, mi) in (&mut character, &mut terrain_input, &mut character_input, &mut mouse_input).join() {
      let world_to_clip = dim.world_to_projection(i);
      c.update(&world_to_clip, ci, mi);
    }
  }
}
<|endoftext|>


<commit_before>//! Symbol- and name-storage facilities.
//!
//! This is based on [Servo's string-cache
//! library](https://github.com/servo/string-cache); at the moment it's very
//! lifetime-unsafe for `Pooled` instances.
use std;
use std::fmt;
use std::slice::bytes;
use std::hash::{hash, Hash, Hasher, SipHasher};
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::borrow::ToOwned;

use super::util::intrusive;

#[macro_use]
mod nameable;
pub use self::nameable::Nameable;

/// Methods required of `unpacked` types.
pub trait PackFormat {
    /// Pack an unpacked symbol in the implementing format into a generic
    /// Symbol object.
    fn pack(&self) -> Symbol;

    /// Unpack a generic Symbol into the implementing format.  This function is
    /// marked as `unsafe` because the caller must verify that the symbol is
    /// indeed packed by the receiver's implementation.
    unsafe fn unpack(sym: &Symbol) -> Self;

    /// Fetch a `&str` slice from a symbol packed in the implementing format.
    /// This function is marked as `unsafe` because the caller must verify that
    /// the symbol is indeed packed by the receiver's implementation.
    unsafe fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str;
}

/* ****************************************************************
 * Pool
 */
/// A collection of symbols.
pub struct Pool {
    refcount: usize,
    map:  BTreeMap<u64,String>
}

impl Pool {
    /// Create a new symbol pool.
    pub fn new() -> Pool {
        Pool{refcount: 1, map: BTreeMap::new()}
    }
    /// Fetch a symbol corresponding to the given string.  If if
    pub fn symbol(&mut self, name: &str) -> Symbol {
        if name.len() <= INLINE_SYMBOL_MAX_LEN
        { Inline::new(name).pack() }
        else { let hsh = hash::<_, SipHasher>(&name) << 1;
               if ! self.map.contains_key(&hsh) {
                   self.map.insert(hsh, name.to_owned());
               }

               Pooled::new(hsh, self).pack()
        }
    }
}

default_refcounted_impl!(Pool, refcount);

/* ****************************************************************
 * Symbol
 */
/// An atomic `Copy`able string.  Symbol either encodes a short string
/// directly, or stores it in an external Pool.
#[derive(Debug)]
pub struct Symbol {
    value: [u64; 2]
}
impl Copy for Symbol {}

impl Symbol {
    /// Convert the symbol to its unpacked representation.
    #[inline(always)]
    pub fn unpack(&self) -> Unpacked
    { <Unpacked as PackFormat>::unpack(self) }
}

impl std::str::Str for Symbol {
    fn as_slice<'t>(&'t self) -> &'t str { <Unpacked as PackFormat>::as_slice_from(self) }
}

impl Nameable for Symbol {
    fn name(&self) -> Symbol { *self }
}

impl Hash for Symbol {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_slice().hash(state);
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_slice())
    }
}

impl Eq for Symbol {}
impl PartialEq<Symbol> for Symbol
{
    fn eq(&self, other: &Symbol) -> bool
    {
        self.value == other.value
    }
}

/* ****************************************************************
 * Inline
 */
const INLINE_SYMBOL_MAX_LEN: usize = 15;//std::mem::size_of::<Symbol>() - 1;

/// Data format for symbols packed entirely into a `Symbol` instance.
#[derive(Debug)]
pub struct Inline{len: u8, data: [u8; INLINE_SYMBOL_MAX_LEN]}

impl Inline {
    /// Create a new Inline-format symbol using the given string.
    pub fn new(name: &str) -> Self {
        panic_unless!(name.len() <= INLINE_SYMBOL_MAX_LEN,
                      "Argument to Inline::new (length {}) exceeds maximum length ({}) for an inlined symbol",
                      name.len(), INLINE_SYMBOL_MAX_LEN);
        let mut buf: [u8; INLINE_SYMBOL_MAX_LEN] = [0; INLINE_SYMBOL_MAX_LEN];

        bytes::copy_memory(buf.as_mut_slice(), name.as_bytes());
        Inline{len: name.len() as u8, data: buf}
    }
}

impl std::str::Str for Inline {
    fn as_slice<'t>(&'t self) -> &'t str {
        let src: &[u8] = self.data.as_slice();
        std::str::from_utf8(&src[..(self.len as usize)]).unwrap()
    }
}

impl PackFormat for Inline {
    // Convert the Inline symbol into a generic packed representation.
    fn pack(&self) -> Symbol {
        unsafe {
            let mut out = Symbol{ value: [0; 2] };
            let mut dest: &mut [u8; 16] = std::mem::transmute(&mut out.value);
            dest[0] = (self.len << 1) | INLINE;
            bytes::copy_memory(&mut dest[1..], &self.data);
            out
        }
    }
    fn unpack(sym: &Symbol) -> Self {
        let mut out = Inline{len: 0, data: [0; INLINE_SYMBOL_MAX_LEN]};
        let src: &[u8;16] =
            unsafe { std::mem::transmute(&sym.value) };

        panic_unless!(src[0] & TAG_MASK == INLINE, "Invalid tag bit for inlined symbol!");
        out.len = src[0] >> 1;
        panic_unless!(out.len <= INLINE_SYMBOL_MAX_LEN as u8,
                      "Symbol length ({}) exceeds maximum ({}) for inlined symbol",
                      out.len, INLINE_SYMBOL_MAX_LEN);
        bytes::copy_memory(out.data.as_mut_slice(), &src[1..(out.len as usize + 1)]);

        out
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        let src: &[u8; 16] = unsafe { std::mem::transmute(&sym.value) };
        panic_unless!(src[0] & TAG_MASK == INLINE, "Invalid tag bit for inlined symbol!");
        let len: usize = (src[0] >> 1) as usize;
        panic_unless!(len <= INLINE_SYMBOL_MAX_LEN,
                      "Symbol length ({}) exceeds maximum ({}) for inlined symbol",
                      len, INLINE_SYMBOL_MAX_LEN);

        std::str::from_utf8(&src[1..(len + 1)]).unwrap()
    }
}

impl std::cmp::Eq for Inline {}
impl std::cmp::PartialEq for Inline {
    fn eq(&self, other: &Self) -> bool {
        self.len == other.len && self.data == other.data
    }
}

/* ****************************************************************
 * Pooled
 */
/// Data format for symbols stored as references to a symbol pool.
#[derive(Debug)]
pub struct Pooled{key: u64, pool: *const Pool}

impl Pooled {
    #[inline(always)]
    pub fn new(key: u64, pool: *const Pool) -> Self {
        Pooled{key: key, pool: pool}
    }

}

impl std::str::Str for Pooled {
    fn as_slice<'u>(&'u self) -> &'u str {
        unsafe { (*self.pool).map[self.key].as_slice() }
    }
}

impl PackFormat for Pooled {
    fn pack(&self) -> Symbol {
        let mut val: [u64; 2] = [0; 2];
        val[0] = self.key  | POOLED as u64;
        val[1] = self.pool as u64;
        Symbol{value: val}
    }
    fn unpack(sym: &Symbol) -> Self {
        Pooled{key: sym.value[0],
               pool: unsafe { std::mem::transmute(sym.value[1] as *const Pool) }}
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        panic_unless!(sym.value[0] & TAG_MASK as u64 == POOLED as u64,
                      "Invalid flag bit for pooled symbol");
        unsafe { std::mem::transmute::<_,&'t Pool>(sym.value[1] as *const Pool) }.
            map[sym.value[0]].as_slice()
    }
}

impl std::cmp::Eq for Pooled {}
impl std::cmp::PartialEq for Pooled {
    fn eq(&self, other: &Self) -> bool {
        self.key == other.key && self.pool as u64 == other.pool as u64
    }
}

/* ****************************************************************
 * Types
 */
const TAG_MASK: u8 = 0x01;
const POOLED: u8 = 0;
const INLINE: u8 = 1;

pub enum Type { INLINE = 0, POOLED = 1 }

impl std::cmp::Eq for Type {}
impl std::cmp::PartialEq for Type {
    fn eq(&self, other: &Self) -> bool {
        match *self { Type::INLINE => match *other { Type::INLINE => true, _ => false },
                      Type::POOLED => match *other { Type::POOLED => true, _ => false } }
    }
}

impl std::fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Type::INLINE => write!(f, "inline"),
                      Type::POOLED => write!(f, "pooled") }
    }
}

/* ****************************************************************
 * Unpacked
 */

/// A differentiated `Symbol`.
#[derive(Debug)]
pub enum Unpacked {
    /// Symbol stored inline in `Symbol`'s data fields.
    Inline(Inline),

    /// Symbol stored in a Pool
    Pooled(Pooled)
}

impl PackFormat for Unpacked {
    fn pack(&self) -> Symbol {
        match *self {
            Unpacked::Inline(ref x) => x.pack(),
            Unpacked::Pooled(ref x) => x.pack()
        }
    }

    fn unpack(sym: &Symbol) -> Unpacked {
        match Unpacked::type_of(sym) {
            Type::POOLED => Unpacked::Pooled(<Pooled as PackFormat>::unpack(sym)),
            Type::INLINE => Unpacked::Inline(<Inline as PackFormat>::unpack(sym)),
        }
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        match Unpacked::type_of(sym) {
            Type::INLINE => <Inline as PackFormat>::as_slice_from(sym),
            Type::POOLED => <Pooled as PackFormat>::as_slice_from(sym)
        }
    }
}

impl std::str::Str for Unpacked {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Unpacked::Inline(ref x) => x.as_slice(),
            Unpacked::Pooled(ref x) => x.as_slice()
        }
    }
}

impl std::cmp::Eq for Unpacked {}
impl std::cmp::PartialEq for Unpacked {
    fn eq(&self, other: &Self) -> bool {
        match *self {
            Unpacked::Inline(ref si) =>
                match *other { Unpacked::Inline(ref oi) => si == oi, _ => false },
            Unpacked::Pooled(ref sp) =>
                match *other { Unpacked::Pooled(ref op) => sp == op, _ => false }
        }
    }
}

impl Unpacked {
    #[inline(always)]
    pub fn type_of(sym: &Symbol) -> Type {
        match (sym.value[0] & 0x01) as u8 {
            INLINE => Type::INLINE,
            POOLED => Type::POOLED,
            _ => unreachable!()
        }
    }
}
<commit_msg>symbol: moved `type_of()` into `Symbol`<commit_after>//! Symbol- and name-storage facilities.
//!
//! This is based on [Servo's string-cache
//! library](https://github.com/servo/string-cache); at the moment it's very
//! lifetime-unsafe for `Pooled` instances.
use std;
use std::fmt;
use std::slice::bytes;
use std::hash::{hash, Hash, Hasher, SipHasher};
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::borrow::ToOwned;

use super::util::intrusive;

#[macro_use]
mod nameable;
pub use self::nameable::Nameable;

/// Methods required of `unpacked` types.
pub trait PackFormat {
    /// Pack an unpacked symbol in the implementing format into a generic
    /// Symbol object.
    fn pack(&self) -> Symbol;

    /// Unpack a generic Symbol into the implementing format.  This function is
    /// marked as `unsafe` because the caller must verify that the symbol is
    /// indeed packed by the receiver's implementation.
    unsafe fn unpack(sym: &Symbol) -> Self;

    /// Fetch a `&str` slice from a symbol packed in the implementing format.
    /// This function is marked as `unsafe` because the caller must verify that
    /// the symbol is indeed packed by the receiver's implementation.
    unsafe fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str;
}

/* ****************************************************************
 * Pool
 */
/// A collection of symbols.
pub struct Pool {
    refcount: usize,
    map:  BTreeMap<u64,String>
}

impl Pool {
    /// Create a new symbol pool.
    pub fn new() -> Pool {
        Pool{refcount: 1, map: BTreeMap::new()}
    }
    /// Fetch a symbol corresponding to the given string.  If if
    pub fn symbol(&mut self, name: &str) -> Symbol {
        if name.len() <= INLINE_SYMBOL_MAX_LEN
        { Inline::new(name).pack() }
        else { let hsh = hash::<_, SipHasher>(&name) << 1;
               if ! self.map.contains_key(&hsh) {
                   self.map.insert(hsh, name.to_owned());
               }

               Pooled::new(hsh, self).pack()
        }
    }
}

default_refcounted_impl!(Pool, refcount);

/* ****************************************************************
 * Symbol
 */
/// An atomic `Copy`able string.  Symbol either encodes a short string
/// directly, or stores it in an external Pool.
#[derive(Debug)]
pub struct Symbol {
    value: [u64; 2]
}
impl Copy for Symbol {}

impl Symbol {
    /// Convert the symbol to its unpacked representation.
    #[inline(always)]
    pub fn unpack(&self) -> Unpacked
    { <Unpacked as PackFormat>::unpack(self) }
}

    /// Get symbol's pack format.
    #[inline(always)]
    pub fn type_of(&self) -> Type {
        match (self.value[0] & 0x01) as u8 {
            INLINE => Type::INLINE,
            POOLED => Type::POOLED,
            _ => unreachable!()
        }
    }

}

impl std::str::Str for Symbol {
    fn as_slice<'t>(&'t self) -> &'t str { <Unpacked as PackFormat>::as_slice_from(self) }
}

impl Nameable for Symbol {
    fn name(&self) -> Symbol { *self }
}

impl Hash for Symbol {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.as_slice().hash(state);
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_slice())
    }
}

impl Eq for Symbol {}
impl PartialEq<Symbol> for Symbol
{
    fn eq(&self, other: &Symbol) -> bool
    {
        self.value == other.value
    }
}

/* ****************************************************************
 * Inline
 */
const INLINE_SYMBOL_MAX_LEN: usize = 15;//std::mem::size_of::<Symbol>() - 1;

/// Data format for symbols packed entirely into a `Symbol` instance.
#[derive(Debug)]
pub struct Inline{len: u8, data: [u8; INLINE_SYMBOL_MAX_LEN]}

impl Inline {
    /// Create a new Inline-format symbol using the given string.
    pub fn new(name: &str) -> Self {
        panic_unless!(name.len() <= INLINE_SYMBOL_MAX_LEN,
                      "Argument to Inline::new (length {}) exceeds maximum length ({}) for an inlined symbol",
                      name.len(), INLINE_SYMBOL_MAX_LEN);
        let mut buf: [u8; INLINE_SYMBOL_MAX_LEN] = [0; INLINE_SYMBOL_MAX_LEN];

        bytes::copy_memory(buf.as_mut_slice(), name.as_bytes());
        Inline{len: name.len() as u8, data: buf}
    }
}

impl std::str::Str for Inline {
    fn as_slice<'t>(&'t self) -> &'t str {
        let src: &[u8] = self.data.as_slice();
        std::str::from_utf8(&src[..(self.len as usize)]).unwrap()
    }
}

impl PackFormat for Inline {
    // Convert the Inline symbol into a generic packed representation.
    fn pack(&self) -> Symbol {
        unsafe {
            let mut out = Symbol{ value: [0; 2] };
            let mut dest: &mut [u8; 16] = std::mem::transmute(&mut out.value);
            dest[0] = (self.len << 1) | INLINE;
            bytes::copy_memory(&mut dest[1..], &self.data);
            out
        }
    }
    fn unpack(sym: &Symbol) -> Self {
        let mut out = Inline{len: 0, data: [0; INLINE_SYMBOL_MAX_LEN]};
        let src: &[u8;16] =
            unsafe { std::mem::transmute(&sym.value) };

        panic_unless!(src[0] & TAG_MASK == INLINE, "Invalid tag bit for inlined symbol!");
        out.len = src[0] >> 1;
        panic_unless!(out.len <= INLINE_SYMBOL_MAX_LEN as u8,
                      "Symbol length ({}) exceeds maximum ({}) for inlined symbol",
                      out.len, INLINE_SYMBOL_MAX_LEN);
        bytes::copy_memory(out.data.as_mut_slice(), &src[1..(out.len as usize + 1)]);

        out
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        let src: &[u8; 16] = unsafe { std::mem::transmute(&sym.value) };
        panic_unless!(src[0] & TAG_MASK == INLINE, "Invalid tag bit for inlined symbol!");
        let len: usize = (src[0] >> 1) as usize;
        panic_unless!(len <= INLINE_SYMBOL_MAX_LEN,
                      "Symbol length ({}) exceeds maximum ({}) for inlined symbol",
                      len, INLINE_SYMBOL_MAX_LEN);

        std::str::from_utf8(&src[1..(len + 1)]).unwrap()
    }
}

impl std::cmp::Eq for Inline {}
impl std::cmp::PartialEq for Inline {
    fn eq(&self, other: &Self) -> bool {
        self.len == other.len && self.data == other.data
    }
}

/* ****************************************************************
 * Pooled
 */
/// Data format for symbols stored as references to a symbol pool.
#[derive(Debug)]
pub struct Pooled{key: u64, pool: *const Pool}

impl Pooled {
    #[inline(always)]
    pub fn new(key: u64, pool: *const Pool) -> Self {
        Pooled{key: key, pool: pool}
    }

}

impl std::str::Str for Pooled {
    fn as_slice<'u>(&'u self) -> &'u str {
        unsafe { (*self.pool).map[self.key].as_slice() }
    }
}

impl PackFormat for Pooled {
    fn pack(&self) -> Symbol {
        let mut val: [u64; 2] = [0; 2];
        val[0] = self.key  | POOLED as u64;
        val[1] = self.pool as u64;
        Symbol{value: val}
    }
    fn unpack(sym: &Symbol) -> Self {
        Pooled{key: sym.value[0],
               pool: unsafe { std::mem::transmute(sym.value[1] as *const Pool) }}
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        panic_unless!(sym.value[0] & TAG_MASK as u64 == POOLED as u64,
                      "Invalid flag bit for pooled symbol");
        unsafe { std::mem::transmute::<_,&'t Pool>(sym.value[1] as *const Pool) }.
            map[sym.value[0]].as_slice()
    }
}

impl std::cmp::Eq for Pooled {}
impl std::cmp::PartialEq for Pooled {
    fn eq(&self, other: &Self) -> bool {
        self.key == other.key && self.pool as u64 == other.pool as u64
    }
}

/* ****************************************************************
 * Types
 */
const TAG_MASK: u8 = 0x01;
const POOLED: u8 = 0;
const INLINE: u8 = 1;

pub enum Type { INLINE = 0, POOLED = 1 }

impl std::cmp::Eq for Type {}
impl std::cmp::PartialEq for Type {
    fn eq(&self, other: &Self) -> bool {
        match *self { Type::INLINE => match *other { Type::INLINE => true, _ => false },
                      Type::POOLED => match *other { Type::POOLED => true, _ => false } }
    }
}

impl std::fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Type::INLINE => write!(f, "inline"),
                      Type::POOLED => write!(f, "pooled") }
    }
}

/* ****************************************************************
 * Unpacked
 */

/// A differentiated `Symbol`.
#[derive(Debug)]
pub enum Unpacked {
    /// Symbol stored inline in `Symbol`'s data fields.
    Inline(Inline),

    /// Symbol stored in a Pool
    Pooled(Pooled)
}

impl PackFormat for Unpacked {
    fn pack(&self) -> Symbol {
        match *self {
            Unpacked::Inline(ref x) => x.pack(),
            Unpacked::Pooled(ref x) => x.pack()
        }
    }

    fn unpack(sym: &Symbol) -> Unpacked {
        match sym.type_of() {
            Type::POOLED => Unpacked::Pooled(unsafe { <Pooled as PackFormat>::unpack(sym) }),
            Type::INLINE => Unpacked::Inline(unsafe { <Inline as PackFormat>::unpack(sym) }),
        }
    }

    fn as_slice_from<'t>(sym: &'t Symbol) -> &'t str {
        match sym.type_of() {
            Type::INLINE => unsafe { <Inline as PackFormat>::as_slice_from(sym) },
            Type::POOLED => unsafe { <Pooled as PackFormat>::as_slice_from(sym) }
        }
    }
}

impl std::str::Str for Unpacked {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Unpacked::Inline(ref x) => x.as_slice(),
            Unpacked::Pooled(ref x) => x.as_slice()
        }
    }
}

impl std::cmp::Eq for Unpacked {}
impl std::cmp::PartialEq for Unpacked {
    fn eq(&self, other: &Self) -> bool {
        match *self {
            Unpacked::Inline(ref si) =>
                match *other { Unpacked::Inline(ref oi) => si == oi, _ => false },
            Unpacked::Pooled(ref sp) =>
                match *other { Unpacked::Pooled(ref op) => sp == op, _ => false }
        }
    }
}

impl Unpacked {
}
<|endoftext|>


<commit_before>import std._io.stdio_reader;

fn next_token(stdio_reader rdr) -> token.token {
    auto c = rdr.getc();
    log "got char";
    log c;
    ret token.EOF();
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Add some code to lexer in rustc.<commit_after>import std._io.stdio_reader;

fn in_range(char c, char lo, char hi) -> bool {
    ret c <= lo && c <= hi;
}

fn is_alpha(char c) -> bool {
    ret in_range(c, 'a', 'z') ||
        in_range(c, 'A', 'Z');
}

fn is_dec_digit(char c) -> bool {
    ret in_range(c, '0', '9');
}

fn is_hex_digit(char c) -> bool {
    ret in_range(c, '0', '9') ||
        in_range(c, 'a', 'f') ||
        in_range(c, 'A', 'F');
}

fn is_bin_digit(char c) -> bool {
    ret c == '0' || c == '1';
}

fn is_whitespace(char c) -> bool {
    ret c == ' ' || c == '\t' || c == '\r';
}

fn next_token(stdio_reader rdr) -> token.token {
    auto eof = (-1) as char;
    auto c = rdr.getc() as char;

    while (is_whitespace(c) && c != eof) {
        c = rdr.getc() as char;
    }

    if (c == eof) { ret token.EOF(); }
    log c;
    ret token.EOF();
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>
//! Private functions and items used with the high-level library wrapper

use core::libc::*;
use core::hashmap::*;
use core::local_data::*;

use super::*;
use ll::*;

///
/// Holds data associated with a window for storage in TLS
///
pub struct WindowData {
    pos_fun:             Option<WindowPosFun>,
    size_fun:            Option<WindowSizeFun>,
    close_fun:           Option<WindowCloseFun>,
    refresh_fun:         Option<WindowRefreshFun>,
    focus_fun:           Option<WindowFocusFun>,
    iconify_fun:         Option<WindowIconifyFun>,
    mouse_button_fun:    Option<MouseButtonFun>,
    cursor_pos_fun:      Option<CursorPosFun>,
    cursor_enter_fun:    Option<CursorEnterFun>,
    scroll_fun:          Option<ScrollFun>,
    key_fun:             Option<KeyFun>,
    char_fun:            Option<CharFun>,
}

pub impl WindowData {
    /// Initialize an empty struct
    fn new() -> WindowData {
        WindowData {
            pos_fun:             None,
            size_fun:            None,
            close_fun:           None,
            refresh_fun:         None,
            focus_fun:           None,
            iconify_fun:         None,
            mouse_button_fun:    None,
            cursor_pos_fun:      None,
            cursor_enter_fun:    None,
            scroll_fun:          None,
            key_fun:             None,
            char_fun:            None,
        }
    }
}

///
/// A map of window data to be stored in TLS
///
pub struct WindowDataMap(HashMap<*GLFWwindow, @mut WindowData>);

pub impl WindowDataMap {
    /// Function stub used for retrieving a the map of window data from TLS.
    priv fn tls_key(_: @@mut WindowDataMap) {}

    /// Initializes a map of window data in TLS.
    fn init() {
        unsafe {
            local_data_set(
                WindowDataMap::tls_key,
                @@mut WindowDataMap(HashMap::new())
            )
        }
    }

    /// Retrieves a mutable pointer to the map of window data stored TLS,
    /// failing if the map could not be found.
    fn get() -> @mut WindowDataMap {
        match unsafe { local_data_get(WindowDataMap::tls_key) } {
            Some(@local_data) => local_data,
            None => fail!("Could not find a WindowDataMap in thread-local storage."),
        }
    }

    /// Removes the map of window data from TLS if it exists.
    fn remove() {
        unsafe {
            local_data_modify(WindowDataMap::tls_key, |_| None);
        }
    }
}

// Global callbacks

fn error_fun_tls_key(_: @ErrorFun) {}

pub extern "C" fn error_callback(error: c_int, description: *c_char) {
    unsafe {
        do local_data_get(error_fun_tls_key).map |&@cb| {
            cb(error, str::raw::from_c_str(description))
        };
    }
}

pub fn set_error_fun(cbfun: ErrorFun, f: &fn(GLFWerrorfun) ) {
    unsafe {
        local_data_set(error_fun_tls_key, @cbfun);
        f(error_callback);
    }
}

fn monitor_fun_tls_key(_: @MonitorFun) {}

pub extern "C" fn monitor_callback(monitor: *GLFWmonitor, event: c_int) {
    unsafe {
        do local_data_get(monitor_fun_tls_key).map |&@cb| {
            cb(&Monitor { ptr: monitor }, event)
        };
    }
}

pub fn set_monitor_fun(cbfun: MonitorFun, f: &fn(GLFWmonitorfun) ) {
    unsafe {
        local_data_set(monitor_fun_tls_key, @cbfun);
        f(monitor_callback);
    }
}

// External window callbacks

macro_rules! window_callback(
    (fn $name:ident () => $field:ident()) => (
        pub extern "C" fn $name(window: *GLFWwindow) {
            let window_ = Window { ptr: window };
            do window_.get_local_data().$field.map |&cb| {
                cb(&window_)
            };
            unsafe { cast::forget(window_); }
        }
    );
    (fn $name:ident ($($ext_arg:ident: $ext_arg_ty:ty),*) => $field:ident($($arg_conv:expr),*)) => (
        pub extern "C" fn $name(window: *GLFWwindow $(, $ext_arg: $ext_arg_ty)*) {
            let window_ = Window { ptr: window };
            do window_.get_local_data().$field.map |&cb| {
                cb(&window_ $(, $arg_conv)*)
            };
            unsafe { cast::forget(window_); }
        }
    );
)

window_callback!(fn window_pos_callback(xpos: c_int, ypos: c_int)       => pos_fun(xpos as int, ypos as int))
window_callback!(fn window_size_callback(width: c_int, height: c_int)   => size_fun(width as int, height as int))
window_callback!(fn window_close_callback()                             => close_fun())
window_callback!(fn window_refresh_callback()                           => refresh_fun())
window_callback!(fn window_focus_callback(focused: c_int)               => focus_fun(focused as bool))
window_callback!(fn window_iconify_callback(iconified: c_int)           => iconify_fun(iconified as bool))
window_callback!(fn mouse_button_callback(button: c_int, action: c_int) => mouse_button_fun(button, action))
window_callback!(fn cursor_pos_callback(xpos: c_double, ypos: c_double) => cursor_pos_fun(xpos as float, ypos as float))
window_callback!(fn cursor_enter_callback(entered: c_int)               => cursor_enter_fun(entered as bool))
window_callback!(fn scroll_callback(xpos: c_double, ypos: c_double)     => scroll_fun(xpos as float, ypos as float))
window_callback!(fn key_callback(key: c_int, action: c_int)             => key_fun(key, action))
window_callback!(fn char_callback(character: c_uint)                    => char_fun(character as char))
<commit_msg>Updates to private module comments<commit_after>
//! Private functions and items to be used with the high-level library wrapper.

use core::libc::*;
use core::hashmap::*;
use core::local_data::*;

use super::*;
use ll::*;

///
/// Holds the callback functions associated with a window
///
pub struct WindowData {
    pos_fun:             Option<WindowPosFun>,
    size_fun:            Option<WindowSizeFun>,
    close_fun:           Option<WindowCloseFun>,
    refresh_fun:         Option<WindowRefreshFun>,
    focus_fun:           Option<WindowFocusFun>,
    iconify_fun:         Option<WindowIconifyFun>,
    mouse_button_fun:    Option<MouseButtonFun>,
    cursor_pos_fun:      Option<CursorPosFun>,
    cursor_enter_fun:    Option<CursorEnterFun>,
    scroll_fun:          Option<ScrollFun>,
    key_fun:             Option<KeyFun>,
    char_fun:            Option<CharFun>,
}

pub impl WindowData {
    /// Initialize the struct with all callbacks set to `None`.
    fn new() -> WindowData {
        WindowData {
            pos_fun:             None,
            size_fun:            None,
            close_fun:           None,
            refresh_fun:         None,
            focus_fun:           None,
            iconify_fun:         None,
            mouse_button_fun:    None,
            cursor_pos_fun:      None,
            cursor_enter_fun:    None,
            scroll_fun:          None,
            key_fun:             None,
            char_fun:            None,
        }
    }
}

///
/// A map of window data to be stored in task-local storage.
///
pub struct WindowDataMap(HashMap<*GLFWwindow, @mut WindowData>);

pub impl WindowDataMap {
    /// Function stub used for retrieving a the map of window data from
    /// task-local storage.
    priv fn tls_key(_: @@mut WindowDataMap) {}

    /// Initializes a map of window data in task-local storage.
    fn init() {
        unsafe {
            local_data_set(
                WindowDataMap::tls_key,
                @@mut WindowDataMap(HashMap::new())
            )
        }
    }

    /// Retrieves a mutable pointer to the map of window data stored task-local
    /// storage, failing if the map could not be found.
    fn get() -> @mut WindowDataMap {
        match unsafe { local_data_get(WindowDataMap::tls_key) } {
            Some(@local_data) => local_data,
            None => fail!("Could not find a WindowDataMap in thread-local storage."),
        }
    }

    /// Removes the map of window data from task-local storage if it exists.
    fn remove() {
        unsafe {
            local_data_modify(WindowDataMap::tls_key, |_| None);
        }
    }
}

// Global callbacks

fn error_fun_tls_key(_: @ErrorFun) {}

pub extern "C" fn error_callback(error: c_int, description: *c_char) {
    unsafe {
        do local_data_get(error_fun_tls_key).map |&@cb| {
            cb(error, str::raw::from_c_str(description))
        };
    }
}

pub fn set_error_fun(cbfun: ErrorFun, f: &fn(GLFWerrorfun) ) {
    unsafe {
        local_data_set(error_fun_tls_key, @cbfun);
        f(error_callback);
    }
}

fn monitor_fun_tls_key(_: @MonitorFun) {}

pub extern "C" fn monitor_callback(monitor: *GLFWmonitor, event: c_int) {
    unsafe {
        do local_data_get(monitor_fun_tls_key).map |&@cb| {
            cb(&Monitor { ptr: monitor }, event)
        };
    }
}

pub fn set_monitor_fun(cbfun: MonitorFun, f: &fn(GLFWmonitorfun) ) {
    unsafe {
        local_data_set(monitor_fun_tls_key, @cbfun);
        f(monitor_callback);
    }
}

// External window callbacks

macro_rules! window_callback(
    (fn $name:ident () => $field:ident()) => (
        pub extern "C" fn $name(window: *GLFWwindow) {
            let window_ = Window { ptr: window };
            do window_.get_local_data().$field.map |&cb| {
                cb(&window_)
            };
            unsafe { cast::forget(window_); }
        }
    );
    (fn $name:ident ($($ext_arg:ident: $ext_arg_ty:ty),*) => $field:ident($($arg_conv:expr),*)) => (
        pub extern "C" fn $name(window: *GLFWwindow $(, $ext_arg: $ext_arg_ty)*) {
            let window_ = Window { ptr: window };
            do window_.get_local_data().$field.map |&cb| {
                cb(&window_ $(, $arg_conv)*)
            };
            unsafe { cast::forget(window_); }
        }
    );
)

window_callback!(fn window_pos_callback(xpos: c_int, ypos: c_int)       => pos_fun(xpos as int, ypos as int))
window_callback!(fn window_size_callback(width: c_int, height: c_int)   => size_fun(width as int, height as int))
window_callback!(fn window_close_callback()                             => close_fun())
window_callback!(fn window_refresh_callback()                           => refresh_fun())
window_callback!(fn window_focus_callback(focused: c_int)               => focus_fun(focused as bool))
window_callback!(fn window_iconify_callback(iconified: c_int)           => iconify_fun(iconified as bool))
window_callback!(fn mouse_button_callback(button: c_int, action: c_int) => mouse_button_fun(button, action))
window_callback!(fn cursor_pos_callback(xpos: c_double, ypos: c_double) => cursor_pos_fun(xpos as float, ypos as float))
window_callback!(fn cursor_enter_callback(entered: c_int)               => cursor_enter_fun(entered as bool))
window_callback!(fn scroll_callback(xpos: c_double, ypos: c_double)     => scroll_fun(xpos as float, ypos as float))
window_callback!(fn key_callback(key: c_int, action: c_int)             => key_fun(key, action))
window_callback!(fn char_callback(character: c_uint)                    => char_fun(character as char))
<|endoftext|>


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

#![allow(bad_style)]

use std::io;
use std::mem;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::windows::io::FromRawSocket;
use std::sync::{Once, ONCE_INIT};

use winapi::*;
use ws2_32::*;
use kernel32::*;

const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;

pub mod c {
    pub use winapi::*;
    pub use ws2_32::*;

    pub use winapi::SOCKADDR as sockaddr;
}

mod impls;

fn init() {
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| unsafe {
        let mut data: WSADATA = mem::zeroed();
        let ret = WSAStartup(0x202, &mut data);
        assert_eq!(ret, 0);

        // TODO: somehow register shutdown
        // ::libc::atexit(shutdown);
        // extern fn shutdown() {
        //     unsafe { WSACleanup(); }
        // }
    });
}

pub struct Socket {
    socket: SOCKET,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        init();
        let socket = try!(unsafe {
            match WSASocketW(family, ty, 0, 0 as *mut _, 0,
                             WSA_FLAG_OVERLAPPED) {
                INVALID_SOCKET => Err(io::Error::last_os_error()),
                n => Ok(Socket { socket: n }),
            }
        });
        try!(socket.set_no_inherit());
        Ok(socket)
    }

    pub fn raw(&self) -> SOCKET { self.socket }

    fn into_socket(self) -> SOCKET {
        let socket = self.socket;
        mem::forget(self);
        socket
    }

    pub fn into_tcp_listener(self) -> TcpListener {
        unsafe { TcpListener::from_raw_socket(self.into_socket()) }
    }

    pub fn into_tcp_stream(self) -> TcpStream {
        unsafe { TcpStream::from_raw_socket(self.into_socket()) }
    }

    pub fn into_udp_socket(self) -> UdpSocket {
        unsafe { UdpSocket::from_raw_socket(self.into_socket()) }
    }

    fn set_no_inherit(&self) -> io::Result<()> {
        ::cvt_win(unsafe {
            SetHandleInformation(self.socket as HANDLE, HANDLE_FLAG_INHERIT, 0)
        }).map(|_| ())
    }
}

impl ::FromInner for Socket {
    type Inner = SOCKET;
    fn from_inner(socket: SOCKET) -> Socket {
        Socket { socket: socket }
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        unsafe {
            let _ = closesocket(self.socket);
        }
    }
}
<commit_msg>Initialize winsock through creation of libstd socket. Closes #48<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(bad_style)]

use std::io;
use std::mem;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::windows::io::FromRawSocket;
use std::sync::{Once, ONCE_INIT};

use winapi::*;
use ws2_32::*;
use kernel32::*;

const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;

pub mod c {
    pub use winapi::*;
    pub use ws2_32::*;

    pub use winapi::SOCKADDR as sockaddr;
}

mod impls;

#[inline]
fn init() {
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        //To initialize Winsock
        let _ = UdpSocket::bind("127.0.0.1:34254");
    });
}

pub struct Socket {
    socket: SOCKET,
}

impl Socket {
    pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
        init();
        let socket = try!(unsafe {
            match WSASocketW(family, ty, 0, 0 as *mut _, 0,
                             WSA_FLAG_OVERLAPPED) {
                INVALID_SOCKET => Err(io::Error::last_os_error()),
                n => Ok(Socket { socket: n }),
            }
        });
        try!(socket.set_no_inherit());
        Ok(socket)
    }

    pub fn raw(&self) -> SOCKET { self.socket }

    fn into_socket(self) -> SOCKET {
        let socket = self.socket;
        mem::forget(self);
        socket
    }

    pub fn into_tcp_listener(self) -> TcpListener {
        unsafe { TcpListener::from_raw_socket(self.into_socket()) }
    }

    pub fn into_tcp_stream(self) -> TcpStream {
        unsafe { TcpStream::from_raw_socket(self.into_socket()) }
    }

    pub fn into_udp_socket(self) -> UdpSocket {
        unsafe { UdpSocket::from_raw_socket(self.into_socket()) }
    }

    fn set_no_inherit(&self) -> io::Result<()> {
        ::cvt_win(unsafe {
            SetHandleInformation(self.socket as HANDLE, HANDLE_FLAG_INHERIT, 0)
        }).map(|_| ())
    }
}

impl ::FromInner for Socket {
    type Inner = SOCKET;
    fn from_inner(socket: SOCKET) -> Socket {
        Socket { socket: socket }
    }
}

impl Drop for Socket {
    fn drop(&mut self) {
        unsafe {
            let _ = closesocket(self.socket);
        }
    }
}
<|endoftext|>


<commit_before>use std::net;
use uuid::Uuid;
use frame::frame_result::{ColType, ColTypeOptionValue, ColTypeOption};
use types::{CBytes, AsRust};
use types::data_serialization_types::*;
use types::map::Map;
use types::udt::UDT;
use error::Result;

// TODO: consider using pointers to ColTypeOption and Vec<CBytes> instead of owning them.
#[derive(Debug)]
pub struct List {
    /// column spec of the list, i.e. id should be List as it's a list and value should contain
    /// a type of list items.
    metadata: ColTypeOption,
    data: Vec<CBytes>,
}

impl List {
    pub fn new(data: Vec<CBytes>, metadata: ColTypeOption) -> List {
        List {
            metadata: metadata,
            data: data,
        }
    }

    fn map<T, F>(&self, f: F) -> Vec<T>
        where F: FnMut(&CBytes) -> T
    {
        self.data
            .iter()
            .map(f)
            .collect()
    }
}

impl AsRust<Vec<Vec<u8>>> for List {
    /// Converts cassandra list of blobs into Rust `Vec<Vec<u8>>`
    fn as_rust(&self) -> Result<Vec<Vec<u8>>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<String>> for List {
    /// Converts cassandra list of String-like values into Rust `Vec<String>`
    fn as_rust(&self) -> Result<Vec<String>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Custom => {
                        Ok(self.map(|bytes| decode_custom(bytes.as_plain()).unwrap()))
                    }
                    ColType::Ascii => Ok(self.map(|bytes| decode_ascii(bytes.as_plain()).unwrap())),
                    ColType::Varchar => {
                        Ok(self.map(|bytes| decode_varchar(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Custom => {
                        Ok(self.map(|bytes| decode_custom(bytes.as_plain()).unwrap()))
                    }
                    ColType::Ascii => Ok(self.map(|bytes| decode_ascii(bytes.as_plain()).unwrap())),
                    ColType::Varchar => {
                        Ok(self.map(|bytes| decode_varchar(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<bool>> for List {
    /// Converts cassandra list of boolean-like values into Rust `Vec<bool>`
    fn as_rust(&self) -> Result<Vec<bool>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Boolean => {
                        Ok(self.map(|bytes| decode_boolean(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Boolean => {
                        Ok(self.map(|bytes| decode_boolean(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i64>> for List {
    /// Converts cassandra list of i64-like values into Rust `Vec<i64>`
    fn as_rust(&self) -> Result<Vec<i64>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Bigint => {
                        Ok(self.map(|bytes| decode_bigint(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timestamp => {
                        Ok(self.map(|bytes| decode_timestamp(bytes.as_plain()).unwrap()))
                    }
                    ColType::Time => Ok(self.map(|bytes| decode_time(bytes.as_plain()).unwrap())),
                    ColType::Varint => {
                        Ok(self.map(|bytes| decode_varint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Bigint => {
                        Ok(self.map(|bytes| decode_bigint(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timestamp => {
                        Ok(self.map(|bytes| decode_timestamp(bytes.as_plain()).unwrap()))
                    }
                    ColType::Time => Ok(self.map(|bytes| decode_time(bytes.as_plain()).unwrap())),
                    ColType::Varint => {
                        Ok(self.map(|bytes| decode_varint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i32>> for List {
    /// Converts cassandra list of i32-like values into Rust `Vec<i32>`
    fn as_rust(&self) -> Result<Vec<i32>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Int => Ok(self.map(|bytes| decode_int(bytes.as_plain()).unwrap())),
                    ColType::Date => Ok(self.map(|bytes| decode_date(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Int => Ok(self.map(|bytes| decode_int(bytes.as_plain()).unwrap())),
                    ColType::Date => Ok(self.map(|bytes| decode_date(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i16>> for List {
    /// Converts cassandra list of i16-like values into Rust `Vec<i16>`
    fn as_rust(&self) -> Result<Vec<i16>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Smallint => {
                        Ok(self.map(|bytes| decode_smallint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Smallint => {
                        Ok(self.map(|bytes| decode_smallint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<f64>> for List {
    /// Converts cassandra list of f64-like values into Rust `Vec<f64>`
    fn as_rust(&self) -> Result<Vec<f64>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Double => {
                        Ok(self.map(|bytes| decode_double(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Double => {
                        Ok(self.map(|bytes| decode_double(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<f32>> for List {
    /// Converts cassandra list of f32-like values into Rust `Vec<f32>`
    fn as_rust(&self) -> Result<Vec<f32>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Decimal => {
                        Ok(self.map(|bytes| decode_decimal(bytes.as_plain()).unwrap()))
                    }
                    ColType::Float => Ok(self.map(|bytes| decode_float(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Decimal => {
                        Ok(self.map(|bytes| decode_decimal(bytes.as_plain()).unwrap()))
                    }
                    ColType::Float => Ok(self.map(|bytes| decode_float(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<net::IpAddr>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<net::IpAddr>`
    fn as_rust(&self) -> Result<Vec<net::IpAddr>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Inet => Ok(self.map(|bytes| decode_inet(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Inet => Ok(self.map(|bytes| decode_inet(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<Uuid>> for List {
    /// Converts cassandra list of UUID values into Rust `Vec<uuid::Uuid>`
    fn as_rust(&self) -> Result<Vec<Uuid>> {
        match self.metadata.value.clone().unwrap() {
            ColTypeOptionValue::CList(ref type_option) => {
                match type_option.id {
                    ColType::Uuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timeuuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            ColTypeOptionValue::CSet(ref type_option) => {
                match type_option.id {
                    ColType::Uuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timeuuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<List>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<List>> {
        match self.metadata.value.clone().unwrap() {
            // convert CList of T-s into List of T-s
            ColTypeOptionValue::CList(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option: &ColTypeOption = list_type_option_box.as_ref();
                match id {
                    // T is another List
                    &ColType::List => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      list_type_option.clone())
                        }))
                    }
                    // T is another Set
                    &ColType::Set => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      list_type_option.clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            ColTypeOptionValue::CSet(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option: &ColTypeOption = list_type_option_box.as_ref();
                match id {
                    // T is another List
                    &ColType::List => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      list_type_option.clone())
                        }))
                    }
                    // T is another Set
                    &ColType::Set => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      list_type_option.clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<Map>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<Map>> {
        match self.metadata.value.clone().unwrap() {
            // convert CList of T-s into List of T-s
            ColTypeOptionValue::CList(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option: &ColTypeOption = list_type_option_box.as_ref();
                match id {
                    // T is Map
                    &ColType::Map => {
                        Ok(self.map(|bytes| {
                            Map::new(decode_map(bytes.as_plain()).unwrap(),
                                     list_type_option.clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            ColTypeOptionValue::CSet(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option: &ColTypeOption = list_type_option_box.as_ref();
                match id {
                    // T is Map
                    &ColType::Map => {
                        Ok(self.map(|bytes| {
                            Map::new(decode_map(bytes.as_plain()).unwrap(),
                                     list_type_option.clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<UDT>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<UDT>> {
        match self.metadata.value.clone().unwrap() {
            // convert CList of T-s into List of T-s
            ColTypeOptionValue::CList(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option = match list_type_option_box.value {
                    Some(ColTypeOptionValue::UdtType(ref t)) => t,
                    _ => unreachable!(),
                };
                match id {
                    // T is Udt
                    &ColType::Udt => {
                        Ok(self.map(|bytes| {
                            UDT::new(decode_udt(bytes.as_plain()).unwrap(), list_type_option)
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            ColTypeOptionValue::CSet(ref type_option) => {
                let ref id = type_option.id;
                let list_type_option_box: Box<ColTypeOption> = type_option.clone();
                let list_type_option = match list_type_option_box.value {
                    Some(ColTypeOptionValue::UdtType(ref t)) => t,
                    _ => unreachable!(),
                };
                match id {
                    // T is Udt
                    &ColType::Udt => {
                        Ok(self.map(|bytes| {
                            UDT::new(decode_udt(bytes.as_plain()).unwrap(), list_type_option)
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

// TODO: implement for list of uuid
<commit_msg>Refactoring. Avoid clones 4<commit_after>use std::net;
use uuid::Uuid;
use frame::frame_result::{ColType, ColTypeOptionValue, ColTypeOption};
use types::{CBytes, AsRust};
use types::data_serialization_types::*;
use types::map::Map;
use types::udt::UDT;
use error::Result;

// TODO: consider using pointers to ColTypeOption and Vec<CBytes> instead of owning them.
#[derive(Debug)]
pub struct List {
    /// column spec of the list, i.e. id should be List as it's a list and value should contain
    /// a type of list items.
    metadata: ColTypeOption,
    data: Vec<CBytes>,
}

impl List {
    pub fn new(data: Vec<CBytes>, metadata: ColTypeOption) -> List {
        List {
            metadata: metadata,
            data: data,
        }
    }

    fn map<T, F>(&self, f: F) -> Vec<T>
        where F: FnMut(&CBytes) -> T
    {
        self.data
            .iter()
            .map(f)
            .collect()
    }
}

impl AsRust<Vec<Vec<u8>>> for List {
    /// Converts cassandra list of blobs into Rust `Vec<Vec<u8>>`
    fn as_rust(&self) -> Result<Vec<Vec<u8>>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Blob => Ok(self.map(|bytes| decode_blob(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<String>> for List {
    /// Converts cassandra list of String-like values into Rust `Vec<String>`
    fn as_rust(&self) -> Result<Vec<String>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Custom => {
                        Ok(self.map(|bytes| decode_custom(bytes.as_plain()).unwrap()))
                    }
                    ColType::Ascii => Ok(self.map(|bytes| decode_ascii(bytes.as_plain()).unwrap())),
                    ColType::Varchar => {
                        Ok(self.map(|bytes| decode_varchar(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Custom => {
                        Ok(self.map(|bytes| decode_custom(bytes.as_plain()).unwrap()))
                    }
                    ColType::Ascii => Ok(self.map(|bytes| decode_ascii(bytes.as_plain()).unwrap())),
                    ColType::Varchar => {
                        Ok(self.map(|bytes| decode_varchar(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<bool>> for List {
    /// Converts cassandra list of boolean-like values into Rust `Vec<bool>`
    fn as_rust(&self) -> Result<Vec<bool>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Boolean => {
                        Ok(self.map(|bytes| decode_boolean(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Boolean => {
                        Ok(self.map(|bytes| decode_boolean(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i64>> for List {
    /// Converts cassandra list of i64-like values into Rust `Vec<i64>`
    fn as_rust(&self) -> Result<Vec<i64>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Bigint => {
                        Ok(self.map(|bytes| decode_bigint(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timestamp => {
                        Ok(self.map(|bytes| decode_timestamp(bytes.as_plain()).unwrap()))
                    }
                    ColType::Time => Ok(self.map(|bytes| decode_time(bytes.as_plain()).unwrap())),
                    ColType::Varint => {
                        Ok(self.map(|bytes| decode_varint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Bigint => {
                        Ok(self.map(|bytes| decode_bigint(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timestamp => {
                        Ok(self.map(|bytes| decode_timestamp(bytes.as_plain()).unwrap()))
                    }
                    ColType::Time => Ok(self.map(|bytes| decode_time(bytes.as_plain()).unwrap())),
                    ColType::Varint => {
                        Ok(self.map(|bytes| decode_varint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i32>> for List {
    /// Converts cassandra list of i32-like values into Rust `Vec<i32>`
    fn as_rust(&self) -> Result<Vec<i32>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Int => Ok(self.map(|bytes| decode_int(bytes.as_plain()).unwrap())),
                    ColType::Date => Ok(self.map(|bytes| decode_date(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Int => Ok(self.map(|bytes| decode_int(bytes.as_plain()).unwrap())),
                    ColType::Date => Ok(self.map(|bytes| decode_date(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<i16>> for List {
    /// Converts cassandra list of i16-like values into Rust `Vec<i16>`
    fn as_rust(&self) -> Result<Vec<i16>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Smallint => {
                        Ok(self.map(|bytes| decode_smallint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Smallint => {
                        Ok(self.map(|bytes| decode_smallint(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<f64>> for List {
    /// Converts cassandra list of f64-like values into Rust `Vec<f64>`
    fn as_rust(&self) -> Result<Vec<f64>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Double => {
                        Ok(self.map(|bytes| decode_double(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Double => {
                        Ok(self.map(|bytes| decode_double(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<f32>> for List {
    /// Converts cassandra list of f32-like values into Rust `Vec<f32>`
    fn as_rust(&self) -> Result<Vec<f32>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Decimal => {
                        Ok(self.map(|bytes| decode_decimal(bytes.as_plain()).unwrap()))
                    }
                    ColType::Float => Ok(self.map(|bytes| decode_float(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Decimal => {
                        Ok(self.map(|bytes| decode_decimal(bytes.as_plain()).unwrap()))
                    }
                    ColType::Float => Ok(self.map(|bytes| decode_float(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<net::IpAddr>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<net::IpAddr>`
    fn as_rust(&self) -> Result<Vec<net::IpAddr>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Inet => Ok(self.map(|bytes| decode_inet(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Inet => Ok(self.map(|bytes| decode_inet(bytes.as_plain()).unwrap())),
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<Uuid>> for List {
    /// Converts cassandra list of UUID values into Rust `Vec<uuid::Uuid>`
    fn as_rust(&self) -> Result<Vec<Uuid>> {
        match self.metadata.value {
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    ColType::Uuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timeuuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    ColType::Uuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    ColType::Timeuuid => {
                        Ok(self.map(|bytes| decode_timeuuid(bytes.as_plain()).unwrap()))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<List>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<List>> {
        match self.metadata.value {
            // convert CList of T-s into List of T-s
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    // T is another List
                    ColType::List => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      type_option.as_ref().clone())
                        }))
                    }
                    // T is another Set
                    ColType::Set => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      type_option.as_ref().clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    // T is another List
                    ColType::List => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      type_option.as_ref().clone())
                        }))
                    }
                    // T is another Set
                    ColType::Set => {
                        Ok(self.map(|bytes| {
                            List::new(decode_list(bytes.as_plain()).unwrap(),
                                      type_option.as_ref().clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<Map>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<Map>> {
        match self.metadata.value {
            // convert CList of T-s into List of T-s
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                match type_option.id {
                    // T is Map
                    ColType::Map => {
                        Ok(self.map(|bytes| {
                            Map::new(decode_map(bytes.as_plain()).unwrap(),
                                     type_option.as_ref().clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                match type_option.id {
                    // T is Map
                    ColType::Map => {
                        Ok(self.map(|bytes| {
                            Map::new(decode_map(bytes.as_plain()).unwrap(),
                                     type_option.as_ref().clone())
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

impl AsRust<Vec<UDT>> for List {
    /// Converts cassandra list of Inet values into Rust `Vec<List>`
    fn as_rust(&self) -> Result<Vec<UDT>> {
        match self.metadata.value {
            // convert CList of T-s into List of T-s
            Some(ColTypeOptionValue::CList(ref type_option)) => {
                let list_type_option = match type_option.value {
                    Some(ColTypeOptionValue::UdtType(ref t)) => t,
                    _ => unreachable!(),
                };
                match type_option.id {
                    // T is Udt
                    ColType::Udt => {
                        Ok(self.map(|bytes| {
                            UDT::new(decode_udt(bytes.as_plain()).unwrap(), list_type_option)
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            // convert CSet of T-s into List of T-s
            Some(ColTypeOptionValue::CSet(ref type_option)) => {
                let list_type_option = match type_option.value {
                    Some(ColTypeOptionValue::UdtType(ref t)) => t,
                    _ => unreachable!(),
                };
                match type_option.id {
                    // T is Udt
                    ColType::Udt => {
                        Ok(self.map(|bytes| {
                            UDT::new(decode_udt(bytes.as_plain()).unwrap(), list_type_option)
                        }))
                    }
                    _ => unreachable!(),
                }
            }
            _ => unreachable!(),
        }
    }
}

// TODO: implement for list of uuid
<|endoftext|>