<commit_before>use luminance::blending::{Equation, Factor};
use luminance::pipeline::{BoundTexture, Gpu, pipeline};
use luminance::shader::program;
use luminance::tess::{Mode, Tess, TessRender, TessVertices};
use luminance::texture::{Dim2, Flat};
use luminance::vertex::{Vertex, VertexFormat};
use std::cell::RefCell;

use framebuffer::Framebuffer2D;
use resource::{Res, ResCache};
use shader::{Program, Uniform, UniformBuilder, UniformInterface, UniformWarning, UnwrapOrUnbound};
use text::TextTexture;
use texture::{Depth32F, R32F, RGBA32F, Texture};

/// Vertex used in overlay’s objects. Position coordinates are in *window space*.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }

  /// Convert the vertex’ position to *clip space*.
  ///
  /// > Note: the depth coordinate is not affected.
  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    let converted = converter.from_win_coord(self.pos[0], self.pos[1]);
    let pos_ = [converted[0], converted[1], self.pos[2]];

    Vert {
      pos: pos_,
      color: self.color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Quad(pub Vert, pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  pub center: Vert,
  pub radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }

  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    Disc {
      center: self.center.to_clip_space(converter),
      radius: self.radius * converter.rw
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

#[derive(Copy, Clone)]
pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_lower: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_lower: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_lower: left_lower
    }
  }
}

struct DiscUniforms {
  screen_ratio: Uniform<f32>
}

impl UniformInterface for DiscUniforms {
  fn uniform_interface(builder: UniformBuilder) -> program::Result<(Self, Vec<UniformWarning>)> {
    let mut warnings = Vec::new();

    let iface = DiscUniforms {
      screen_ratio: builder.ask("ratio").unwrap_or_unbound(&builder, &mut warnings)
    };

    Ok((iface, warnings))
  }
}

struct TextUniforms {
  sampler: Uniform<BoundTexture<Texture<Flat, Dim2, R32F>>>,
  pos: Uniform<[f32; 3]>,
  size: Uniform<[f32; 2]>,
  scale: Uniform<f32>,
  color: Uniform<[f32; 4]>
}

impl UniformInterface for TextUniforms {
  fn uniform_interface(builder: UniformBuilder) -> program::Result<(Self, Vec<UniformWarning>)> {
    let mut warnings = Vec::new();

    let iface = TextUniforms {
      sampler: builder.ask("text_texture").unwrap_or_unbound(&builder, &mut warnings),
      pos: builder.ask("pos").unwrap_or_unbound(&builder, &mut warnings),
      size: builder.ask("size").unwrap_or_unbound(&builder, &mut warnings),
      scale: builder.ask("scale").unwrap_or_unbound(&builder, &mut warnings),
      color: builder.ask("color").unwrap_or_unbound(&builder, &mut warnings)
    };

    Ok((iface, warnings))
  }
}

pub struct Overlay {
  ratio: f32,
  tri_program: Res<Program<Vert, (), ()>>,
  tris: RefCell<Tess<Vert>>,
  disc_program: Res<Program<Disc, (), DiscUniforms>>,
  discs: RefCell<Tess<Disc>>,
  text_program: Res<Program<[f32; 2], (), TextUniforms>>,
  text_quad: Tess<[f32; 2]>,
  unit_converter: UnitConverter,
}

impl Overlay {
  pub fn new(w: u32, h: u32, max_tris: usize, max_quads: usize, max_discs: usize, cache: &mut ResCache) -> Self {
    let tri_program = cache.get("spectra/overlay/triangle.glsl", ()).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3 + max_quads * 4), None);

    let disc_program = cache.get("spectra/overlay/disc.glsl", ()).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = cache.get("spectra/overlay/text.glsl", ()).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Overlay {
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: RefCell::new(tris),
      disc_program: disc_program,
      discs: RefCell::new(discs),
      text_program: text_program,
      text_quad: text_quad,
      unit_converter: UnitConverter::new(w, h)
    }
  }

  /// Dispatch render input primitives into GPU buffers.
  fn dispatch(&self, input: &RenderInput) -> (usize, usize) {
    let mut tris_ref = self.tris.borrow_mut();
    let mut tri_i = 0;
    if let Ok(mut tris) = tris_ref.as_slice_mut() {
      for &Triangle(a, b, c) in input.triangles {
        let abc = [a, b, c];

        for &v in &abc {
          tris[tri_i] = v.to_clip_space(&self.unit_converter);
          tri_i += 1;
        }
      }

      for &Quad(a, b, c, d) in input.quads {
        let abcd = [a, b, c, c, b, d];

        for &v in &abcd {
          tris[tri_i] = v.to_clip_space(&self.unit_converter);
          tri_i += 1;
        }
      }
    }

    let mut discs_ref = self.discs.borrow_mut();
    let mut disc_i = 0;
    if let Ok(mut discs) = discs_ref.as_slice_mut() {
      for disc in input.discs {
        discs[disc_i] = disc.to_clip_space(&self.unit_converter);
        disc_i += 1;
      }
    }

    (tri_i, disc_i)
  }

  pub fn render(&self, gpu: &Gpu, framebuffer: &Framebuffer2D<Texture<Flat, Dim2, RGBA32F>, Texture<Flat, Dim2, Depth32F>>, input: &RenderInput) {
    let (tri_vert_nb, disc_vert_nb) = self.dispatch(input);

    let tris_ref = self.tris.borrow();
    let tris = TessRender::one_sub(&tris_ref, tri_vert_nb);

    let discs_ref = self.discs.borrow();
    let discs = TessRender::one_sub(&discs_ref, disc_vert_nb);

    let text_quad = TessRender::one_whole(&self.text_quad);

    let tri_program = self.tri_program.borrow();
    let disc_program = self.disc_program.borrow();
    let text_program = self.text_program.borrow();

    pipeline(framebuffer, [0., 0., 0., 0.], |shd_gate| {
      shd_gate.shade(&tri_program, |rdr_gate, _| {
        rdr_gate.render(None, true, |tess_gate| {
          tess_gate.render(tris);
        });
      });

      shd_gate.shade(&disc_program, |rdr_gate, uniforms| {
        uniforms.screen_ratio.update(self.ratio);

        rdr_gate.render(None, true, |tess_gate| {
          tess_gate.render(discs);
        });
      });

      if let Some((texts, text_scale)) = input.texts {
        shd_gate.shade(&text_program, |rdr_gate, uniforms| {
          for text in texts {
            let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
            let [tex_w, tex_h] = text.text_texture.size();

            let texture = gpu.bind_texture(&**text.text_texture);

            uniforms.sampler.update(texture);
            uniforms.pos.update(text.left_lower.to_clip_space(&self.unit_converter).pos);
            uniforms.size.update(self.unit_converter.from_win_dim(tex_w as f32, tex_h as f32));
            uniforms.scale.update(text_scale);
            uniforms.color.update(text.left_lower.color);

            rdr_gate.render(blending, true, |tess_gate| {
              tess_gate.render(text_quad.clone());
            });
          }
        });
      }
    });
  }
}

#[derive(Clone)]
pub struct RenderInput<'a> {
  triangles: &'a [Triangle],
  quads: &'a [Quad],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'a>], f32)>
}

impl<'a> RenderInput<'a> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      quads: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles,
      ..self
    }
  }

  pub fn quads(self, quads: &'a [Quad]) -> Self {
    RenderInput {
      quads: quads,
      ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'a>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// A *unit converter* is used to position stuff in overlay in a universal and screen independent
/// way.
///
/// The idea is that you provide should handle *window space* coordinates only. This type will then
/// help compute normalized coordinates the renderer can understand.
///
/// For the record, *window space* coordinates are defined as below – given a viewport size of
/// *w × h*:
///
/// ^ y = h
/// |
/// |
/// |    x = w
/// O------>
///
/// The formula used to convert from *window space* to what we call *clip space* is:
///
/// > x' = 2x / w - 1
/// > y' = 2y / h - 1
#[derive(Copy, Clone, Debug, PartialEq)]
struct UnitConverter {
  rw: f32,
  rh: f32,
  twice_rw: f32,
  twice_rh: f32
}

impl UnitConverter {
  /// Build a unit converter by giving it the size of the viewport.
  pub fn new(w: u32, h: u32) -> Self {
    let rw = 1. / (w as f32);
    let rh = 1. / (h as f32);

    UnitConverter {
      rw: rw,
      rh: rh,
      twice_rw: 2. * rw,
      twice_rh: 2. * rh
    }
  }

  /// Convert from *window space* coordinates to clip space* ones.
  pub fn from_win_coord(&self, x: f32, y: f32) -> [f32; 2] {
    let x_ = x * self.twice_rw - 1.;
    let y_ = y * self.twice_rh - 1.;

    [x_.min(1.).max(-1.), y_.min(1.).max(-1.)]
  }

  /// Convert from *window space* dimensions to clip space* ones.
  pub fn from_win_dim(&self, w: f32, h: f32) -> [f32; 2] {
    let w_ = w * self.rw;
    let h_ = h * self.rh;

    [w_.min(1.).max(-1.), h_.min(1.).max(-1.)]
  }
}
<commit_msg>Fixed TextUniforms’ BoundTexture with 'static lifetime.<commit_after>use luminance::blending::{Equation, Factor};
use luminance::pipeline::{BoundTexture, Gpu, pipeline};
use luminance::shader::program;
use luminance::tess::{Mode, Tess, TessRender, TessVertices};
use luminance::texture::{Dim2, Flat};
use luminance::vertex::{Vertex, VertexFormat};
use std::cell::RefCell;

use framebuffer::Framebuffer2D;
use resource::{Res, ResCache};
use shader::{Program, Uniform, UniformBuilder, UniformInterface, UniformWarning, UnwrapOrUnbound};
use text::TextTexture;
use texture::{Depth32F, R32F, RGBA32F, Texture};

/// Vertex used in overlay’s objects. Position coordinates are in *window space*.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }

  /// Convert the vertex’ position to *clip space*.
  ///
  /// > Note: the depth coordinate is not affected.
  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    let converted = converter.from_win_coord(self.pos[0], self.pos[1]);
    let pos_ = [converted[0], converted[1], self.pos[2]];

    Vert {
      pos: pos_,
      color: self.color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Quad(pub Vert, pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  pub center: Vert,
  pub radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }

  fn to_clip_space(&self, converter: &UnitConverter) -> Self {
    Disc {
      center: self.center.to_clip_space(converter),
      radius: self.radius * converter.rw
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

#[derive(Copy, Clone)]
pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_lower: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_lower: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_lower: left_lower
    }
  }
}

struct DiscUniforms {
  screen_ratio: Uniform<f32>
}

impl UniformInterface for DiscUniforms {
  fn uniform_interface(builder: UniformBuilder) -> program::Result<(Self, Vec<UniformWarning>)> {
    let mut warnings = Vec::new();

    let iface = DiscUniforms {
      screen_ratio: builder.ask("ratio").unwrap_or_unbound(&builder, &mut warnings)
    };

    Ok((iface, warnings))
  }
}

struct TextUniforms {
  sampler: Uniform<BoundTexture<'static, Texture<Flat, Dim2, R32F>>>,
  pos: Uniform<[f32; 3]>,
  size: Uniform<[f32; 2]>,
  scale: Uniform<f32>,
  color: Uniform<[f32; 4]>
}

impl UniformInterface for TextUniforms {
  fn uniform_interface(builder: UniformBuilder) -> program::Result<(Self, Vec<UniformWarning>)> {
    let mut warnings = Vec::new();

    let iface = TextUniforms {
      sampler: builder.ask("text_texture").unwrap_or_unbound(&builder, &mut warnings),
      pos: builder.ask("pos").unwrap_or_unbound(&builder, &mut warnings),
      size: builder.ask("size").unwrap_or_unbound(&builder, &mut warnings),
      scale: builder.ask("scale").unwrap_or_unbound(&builder, &mut warnings),
      color: builder.ask("color").unwrap_or_unbound(&builder, &mut warnings)
    };

    Ok((iface, warnings))
  }
}

pub struct Overlay {
  ratio: f32,
  tri_program: Res<Program<Vert, (), ()>>,
  tris: RefCell<Tess<Vert>>,
  disc_program: Res<Program<Disc, (), DiscUniforms>>,
  discs: RefCell<Tess<Disc>>,
  text_program: Res<Program<[f32; 2], (), TextUniforms>>,
  text_quad: Tess<[f32; 2]>,
  unit_converter: UnitConverter,
}

impl Overlay {
  pub fn new(w: u32, h: u32, max_tris: usize, max_quads: usize, max_discs: usize, cache: &mut ResCache) -> Self {
    let tri_program = cache.get("spectra/overlay/triangle.glsl", ()).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3 + max_quads * 4), None);

    let disc_program = cache.get("spectra/overlay/disc.glsl", ()).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = cache.get("spectra/overlay/text.glsl", ()).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Overlay {
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: RefCell::new(tris),
      disc_program: disc_program,
      discs: RefCell::new(discs),
      text_program: text_program,
      text_quad: text_quad,
      unit_converter: UnitConverter::new(w, h)
    }
  }

  /// Dispatch render input primitives into GPU buffers.
  fn dispatch(&self, input: &RenderInput) -> (usize, usize) {
    let mut tris_ref = self.tris.borrow_mut();
    let mut tri_i = 0;
    if let Ok(mut tris) = tris_ref.as_slice_mut() {
      for &Triangle(a, b, c) in input.triangles {
        let abc = [a, b, c];

        for &v in &abc {
          tris[tri_i] = v.to_clip_space(&self.unit_converter);
          tri_i += 1;
        }
      }

      for &Quad(a, b, c, d) in input.quads {
        let abcd = [a, b, c, c, b, d];

        for &v in &abcd {
          tris[tri_i] = v.to_clip_space(&self.unit_converter);
          tri_i += 1;
        }
      }
    }

    let mut discs_ref = self.discs.borrow_mut();
    let mut disc_i = 0;
    if let Ok(mut discs) = discs_ref.as_slice_mut() {
      for disc in input.discs {
        discs[disc_i] = disc.to_clip_space(&self.unit_converter);
        disc_i += 1;
      }
    }

    (tri_i, disc_i)
  }

  pub fn render(&self, gpu: &Gpu, framebuffer: &Framebuffer2D<Texture<Flat, Dim2, RGBA32F>, Texture<Flat, Dim2, Depth32F>>, input: &RenderInput) {
    let (tri_vert_nb, disc_vert_nb) = self.dispatch(input);

    let tris_ref = self.tris.borrow();
    let tris = TessRender::one_sub(&tris_ref, tri_vert_nb);

    let discs_ref = self.discs.borrow();
    let discs = TessRender::one_sub(&discs_ref, disc_vert_nb);

    let text_quad = TessRender::one_whole(&self.text_quad);

    let tri_program = self.tri_program.borrow();
    let disc_program = self.disc_program.borrow();
    let text_program = self.text_program.borrow();

    pipeline(framebuffer, [0., 0., 0., 0.], |shd_gate| {
      shd_gate.shade(&tri_program, |rdr_gate, _| {
        rdr_gate.render(None, true, |tess_gate| {
          tess_gate.render(tris);
        });
      });

      shd_gate.shade(&disc_program, |rdr_gate, uniforms| {
        uniforms.screen_ratio.update(self.ratio);

        rdr_gate.render(None, true, |tess_gate| {
          tess_gate.render(discs);
        });
      });

      if let Some((texts, text_scale)) = input.texts {
        shd_gate.shade(&text_program, |rdr_gate, uniforms| {
          for text in texts {
            let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
            let [tex_w, tex_h] = text.text_texture.size();

            let texture = gpu.bind_texture(&**text.text_texture);

            uniforms.sampler.update(texture);
            uniforms.pos.update(text.left_lower.to_clip_space(&self.unit_converter).pos);
            uniforms.size.update(self.unit_converter.from_win_dim(tex_w as f32, tex_h as f32));
            uniforms.scale.update(text_scale);
            uniforms.color.update(text.left_lower.color);

            rdr_gate.render(blending, true, |tess_gate| {
              tess_gate.render(text_quad.clone());
            });
          }
        });
      }
    });
  }
}

#[derive(Clone)]
pub struct RenderInput<'a> {
  triangles: &'a [Triangle],
  quads: &'a [Quad],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'a>], f32)>
}

impl<'a> RenderInput<'a> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      quads: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles,
      ..self
    }
  }

  pub fn quads(self, quads: &'a [Quad]) -> Self {
    RenderInput {
      quads: quads,
      ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'a>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// A *unit converter* is used to position stuff in overlay in a universal and screen independent
/// way.
///
/// The idea is that you provide should handle *window space* coordinates only. This type will then
/// help compute normalized coordinates the renderer can understand.
///
/// For the record, *window space* coordinates are defined as below – given a viewport size of
/// *w × h*:
///
/// ^ y = h
/// |
/// |
/// |    x = w
/// O------>
///
/// The formula used to convert from *window space* to what we call *clip space* is:
///
/// > x' = 2x / w - 1
/// > y' = 2y / h - 1
#[derive(Copy, Clone, Debug, PartialEq)]
struct UnitConverter {
  rw: f32,
  rh: f32,
  twice_rw: f32,
  twice_rh: f32
}

impl UnitConverter {
  /// Build a unit converter by giving it the size of the viewport.
  pub fn new(w: u32, h: u32) -> Self {
    let rw = 1. / (w as f32);
    let rh = 1. / (h as f32);

    UnitConverter {
      rw: rw,
      rh: rh,
      twice_rw: 2. * rw,
      twice_rh: 2. * rh
    }
  }

  /// Convert from *window space* coordinates to clip space* ones.
  pub fn from_win_coord(&self, x: f32, y: f32) -> [f32; 2] {
    let x_ = x * self.twice_rw - 1.;
    let y_ = y * self.twice_rh - 1.;

    [x_.min(1.).max(-1.), y_.min(1.).max(-1.)]
  }

  /// Convert from *window space* dimensions to clip space* ones.
  pub fn from_win_dim(&self, w: f32, h: f32) -> [f32; 2] {
    let w_ = w * self.rw;
    let h_ = h * self.rh;

    [w_.min(1.).max(-1.), h_.min(1.).max(-1.)]
  }
}
<|endoftext|>


<commit_before>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use std::str;

use nom::{
    branch::alt,
    bytes::complete::{tag, take_while, take_while_m_n},
    character::complete::one_of,
    character::is_digit,
    combinator::{map, opt},
    sequence::preceded,
    IResult,
};

use crate::{Date, DateTime, Time};

#[cfg(test)]
mod tests;

fn take_n_digits(i: &[u8], n: usize) -> IResult<&[u8], u32> {
    let (i, digits) = take_while_m_n(n, n, is_digit)(i)?;

    let s = str::from_utf8(digits).expect("Invalid data, expected UTF-8 string");
    let res = s
        .parse()
        .expect("Invalid string, expected ASCII reprensation of a number");
    Ok((i, res))
}

// year
fn year_prefix(i: &[u8]) -> IResult<&[u8], &[u8]> {
    alt((tag(b"+"), tag(b"-")))(i)
}
fn year(i: &[u8]) -> IResult<&[u8], i32> {
    let (i, is_pos) = match opt(year_prefix)(i) {
        Ok((i, Some(b))) if b == b"-" => (i, false),
        Ok((i, _)) => (i, true),
        Err(e) => return Err(e),
    };
    let (i, year) = take_n_digits(i, 4)?;
    let mut year = year as i32;
    if !is_pos {
        year = -year
    }

    Ok((i, year))
}

// MM
fn month(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, m) = take_n_digits(i, 2)?;

    if m >= 1 && m <= 12 {
        Ok((new_i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// DD
fn day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 2)?;

    if d >= 1 && d <= 31 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// WW
fn week(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, w) = take_n_digits(i, 2)?;

    if w >= 1 && w <= 52 {
        Ok((new_i, w))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn week_day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 1)?;

    if d >= 1 && d <= 7 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// ordinal DDD
fn ord_day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 3)?;

    if d >= 1 && d <= 366 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// YYYY-MM-DD
fn ymd_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, m) = month(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = day(i)?;
    Ok((
        i,
        Date::YMD {
            year: y,
            month: m,
            day: d,
        },
    ))
}

// YYYY-DDD
fn ordinal_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = ord_day(i)?;
    Ok((i, Date::Ordinal { year: y, ddd: d }))
}

// YYYY-"W"WW-D
fn iso_week_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, _) = tag(b"W")(i)?;
    let (i, w) = week(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = week_day(i)?;
    Ok((
        i,
        Date::Week {
            year: y,
            ww: w,
            d: d,
        },
    ))
}

pub fn parse_date(i: &[u8]) -> IResult<&[u8], Date> {
    alt((ymd_date, iso_week_date, ordinal_date))(i)
}

// TIME

// HH
fn hour(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 24 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// MM
fn minute(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 59 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn second(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 60 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn fractions(i: &[u8]) -> IResult<&[u8], f32> {
    let (i, digits) = take_while(is_digit)(i)?;
    let digits = str::from_utf8(digits).unwrap(); // This can't panic, `digits` will only include digits.
    let f = format!("0.{}", digits).parse().unwrap(); // This can't panic, the string is a valid `f32`.

    Ok((i, f))
}

fn millisecond(fraction: f32) -> u32 {
    (1000.0 * fraction) as u32
}

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
pub fn parse_time(i: &[u8]) -> IResult<&[u8], Time> {
    let (i, h) = hour(i)?;
    let (i, _) = opt(tag(b":"))(i)?;
    let (i, m) = minute(i)?;
    let (i, s) = opt(preceded(opt(tag(b":")), second))(i)?;
    let (i, ms) = opt(map(preceded(one_of(",."), fractions), millisecond))(i)?;
    let (i, z) = match opt(alt((timezone_hour, timezone_utc)))(i) {
        Ok(ok) => ok,
        Err(nom::Err::Incomplete(_)) => (i, None),
        Err(e) => return Err(e),
    };

    Ok((
        i,
        Time {
            hour: h,
            minute: m,
            second: s.unwrap_or(0),
            millisecond: ms.unwrap_or(0),
            tz_offset_hours: z.unwrap_or((0, 0)).0,
            tz_offset_minutes: z.unwrap_or((0, 0)).1,
        },
    ))
}

fn sign(i: &[u8]) -> IResult<&[u8], i32> {
    map(alt((tag(b"-"), tag(b"+"))), |s: &[u8]| match s {
        b"-" => -1,
        _ => 1,
    })(i)
}

fn timezone_hour(i: &[u8]) -> IResult<&[u8], (i32, i32)> {
    let (i, s) = sign(i)?;
    let (i, h) = hour(i)?;
    let (i, m) = if i.is_empty() {
        (i, 0)
    } else {
        let (i, _) = opt(tag(b":"))(i)?;
        minute(i)?
    };

    Ok((i, ((s * (h as i32), s * (m as i32)))))
}

fn timezone_utc(i: &[u8]) -> IResult<&[u8], (i32, i32)> {
    map(tag(b"Z"), |_| (0, 0))(i)
}

// Full ISO8601
pub fn parse_datetime(i: &[u8]) -> IResult<&[u8], DateTime> {
    let (i, d) = parse_date(i)?;
    let (i, _) = tag(b"T")(i)?;
    let (i, t) = parse_time(i)?;

    Ok((i, DateTime { date: d, time: t }))
}
<commit_msg>Re-use sign parsing<commit_after>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use std::str;

use nom::{
    branch::alt,
    bytes::complete::{tag, take_while, take_while_m_n},
    character::complete::one_of,
    character::is_digit,
    combinator::{map, opt},
    sequence::preceded,
    IResult,
};

use crate::{Date, DateTime, Time};

#[cfg(test)]
mod tests;

fn take_n_digits(i: &[u8], n: usize) -> IResult<&[u8], u32> {
    let (i, digits) = take_while_m_n(n, n, is_digit)(i)?;

    let s = str::from_utf8(digits).expect("Invalid data, expected UTF-8 string");
    let res = s
        .parse()
        .expect("Invalid string, expected ASCII reprensation of a number");
    Ok((i, res))
}

fn sign(i: &[u8]) -> IResult<&[u8], i32> {
    map(alt((tag(b"-"), tag(b"+"))), |s: &[u8]| match s {
        b"-" => -1,
        _ => 1,
    })(i)
}

// [+/-] year
fn year(i: &[u8]) -> IResult<&[u8], i32> {
    // The sign is optional, but defaults to `+`
    let (i, s) = sign(i).unwrap_or((i, 1));
    let (i, year) = take_n_digits(i, 4)?;
    let year = s * year as i32;

    Ok((i, year))
}

// MM
fn month(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, m) = take_n_digits(i, 2)?;

    if m >= 1 && m <= 12 {
        Ok((new_i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// DD
fn day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 2)?;

    if d >= 1 && d <= 31 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// WW
fn week(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, w) = take_n_digits(i, 2)?;

    if w >= 1 && w <= 52 {
        Ok((new_i, w))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn week_day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 1)?;

    if d >= 1 && d <= 7 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// ordinal DDD
fn ord_day(i: &[u8]) -> IResult<&[u8], u32> {
    let (new_i, d) = take_n_digits(i, 3)?;

    if d >= 1 && d <= 366 {
        Ok((new_i, d))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// YYYY-MM-DD
fn ymd_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, m) = month(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = day(i)?;
    Ok((
        i,
        Date::YMD {
            year: y,
            month: m,
            day: d,
        },
    ))
}

// YYYY-DDD
fn ordinal_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = ord_day(i)?;
    Ok((i, Date::Ordinal { year: y, ddd: d }))
}

// YYYY-"W"WW-D
fn iso_week_date(i: &[u8]) -> IResult<&[u8], Date> {
    let (i, y) = year(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, _) = tag(b"W")(i)?;
    let (i, w) = week(i)?;
    let (i, _) = opt(tag(b"-"))(i)?;
    let (i, d) = week_day(i)?;
    Ok((
        i,
        Date::Week {
            year: y,
            ww: w,
            d: d,
        },
    ))
}

pub fn parse_date(i: &[u8]) -> IResult<&[u8], Date> {
    alt((ymd_date, iso_week_date, ordinal_date))(i)
}

// TIME

// HH
fn hour(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 24 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

// MM
fn minute(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 59 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn second(i: &[u8]) -> IResult<&[u8], u32> {
    let (i, m) = take_n_digits(i, 2)?;

    if m <= 60 {
        Ok((i, m))
    } else {
        Err(nom::Err::Error((i, nom::error::ErrorKind::Eof)))
    }
}

fn fractions(i: &[u8]) -> IResult<&[u8], f32> {
    let (i, digits) = take_while(is_digit)(i)?;
    let digits = str::from_utf8(digits).unwrap(); // This can't panic, `digits` will only include digits.
    let f = format!("0.{}", digits).parse().unwrap(); // This can't panic, the string is a valid `f32`.

    Ok((i, f))
}

fn millisecond(fraction: f32) -> u32 {
    (1000.0 * fraction) as u32
}

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
pub fn parse_time(i: &[u8]) -> IResult<&[u8], Time> {
    let (i, h) = hour(i)?;
    let (i, _) = opt(tag(b":"))(i)?;
    let (i, m) = minute(i)?;
    let (i, s) = opt(preceded(opt(tag(b":")), second))(i)?;
    let (i, ms) = opt(map(preceded(one_of(",."), fractions), millisecond))(i)?;
    let (i, z) = match opt(alt((timezone_hour, timezone_utc)))(i) {
        Ok(ok) => ok,
        Err(nom::Err::Incomplete(_)) => (i, None),
        Err(e) => return Err(e),
    };

    Ok((
        i,
        Time {
            hour: h,
            minute: m,
            second: s.unwrap_or(0),
            millisecond: ms.unwrap_or(0),
            tz_offset_hours: z.unwrap_or((0, 0)).0,
            tz_offset_minutes: z.unwrap_or((0, 0)).1,
        },
    ))
}

fn timezone_hour(i: &[u8]) -> IResult<&[u8], (i32, i32)> {
    let (i, s) = sign(i)?;
    let (i, h) = hour(i)?;
    let (i, m) = if i.is_empty() {
        (i, 0)
    } else {
        let (i, _) = opt(tag(b":"))(i)?;
        minute(i)?
    };

    Ok((i, ((s * (h as i32), s * (m as i32)))))
}

fn timezone_utc(i: &[u8]) -> IResult<&[u8], (i32, i32)> {
    map(tag(b"Z"), |_| (0, 0))(i)
}

// Full ISO8601
pub fn parse_datetime(i: &[u8]) -> IResult<&[u8], DateTime> {
    let (i, d) = parse_date(i)?;
    let (i, _) = tag(b"T")(i)?;
    let (i, t) = parse_time(i)?;

    Ok((i, DateTime { date: d, time: t }))
}
<|endoftext|>


<commit_before>//inherited mutability: player is mutable if let is mutable

//todo: Test in ticks
//      Implement player acceleration based on ticks between inputs.
//      Potentially ticks holding a button and ticks not
//      Rotation accel/vel
use game;

use std::cmp::{max, min};

pub use self::collision::collide;

#[deriving(Eq)]
pub enum Direction {
    Forward,
    Backward,
    Still
}

pub fn accel(p: &mut game::Player){ //mut player:&mut player would allow to play w/ pointer
    if p.velocity >= -0.15 && p.velocity <= 0.15 {
        p.velocity += p.accel * 0.0001;
    }

    if p.velocity < -0.05 {
        p.velocity = -0.05;
    }

    if p.velocity >= 0.05 {
        p.velocity = 0.05
    }

    p.position += p.velocity;

    let (acc, amod) = accel_compute(p.dir, p.accel, p.accel_mod);

    p.accel = acc;
    p.accel_mod = amod;
}

pub fn accel_compute (dir: Direction, mut accel: f32, mut accel_mod: int) -> (f32, int) {
    //this will use accel/accel_mod to compute the rate of increase of acceleration.
    if dir == Forward {
        let bounds = [
            (-85, -75, 25),
            (-75, -60, 22),
            (-60, -41, 19),
            (-40, -15, 17),
            (0, 15, 12),
            (14, 40, 10),
            (40, 60, 8),
            (60, 75, 5),
            (75, 85, 2)
        ];

        accel_mod = max(accel_mod, -84);

        if accel_mod == 0 {
            accel_mod = 15;
        } else if accel_mod >= -15 && accel_mod < 0 {
            accel_mod = 0;
        } else {
            for &(lower, upper, increment) in bounds.iter() {
                if accel_mod >= lower && accel_mod <= upper {
                    accel_mod += increment;
                    break
                }
            }
        }

    } else if dir == Backward {
        let bounds = [
            (-85, -75, -2),
            (-75, -60, -5),
            (-60, -41, -8),
            (-40, -15, -10),
            (-15, 0, -12),
            (15, 40, 17),
            (40, 60, 19),
            (60, 75, -22),
            (75, 85, -25)
        ];

        accel_mod = min(accel_mod, 84);

        if accel_mod == 0 {
            accel_mod = -15;
        } else if accel_mod <= 15 && accel_mod > 0 {
            accel_mod = 0;
        } else {
            for &(lower, upper, increment) in bounds.iter() {
                if accel_mod >= lower && accel_mod <= upper {
                    accel_mod += increment;
                    break
                }
            }
        }
    }

    if accel <= 0.05 && accel >= -0.05 {
        accel = accel + (0.00003 * (accel_mod as f32));
    } else {
        accel = accel.signum() * 0.05;
    }

    (accel, accel_mod) //returns accel and accel mod
}

mod collision {
    use cgmath::angle::Rad;
    use cgmath::vector::{Vector, Vector2};
    use cgmath::matrix::{Matrix, Matrix2};
    use gl::types::GLfloat;
    use render::Sprite;
    use std::f32::consts::PI;

    type V = Vector2<GLfloat>;

    fn min(a: GLfloat, b: GLfloat) -> GLfloat {
        a.min(b)
    }

    fn max(a: GLfloat, b: GLfloat) -> GLfloat {
        a.max(b)
    }

    fn slope(a: V, b: V) -> GLfloat {
        (a.y - b.y) / (a.x - b.x)
    }

    fn line_intercept((a1, a2): (V, V), (b1, b2): (V, V)) -> f32 {
        let (x1, x2, y1, y2, m1, m2) = (a1.x, b1.x, a1.y, b1.y, slope(a1, a2), slope(b1, b2));

        ((m1*x1) - (m2*x2) - y1 + y2) / (m1 - m2)
    }

    fn intersect((a1, a2): (V, V), (b1, b2): (V, V)) -> Option<V> {
        debug!("Checking the intersection of the two lines, {} to {} and {} to {}", a1, a2, b1, b2);

        let x = line_intercept((a1, a2), (b1, b2));
        debug!("The lines, were they infinite, intersect at x = {}", x);

        let y = slope(a1, a2)*(x - a1.x) + a1.y;
        debug!("The corresponding y is {}", y);

        if x >= min(a1.x, a2.x) && x <= max(a1.x, a2.x) {
            debug!("It's within the first line's x values");
            if x >= min(b1.x, b2.x) && x <= max(b1.x, b2.x) {
                debug!("It's within the second line's x values");
                if y >= min(a1.y, a2.y) && y <= max(a1.y, a2.y) {
                    debug!("It's within the first line's y values");
                    if y >= min(b1.y, b2.y) && y <= max(b1.y, b2.y) {
                        debug!("It's within the second line's y values");
                        return Some(Vector2::new(x, y));
                    }
                }
            }
        }

        None
    }

    #[test]
    fn test_intersect() {
        let a = Vector2::new(1f32, 1f32);
        let b = Vector2::new(-1f32, -1f32);

        let c = Vector2::new(-1f32, 1f32);
        let d = Vector2::new(1f32, -1f32);

        assert_eq!(intersect((a, b), (c, d)), Some(Vector2::new(0f32, 0f32)));
    }

    /// Determines if two Sprites collide, assuming that they collide iff their
    /// (possibly rotated) bounding boxes collide, not using the texture in any
    /// way.
    pub fn collide(a: &Sprite, b: &Sprite) -> bool {

        // make lists of points making up each sprite, transformed with the
        // rotation

        let mut arot = a.rot;
        let mut brot = b.rot;

        // make sure their slopes aren't NaN :(
        if arot % (PI / 4.0) == 0.0 {
            arot += 0.01;
        }

        if brot % (PI / 4.0) == 0.0 {
            brot += 0.01;
        }

        let amat = Matrix2::from_angle(Rad { s: arot });
        let bmat = Matrix2::from_angle(Rad { s: brot });

        let pairs = [(0, 1), (1, 2), (2, 3), (3, 0)]; // which indices form lines we care about?

        let &Sprite {x, y, width, height, .. } = a;
        let apoints = [
            amat.mul_v(&Vector2::new(x, y)),
            amat.mul_v(&Vector2::new(x + width, y)),
            amat.mul_v(&Vector2::new(x + width, y + height)),
            amat.mul_v(&Vector2::new(x, y + height))
        ];

        let &Sprite {x, y, width, height, .. } = b;
        let bpoints = [
            bmat.mul_v(&Vector2::new(x, y)),
            bmat.mul_v(&Vector2::new(x + width, y)),
            bmat.mul_v(&Vector2::new(x + width, y + height)),
            bmat.mul_v(&Vector2::new(x, y + height))
        ];

        for &(a1, a2) in pairs.iter() {
            for &(b1, b2) in pairs.iter() {
                if intersect((apoints[a1], apoints[a2]), (bpoints[b1], bpoints[b2])) != None {
                    return true;
                }
            }
        }

        false
    }

    #[test]
    fn test_collide() {
        use std;

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(0.5, 0.5, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(1.0, 1.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.5, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }
    }
}

<commit_msg>Fix oscillation<commit_after>//inherited mutability: player is mutable if let is mutable

//todo: Test in ticks
//      Implement player acceleration based on ticks between inputs.
//      Potentially ticks holding a button and ticks not
//      Rotation accel/vel
use game;

use std::cmp::{max, min};

pub use self::collision::collide;

#[deriving(Eq)]
pub enum Direction {
    Forward,
    Backward,
    Still
}

pub fn accel(p: &mut game::Player){ //mut player:&mut player would allow to play w/ pointer
    if p.velocity >= -0.15 && p.velocity <= 0.15 {
        p.velocity += p.accel * 0.0001;
    }

    if p.velocity < -0.05 {
        p.velocity = -0.05;
    }

    if p.velocity >= 0.05 {
        p.velocity = 0.05
    }

    p.position += p.velocity;

    let (acc, amod) = accel_compute(p.dir, p.accel, p.accel_mod);

    p.accel = acc;
    p.accel_mod = amod;
}

pub fn accel_compute (dir: Direction, mut accel: f32, mut accel_mod: int) -> (f32, int) {
    //this will use accel/accel_mod to compute the rate of increase of acceleration.
    if dir == Forward {
        let bounds = [
            (-85, -75, 25),
            (-75, -60, 22),
            (-60, -41, 19),
            (-40, -15, 17),
            (0, 15, 12),
            (14, 40, 10),
            (40, 60, 8),
            (60, 75, 5),
            (75, 85, 2)
        ];

        accel_mod = max(accel_mod, -84);

        if accel_mod == 0 {
            accel_mod = 15;
        } else if accel_mod >= -15 && accel_mod < 0 {
            accel_mod = 0;
        } else {
            for &(lower, upper, increment) in bounds.iter() {
                if accel_mod >= lower && accel_mod <= upper {
                    accel_mod += increment;
                    break
                }
            }
        }

    } else if dir == Backward {
        let bounds = [
            (-85, -75, -2),
            (-75, -60, -5),
            (-60, -41, -8),
            (-40, -15, -10),
            (-15, 0, -12),
            (15, 40, -17),
            (40, 60, -19),
            (60, 75, -22),
            (75, 85, -25)
        ];

        accel_mod = min(accel_mod, 84);

        if accel_mod == 0 {
            accel_mod = -15;
        } else if accel_mod <= 15 && accel_mod > 0 {
            accel_mod = 0;
        } else {
            for &(lower, upper, increment) in bounds.iter() {
                if accel_mod >= lower && accel_mod <= upper {
                    accel_mod += increment;
                    break
                }
            }
        }
    }

    if accel <= 0.05 && accel >= -0.05 {
        accel = accel + (0.00003 * (accel_mod as f32));
    } else {
        accel = accel.signum() * 0.05;
    }

    (accel, accel_mod) //returns accel and accel mod
}

mod collision {
    use cgmath::angle::Rad;
    use cgmath::vector::{Vector, Vector2};
    use cgmath::matrix::{Matrix, Matrix2};
    use gl::types::GLfloat;
    use render::Sprite;
    use std::f32::consts::PI;

    type V = Vector2<GLfloat>;

    fn min(a: GLfloat, b: GLfloat) -> GLfloat {
        a.min(b)
    }

    fn max(a: GLfloat, b: GLfloat) -> GLfloat {
        a.max(b)
    }

    fn slope(a: V, b: V) -> GLfloat {
        (a.y - b.y) / (a.x - b.x)
    }

    fn line_intercept((a1, a2): (V, V), (b1, b2): (V, V)) -> f32 {
        let (x1, x2, y1, y2, m1, m2) = (a1.x, b1.x, a1.y, b1.y, slope(a1, a2), slope(b1, b2));

        ((m1*x1) - (m2*x2) - y1 + y2) / (m1 - m2)
    }

    fn intersect((a1, a2): (V, V), (b1, b2): (V, V)) -> Option<V> {
        debug!("Checking the intersection of the two lines, {} to {} and {} to {}", a1, a2, b1, b2);

        let x = line_intercept((a1, a2), (b1, b2));
        debug!("The lines, were they infinite, intersect at x = {}", x);

        let y = slope(a1, a2)*(x - a1.x) + a1.y;
        debug!("The corresponding y is {}", y);

        if x >= min(a1.x, a2.x) && x <= max(a1.x, a2.x) {
            debug!("It's within the first line's x values");
            if x >= min(b1.x, b2.x) && x <= max(b1.x, b2.x) {
                debug!("It's within the second line's x values");
                if y >= min(a1.y, a2.y) && y <= max(a1.y, a2.y) {
                    debug!("It's within the first line's y values");
                    if y >= min(b1.y, b2.y) && y <= max(b1.y, b2.y) {
                        debug!("It's within the second line's y values");
                        return Some(Vector2::new(x, y));
                    }
                }
            }
        }

        None
    }

    #[test]
    fn test_intersect() {
        let a = Vector2::new(1f32, 1f32);
        let b = Vector2::new(-1f32, -1f32);

        let c = Vector2::new(-1f32, 1f32);
        let d = Vector2::new(1f32, -1f32);

        assert_eq!(intersect((a, b), (c, d)), Some(Vector2::new(0f32, 0f32)));
    }

    /// Determines if two Sprites collide, assuming that they collide iff their
    /// (possibly rotated) bounding boxes collide, not using the texture in any
    /// way.
    pub fn collide(a: &Sprite, b: &Sprite) -> bool {

        // make lists of points making up each sprite, transformed with the
        // rotation

        let mut arot = a.rot;
        let mut brot = b.rot;

        // make sure their slopes aren't NaN :(
        if arot % (PI / 4.0) == 0.0 {
            arot += 0.01;
        }

        if brot % (PI / 4.0) == 0.0 {
            brot += 0.01;
        }

        let amat = Matrix2::from_angle(Rad { s: arot });
        let bmat = Matrix2::from_angle(Rad { s: brot });

        let pairs = [(0, 1), (1, 2), (2, 3), (3, 0)]; // which indices form lines we care about?

        let &Sprite {x, y, width, height, .. } = a;
        let apoints = [
            amat.mul_v(&Vector2::new(x, y)),
            amat.mul_v(&Vector2::new(x + width, y)),
            amat.mul_v(&Vector2::new(x + width, y + height)),
            amat.mul_v(&Vector2::new(x, y + height))
        ];

        let &Sprite {x, y, width, height, .. } = b;
        let bpoints = [
            bmat.mul_v(&Vector2::new(x, y)),
            bmat.mul_v(&Vector2::new(x + width, y)),
            bmat.mul_v(&Vector2::new(x + width, y + height)),
            bmat.mul_v(&Vector2::new(x, y + height))
        ];

        for &(a1, a2) in pairs.iter() {
            for &(b1, b2) in pairs.iter() {
                if intersect((apoints[a1], apoints[a2]), (bpoints[b1], bpoints[b2])) != None {
                    return true;
                }
            }
        }

        false
    }

    #[test]
    fn test_collide() {
        use std;

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(0.5, 0.5, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(1.0, 1.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }

        let s1 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.0, unsafe { std::mem::uninit() });
        let s2 = Sprite::new(0.0, 0.0, 1.0, 1.0, 0.5, unsafe { std::mem::uninit() });

        assert_eq!(collide(&s1, &s2), true);

        unsafe {
            // since we're stubbing out the texture
            std::cast::forget(s1);
            std::cast::forget(s2);
        }
    }
}
<|endoftext|>


<commit_before>use ffi::*;

use pipeline::Pipeline;
use pipeline::PipelineT;
use element::Element;
use element::ElementT;
use bin::Bin;
use bin::BinT;
use bus::Bus;
use std::ffi::CString;
use std::ptr;

pub struct PlayBin{
    playbin: Pipeline
}

impl PlayBin{
    pub fn new(name: &str) -> Option<PlayBin>{
        let pipeline = Element::new("playbin",name);
        match pipeline{
            Some(p) => Some(PlayBin{ playbin: Pipeline{ pipeline: Bin{ bin: p} } }),
            None => None
        }
    }

    pub fn set_audio_sink(&self, audio_sink: &ElementT){
        self.set("audio-sink", unsafe{ audio_sink.gst_element() });
    }

    /*pub fn frame(&self) -> GBuffer{
        GBuffer::new(playbin.get<GstBuffer*>("frame"))
    }*/

    pub fn set_subtitle_font_desc(&self, font: &str){
        self.set("subtitle-font-desc",to_c_str!(font));
    }

    pub fn set_video_sink(&self, video_sink: &ElementT){
        self.set("video-sink", unsafe{ video_sink.gst_element() });
    }

    pub fn set_vis_plugin(&self, vis_plugin: &ElementT){
        self.set("vis-plugin", vis_plugin);
    }

    pub fn set_volume(&self, volume: f64){
        self.set("volume", volume);
    }

    pub fn set_connection_speed(&self, connection_speed: u64){
        self.set("connection-speed",connection_speed);
    }

    pub fn set_av_offset(&self, av_offset: i64){
        self.set("av-offset", av_offset);
    }

    pub fn set_buffer_duration(&self, buffer_duration: i64){
        self.set("buffer-duration",buffer_duration);
    }

    pub fn set_current_audio(&self, current_audio: i32){
        self.set("current-audio",current_audio);
    }

    pub fn set_current_text(&self, current_text: i32){
        self.set("current-text", current_text);
    }

    /*pub fn set_flags(&self, flags: GstPlayFlags){
        self.set("flags", flags);
    }*/

    pub fn mute(&self){
        self.set("mute", 1 as gboolean);
    }

    pub fn unmute(&self){
        self.set("mute", 0 as gboolean);
    }

    pub fn set_ring_buffer_max_size(&self, ring_buffer_max_size: u64){
        self.set("ring-buffer-max-size", ring_buffer_max_size);
    }

    pub fn set_source(&self, source: &ElementT){
        self.set("source", unsafe{ source.gst_element() });
    }

    pub fn set_subtitle_encoding(&self, encoding: &str){
        self.set("subtitle-encoding", to_c_str!(encoding));
    }

    pub fn set_suburi(&self, suburi: &str){
        self.set("suburi", to_c_str!(suburi));
    }

    pub fn set_text_sink(&self, textsink: &ElementT){
        self.set("text-sink", unsafe{ textsink.gst_element() });
    }

    pub fn set_uri(&self, uri: &str){
        self.set("uri", to_c_str!(uri));
    }

    pub fn set_force_aspect_ratio(&self, force_aspect_ratio: bool){
        self.set("force-aspect-ratio", force_aspect_ratio as gboolean);
    }

    pub fn set_audio_stream_combiner(&self, audio_stream_combiner: &ElementT){
        self.set("audio-stream-combiner", unsafe{ audio_stream_combiner.gst_element() });
    }

    pub fn set_video_stream_combiner(&self, video_stream_combiner: &ElementT){
        self.set("vide-stream-combiner", unsafe{ video_stream_combiner.gst_element() });
    }

    pub fn set_flags(&self, flags: i32){
        self.set("flags", flags);
    }

    pub fn set<T>(&self, name: &str, value: T){
        self.playbin.set(name,value);
    }
}

impl PipelineT for PlayBin{

    fn delay(&self) -> GstClockTime{
        self.playbin.delay()
    }

    fn set_delay(&self, delay: GstClockTime){
        self.playbin.set_delay(delay);
    }

    unsafe fn gst_pipeline(&self) -> *mut GstPipeline{
        self.playbin.gst_pipeline()
    }
}

impl BinT for PlayBin{

    unsafe fn gst_bin(&self) -> *mut GstBin{
        self.playbin.gst_bin()
    }

    fn add(&self, element: &ElementT) -> bool{
        self.playbin.add(element)
    }

    fn remove(&self, element: &ElementT) -> bool{
        self.playbin.remove(element)
    }

    fn get_by_name(&self, name: &str) -> Option<Element>{
        self.playbin.get_by_name(name)
    }

    fn recalculate_latency(&self) -> bool{
        self.playbin.recalculate_latency()
    }

    fn set_async_handling(&self, async: bool){
        self.playbin.set_async_handling(async);
    }

    fn set_message_forward(&self, forward: bool){
        self.playbin.set_message_forward(forward);
    }
}

impl ElementT for PlayBin{

    fn link(&mut self, dst: &mut ElementT) -> bool{
        self.playbin.link(dst)
    }

    fn unlink(&mut self, dst: &mut ElementT){
        self.playbin.unlink(dst);
    }

    fn bus(&self) -> Option<Bus>{
        self.playbin.bus()
    }

    fn name(&self) -> String{
        self.playbin.name()
    }

    fn set_name(&mut self, name: &str){
        self.playbin.set_name(name);
    }

    fn set_state(&mut self, state: GstState) -> GstStateChangeReturn{
        self.playbin.set_state(state)
    }

    fn get_state(&self, timeout: GstClockTime) -> (GstState, GstState, GstStateChangeReturn){
        self.playbin.get_state(timeout)
    }

    fn send_event(&mut self, event: *mut GstEvent) -> bool{
        self.playbin.send_event(event)
    }

    fn seek_simple(&mut self, format: GstFormat, flags: GstSeekFlags, pos: i64) -> bool{
        self.playbin.seek_simple(format, flags, pos)
    }

    fn seek(&mut self, rate: f64, format: GstFormat, flags: GstSeekFlags, start_type: GstSeekType, start: i64, stop_type: GstSeekType, stop: i64) -> bool{
        self.playbin.seek(rate, format, flags, start_type, start, stop_type, stop)
    }

    fn seek_async(&mut self, rate: f64, format: GstFormat, flags: GstSeekFlags, start_type: GstSeekType, start: i64, stop_type: GstSeekType, stop: i64){
        self.playbin.seek_async(rate,format,flags,start_type,start,stop_type,stop);
    }

    fn query_duration(&self, format: GstFormat) -> Option<i64>{
        self.playbin.query_duration(format)
    }

    fn query_position(&self, format: GstFormat) -> Option<i64>{
        self.playbin.query_position(format)
    }

    fn duration_ns(&self) -> Option<i64>{
        self.playbin.duration_ns()
    }

    fn duration_s(&self) -> Option<f64>{
        self.playbin.duration_s()
    }

    fn position_ns(&self) -> i64{
        self.playbin.position_ns()
    }

    fn position_pct(&self) -> Option<f64>{
        self.playbin.position_pct()
    }

    fn position_s(&self) -> f64{
        self.playbin.position_s()
    }

    fn speed(&self) -> f64{
        self.playbin.speed()
    }

    fn set_position_ns(&mut self, ns: i64) -> bool{
        self.playbin.set_position_ns(ns)
    }

    fn set_position_s(&mut self, s: f64) -> bool{
        self.playbin.set_position_s(s)
    }

    fn set_position_pct(&mut self, pct: f64) -> bool{
        self.playbin.set_position_pct(pct)
    }

    fn set_speed(&mut self, speed: f64) -> bool{
        self.playbin.set_speed(speed)
    }

    fn set_position_ns_async(&mut self, ns: i64){
        self.playbin.set_position_ns_async(ns);
    }

    fn set_position_s_async(&mut self, s: f64){
        self.playbin.set_position_s_async(s);
    }

    fn set_position_pct_async(&mut self, pct: f64) -> bool{
        self.playbin.set_position_pct_async(pct)
    }

    fn set_speed_async(&mut self, speed: f64) -> bool{
        self.playbin.set_speed_async(speed)
    }

    unsafe fn gst_element(&self) -> *const GstElement{
        self.playbin.gst_element()
    }

    unsafe fn gst_element_mut(&mut self) -> *mut GstElement{
        self.playbin.gst_element_mut()
    }

    /*fn set<T>(&self, name: &str, value: T){
        self.playbin.set(name,value);
    }*/

    fn set_null_state(&mut self){
        self.playbin.set_null_state();
    }

    fn set_ready_state(&mut self){
        self.playbin.set_ready_state();
    }

    fn pause(&mut self){
        self.playbin.pause();
    }

    fn play(&mut self){
        self.playbin.play();
    }

    fn is_paused(&self) -> bool{
        self.playbin.is_paused()
    }

    fn is_playing(&self) -> bool{
        self.playbin.is_playing()
    }

    fn is_null_state(&self) -> bool{
        self.playbin.is_null_state()
    }

    fn is_ready_state(&self) -> bool{
        self.playbin.is_ready_state()
    }
}
<commit_msg>playbin: remove warnings<commit_after>use ffi::*;

use pipeline::Pipeline;
use pipeline::PipelineT;
use element::Element;
use element::ElementT;
use bin::Bin;
use bin::BinT;
use bus::Bus;
use std::ffi::CString;

pub struct PlayBin{
    playbin: Pipeline
}

impl PlayBin{
    pub fn new(name: &str) -> Option<PlayBin>{
        let pipeline = Element::new("playbin",name);
        match pipeline{
            Some(p) => Some(PlayBin{ playbin: Pipeline{ pipeline: Bin{ bin: p} } }),
            None => None
        }
    }

    pub fn set_audio_sink(&self, audio_sink: &ElementT){
        self.set("audio-sink", unsafe{ audio_sink.gst_element() });
    }

    /*pub fn frame(&self) -> GBuffer{
        GBuffer::new(playbin.get<GstBuffer*>("frame"))
    }*/

    pub fn set_subtitle_font_desc(&self, font: &str){
        self.set("subtitle-font-desc",to_c_str!(font));
    }

    pub fn set_video_sink(&self, video_sink: &ElementT){
        self.set("video-sink", unsafe{ video_sink.gst_element() });
    }

    pub fn set_vis_plugin(&self, vis_plugin: &ElementT){
        self.set("vis-plugin", vis_plugin);
    }

    pub fn set_volume(&self, volume: f64){
        self.set("volume", volume);
    }

    pub fn set_connection_speed(&self, connection_speed: u64){
        self.set("connection-speed",connection_speed);
    }

    pub fn set_av_offset(&self, av_offset: i64){
        self.set("av-offset", av_offset);
    }

    pub fn set_buffer_duration(&self, buffer_duration: i64){
        self.set("buffer-duration",buffer_duration);
    }

    pub fn set_current_audio(&self, current_audio: i32){
        self.set("current-audio",current_audio);
    }

    pub fn set_current_text(&self, current_text: i32){
        self.set("current-text", current_text);
    }

    /*pub fn set_flags(&self, flags: GstPlayFlags){
        self.set("flags", flags);
    }*/

    pub fn mute(&self){
        self.set("mute", 1 as gboolean);
    }

    pub fn unmute(&self){
        self.set("mute", 0 as gboolean);
    }

    pub fn set_ring_buffer_max_size(&self, ring_buffer_max_size: u64){
        self.set("ring-buffer-max-size", ring_buffer_max_size);
    }

    pub fn set_source(&self, source: &ElementT){
        self.set("source", unsafe{ source.gst_element() });
    }

    pub fn set_subtitle_encoding(&self, encoding: &str){
        self.set("subtitle-encoding", to_c_str!(encoding));
    }

    pub fn set_suburi(&self, suburi: &str){
        self.set("suburi", to_c_str!(suburi));
    }

    pub fn set_text_sink(&self, textsink: &ElementT){
        self.set("text-sink", unsafe{ textsink.gst_element() });
    }

    pub fn set_uri(&self, uri: &str){
        self.set("uri", to_c_str!(uri));
    }

    pub fn set_force_aspect_ratio(&self, force_aspect_ratio: bool){
        self.set("force-aspect-ratio", force_aspect_ratio as gboolean);
    }

    pub fn set_audio_stream_combiner(&self, audio_stream_combiner: &ElementT){
        self.set("audio-stream-combiner", unsafe{ audio_stream_combiner.gst_element() });
    }

    pub fn set_video_stream_combiner(&self, video_stream_combiner: &ElementT){
        self.set("vide-stream-combiner", unsafe{ video_stream_combiner.gst_element() });
    }

    pub fn set_flags(&self, flags: i32){
        self.set("flags", flags);
    }

    pub fn set<T>(&self, name: &str, value: T){
        self.playbin.set(name,value);
    }
}

impl PipelineT for PlayBin{

    fn delay(&self) -> GstClockTime{
        self.playbin.delay()
    }

    fn set_delay(&self, delay: GstClockTime){
        self.playbin.set_delay(delay);
    }

    unsafe fn gst_pipeline(&self) -> *mut GstPipeline{
        self.playbin.gst_pipeline()
    }
}

impl BinT for PlayBin{

    unsafe fn gst_bin(&self) -> *mut GstBin{
        self.playbin.gst_bin()
    }

    fn add(&self, element: &ElementT) -> bool{
        self.playbin.add(element)
    }

    fn remove(&self, element: &ElementT) -> bool{
        self.playbin.remove(element)
    }

    fn get_by_name(&self, name: &str) -> Option<Element>{
        self.playbin.get_by_name(name)
    }

    fn recalculate_latency(&self) -> bool{
        self.playbin.recalculate_latency()
    }

    fn set_async_handling(&self, async: bool){
        self.playbin.set_async_handling(async);
    }

    fn set_message_forward(&self, forward: bool){
        self.playbin.set_message_forward(forward);
    }
}

impl ElementT for PlayBin{

    fn link(&mut self, dst: &mut ElementT) -> bool{
        self.playbin.link(dst)
    }

    fn unlink(&mut self, dst: &mut ElementT){
        self.playbin.unlink(dst);
    }

    fn bus(&self) -> Option<Bus>{
        self.playbin.bus()
    }

    fn name(&self) -> String{
        self.playbin.name()
    }

    fn set_name(&mut self, name: &str){
        self.playbin.set_name(name);
    }

    fn set_state(&mut self, state: GstState) -> GstStateChangeReturn{
        self.playbin.set_state(state)
    }

    fn get_state(&self, timeout: GstClockTime) -> (GstState, GstState, GstStateChangeReturn){
        self.playbin.get_state(timeout)
    }

    fn send_event(&mut self, event: *mut GstEvent) -> bool{
        self.playbin.send_event(event)
    }

    fn seek_simple(&mut self, format: GstFormat, flags: GstSeekFlags, pos: i64) -> bool{
        self.playbin.seek_simple(format, flags, pos)
    }

    fn seek(&mut self, rate: f64, format: GstFormat, flags: GstSeekFlags, start_type: GstSeekType, start: i64, stop_type: GstSeekType, stop: i64) -> bool{
        self.playbin.seek(rate, format, flags, start_type, start, stop_type, stop)
    }

    fn seek_async(&mut self, rate: f64, format: GstFormat, flags: GstSeekFlags, start_type: GstSeekType, start: i64, stop_type: GstSeekType, stop: i64){
        self.playbin.seek_async(rate,format,flags,start_type,start,stop_type,stop);
    }

    fn query_duration(&self, format: GstFormat) -> Option<i64>{
        self.playbin.query_duration(format)
    }

    fn query_position(&self, format: GstFormat) -> Option<i64>{
        self.playbin.query_position(format)
    }

    fn duration_ns(&self) -> Option<i64>{
        self.playbin.duration_ns()
    }

    fn duration_s(&self) -> Option<f64>{
        self.playbin.duration_s()
    }

    fn position_ns(&self) -> i64{
        self.playbin.position_ns()
    }

    fn position_pct(&self) -> Option<f64>{
        self.playbin.position_pct()
    }

    fn position_s(&self) -> f64{
        self.playbin.position_s()
    }

    fn speed(&self) -> f64{
        self.playbin.speed()
    }

    fn set_position_ns(&mut self, ns: i64) -> bool{
        self.playbin.set_position_ns(ns)
    }

    fn set_position_s(&mut self, s: f64) -> bool{
        self.playbin.set_position_s(s)
    }

    fn set_position_pct(&mut self, pct: f64) -> bool{
        self.playbin.set_position_pct(pct)
    }

    fn set_speed(&mut self, speed: f64) -> bool{
        self.playbin.set_speed(speed)
    }

    fn set_position_ns_async(&mut self, ns: i64){
        self.playbin.set_position_ns_async(ns);
    }

    fn set_position_s_async(&mut self, s: f64){
        self.playbin.set_position_s_async(s);
    }

    fn set_position_pct_async(&mut self, pct: f64) -> bool{
        self.playbin.set_position_pct_async(pct)
    }

    fn set_speed_async(&mut self, speed: f64) -> bool{
        self.playbin.set_speed_async(speed)
    }

    unsafe fn gst_element(&self) -> *const GstElement{
        self.playbin.gst_element()
    }

    unsafe fn gst_element_mut(&mut self) -> *mut GstElement{
        self.playbin.gst_element_mut()
    }

    /*fn set<T>(&self, name: &str, value: T){
        self.playbin.set(name,value);
    }*/

    fn set_null_state(&mut self){
        self.playbin.set_null_state();
    }

    fn set_ready_state(&mut self){
        self.playbin.set_ready_state();
    }

    fn pause(&mut self){
        self.playbin.pause();
    }

    fn play(&mut self){
        self.playbin.play();
    }

    fn is_paused(&self) -> bool{
        self.playbin.is_paused()
    }

    fn is_playing(&self) -> bool{
        self.playbin.is_playing()
    }

    fn is_null_state(&self) -> bool{
        self.playbin.is_null_state()
    }

    fn is_ready_state(&self) -> bool{
        self.playbin.is_ready_state()
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::error;
use std::fmt;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::ffi::CString;
use gl;
use gl::types::*;
use types::GLError;
use context::{AContext, ContextOf};
use shader::Shader;
use uniform_data::{UniformData, UniformDatumType, UniformPrimitiveType};

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

unsafe fn _get_program_iv(program: &Program,
                          pname: GLenum,
                          params: *mut GLint)
{
    gl::GetProgramiv(program.gl_id(), pname, params);
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`pname` is not an accepted value",
        GLError::InvalidValue => "`program` is not a value generated by OpenGL",
        GLError::InvalidOperation => "`program` does not refer to a program object",
        _ => "Unknown error"
    }
}

pub struct ProgramBuilder<'a, C>
    where C: AContext + 'a
{
    gl: &'a C,
    shaders: &'a [Shader]
}

impl<'a, C> ProgramBuilder<'a, C>
    where C: AContext
{
    pub fn new(gl: &'a C, shaders: &'a [Shader])
        -> Self
    {
        ProgramBuilder { gl: gl, shaders: shaders }
    }

    pub fn try_unwrap(self) -> Result<Program, GLError> {
        unsafe {
            let mut program = try! {
                self.gl.create_program().or_else(|_| {
                    let msg = "Error creating OpenGL program";
                    Err(GLError::Message(msg.to_owned()))
                })
            };

            for shader in self.shaders {
                self.gl.attach_shader(&mut program, shader);
            }

            try!(self.gl.link_program(&mut program));
            Ok(program)
        }
    }

    pub fn unwrap(self) -> Program {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextProgramBuilderExt: AContext + Sized {
    fn build_program<'a>(&'a self, shaders: &'a [Shader])
        -> ProgramBuilder<'a, Self>;
}

impl<C: AContext> ContextProgramBuilderExt for C {
    fn build_program<'a>(&'a self, shaders: &'a [Shader])
        -> ProgramBuilder<'a, C>
    {
        ProgramBuilder::new(self, shaders)
    }
}

pub unsafe trait ContextProgramExt {
    unsafe fn create_program(&self) -> Result<Program, ()> {
        let id = gl::CreateProgram();
        if id > 0 {
            Ok(Program { gl_id: id })
        }
        else {
            Err(())
        }
    }

    fn attach_shader(&self, program: &mut Program, shader: &Shader) {
        unsafe {
            gl::AttachShader(program.gl_id(), shader.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "One of either `program` or `shader` is not an OpenGL object",
                GLError::InvalidOperation => "`shader` is already attached to `program`, `shader` is not a shader object, or `program` is not a program object",
                _ => "Unknown error"
            }
        }
    }

    fn link_program(&self, program: &mut Program) -> Result<(), GLError> {
        let success = unsafe {
            gl::LinkProgram(program.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is not a value from OpenGL",
                GLError::InvalidOperation => "`program` is not a program object",
                _ => "Unknown error"
            }

            let mut link_status : GLint = 0;
            _get_program_iv(program,
                            gl::LINK_STATUS,
                            &mut link_status as *mut GLint);

            link_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            let msg = match self.get_program_info_log(&program) {
                Some(s) => { s },
                None => { String::from("[Unknown program error]") }
            };
            Err(GLError::Message(msg))
        }
    }

    fn get_program_info_log(&self, program: &Program) -> Option<String> {
        unsafe {
            let mut info_length : GLint = 0;
            _get_program_iv(program,
                            gl::INFO_LOG_LENGTH,
                            &mut info_length as *mut GLint);

            if info_length > 0 {
                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetProgramInfoLog(program.gl_id(),
                                      info_length,
                                      ptr::null_mut(),
                                      bytes.as_mut_ptr() as *mut GLchar);
                dbg_gl_sanity_check! {
                    GLError::InvalidValue => "`program` is not a value generated by OpenGL, or `maxLength` < 0",
                    GLError::InvalidOperation => "`program` is not a program object",
                    _ => "Unknown error"
                }
                bytes.set_len((info_length - 1) as usize);

                String::from_utf8(bytes).ok()
            }
            else {
                None
            }
        }
    }

    fn get_attrib_location<'a>(&self, program: &Program, name: &'a str)
        -> Result<ProgramAttrib, UnknownProgramAttrib<'a>>
    {
        let err = Err(UnknownProgramAttrib { name: name });

        let c_str = match CString::new(name) {
            Ok(s) => { s },
            Err(_) => { return err }
        };

        let str_ptr = c_str.as_ptr() as *const GLchar;
        unsafe {
            let index = gl::GetAttribLocation(program.gl_id(), str_ptr);
            dbg_gl_error! {
                GLError::InvalidOperation => "`program` has not been linked, `program` is not a program object, or `program` is not a value generated by OpenGL",
                _ => "Unknown error"
            }

            if index >= 0 {
                Ok(ProgramAttrib { gl_index: index as GLuint })
            }
            else {
                err
            }
        }
    }

    fn get_uniform_location<'a>(&self, program: &Program, name: &'a str)
        -> Result<ProgramUniform, UnknownProgramUniform<'a>>
    {
        let err = Err(UnknownProgramUniform { name: name });

        let c_str = match CString::new(name) {
            Ok(s) => { s },
            Err(_) => { return err; }
        };

        let str_ptr = c_str.as_ptr() as *const GLchar;
        unsafe {
            let index = gl::GetUniformLocation(program.gl_id(), str_ptr);
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is not a value generated by OpenGL",
                GLError::InvalidOperation => "`program` is not a program object, or has not been successfully linked",
                _ => "Unknown error"
            }

            if index >= 0 {
                Ok(ProgramUniform { gl_index: index as GLuint })
            }
            else {
                err
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextProgramExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'b, B, F, P, R, T> ContextProgramExt
    for &'b mut ContextOf<B, F, P, R, T>
{

}

pub trait ProgramContext: AContext {
    type Rest: AContext;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest);
}

impl<B, F, P, R, T> ProgramContext for ContextOf<B, F, P, R, T>
    where P: BorrowMut<ProgramBinder>
{
    type Rest = ContextOf<B, F, (), R, T>;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest)
    {
        let (mut program_binder, rest) = self.split_program();
        (program_binder.borrow_mut().bind(program), rest)
    }
}

impl<'b, B, F, P, R, T> ProgramContext for &'b mut ContextOf<B, F, P, R, T>
    where P: BorrowMut<ProgramBinder>
{
    type Rest = ContextOf<&'b mut B, &'b mut F, (), &'b mut R, &'b mut T>;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest)
    {
        let gl = self.mut_into();
        let (program_binder, rest): (&mut P, _) = gl.split_program();
        (program_binder.borrow_mut().bind(program), rest)
    }
}

pub struct ProgramBinding<'a> {
    phantom: PhantomData<&'a mut Program>
}

impl<'a> ProgramBinding<'a> {
    pub fn set_uniform<T>(&self, uniform: ProgramUniform, val: T)
        where T: UniformData
    {
        let idx = uniform.gl_index as GLint;
        let count = val.uniform_elements() as GLsizei;
        let ptr = val.uniform_bytes().as_ptr();
        unsafe {
            match T::uniform_datum_type() {
                UniformDatumType::Vec1(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform1fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform1iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec2(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform2fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform2iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec3(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform3fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform3iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec4(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform4fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform4iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Matrix2x2 => {
                    gl::UniformMatrix2fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
                UniformDatumType::Matrix3x3 => {
                    gl::UniformMatrix3fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
                UniformDatumType::Matrix4x4 => {
                    gl::UniformMatrix4fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
            }

            dbg_gl_error! {
                GLError::InvalidOperation => "Invalid uniform operation",
                GLError::InvalidValue => "`count` < 0 or `transpose` is not GL_FALSE",
                _ => "Unknown error"
            }
        }
    }
}

pub struct ProgramBinder;
impl ProgramBinder {
    pub fn bind<'a>(&mut self, program: &'a mut Program) -> ProgramBinding<'a>
    {
        let binding = ProgramBinding { phantom: PhantomData };
        unsafe {
            gl::UseProgram(program.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is neither 0 nor an object generated by OpenGL",
                GLError::InvalidOperation => "`program` is not a program object or `program` could not be made part of the current state",
                _ => "Unknown error"
            }
        }
        binding
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramUniform {
    pub gl_index: GLuint
}

#[derive(Debug)]
pub struct UnknownProgramAttrib<'a> {
    name: &'a str
}

impl<'a> fmt::Display for UnknownProgramAttrib<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Unknown program attribute: {:?}", self.name)
    }
}

impl<'a> error::Error for UnknownProgramAttrib<'a> {
    fn description(&self) -> &str {
        "The desired program attribute was not found"
    }
}

#[derive(Debug)]
pub struct UnknownProgramUniform<'a> {
    name: &'a str
}

impl<'a> fmt::Display for UnknownProgramUniform<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Unknown program uniform: {:?}", self.name)
    }
}

impl<'a> error::Error for UnknownProgramUniform<'a> {
    fn description(&self) -> &str {
        "The desired program uniform was not found"
    }
}
<commit_msg>Move `ProgramBinding.set_uniform()` to `ContextProgramExt.set_uniform()`<commit_after>use std::ptr;
use std::error;
use std::fmt;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::ffi::CString;
use gl;
use gl::types::*;
use types::GLError;
use context::{AContext, ContextOf};
use shader::Shader;
use uniform_data::{UniformData, UniformDatumType, UniformPrimitiveType};

pub struct Program {
    gl_id: GLuint
}

impl Program {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteProgram(self.gl_id);
        }
    }
}

unsafe fn _get_program_iv(program: &Program,
                          pname: GLenum,
                          params: *mut GLint)
{
    gl::GetProgramiv(program.gl_id(), pname, params);
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`pname` is not an accepted value",
        GLError::InvalidValue => "`program` is not a value generated by OpenGL",
        GLError::InvalidOperation => "`program` does not refer to a program object",
        _ => "Unknown error"
    }
}

pub struct ProgramBuilder<'a, C>
    where C: AContext + 'a
{
    gl: &'a C,
    shaders: &'a [Shader]
}

impl<'a, C> ProgramBuilder<'a, C>
    where C: AContext
{
    pub fn new(gl: &'a C, shaders: &'a [Shader])
        -> Self
    {
        ProgramBuilder { gl: gl, shaders: shaders }
    }

    pub fn try_unwrap(self) -> Result<Program, GLError> {
        unsafe {
            let mut program = try! {
                self.gl.create_program().or_else(|_| {
                    let msg = "Error creating OpenGL program";
                    Err(GLError::Message(msg.to_owned()))
                })
            };

            for shader in self.shaders {
                self.gl.attach_shader(&mut program, shader);
            }

            try!(self.gl.link_program(&mut program));
            Ok(program)
        }
    }

    pub fn unwrap(self) -> Program {
        self.try_unwrap().unwrap()
    }
}

pub trait ContextProgramBuilderExt: AContext + Sized {
    fn build_program<'a>(&'a self, shaders: &'a [Shader])
        -> ProgramBuilder<'a, Self>;
}

impl<C: AContext> ContextProgramBuilderExt for C {
    fn build_program<'a>(&'a self, shaders: &'a [Shader])
        -> ProgramBuilder<'a, C>
    {
        ProgramBuilder::new(self, shaders)
    }
}

pub unsafe trait ContextProgramExt {
    unsafe fn create_program(&self) -> Result<Program, ()> {
        let id = gl::CreateProgram();
        if id > 0 {
            Ok(Program { gl_id: id })
        }
        else {
            Err(())
        }
    }

    fn attach_shader(&self, program: &mut Program, shader: &Shader) {
        unsafe {
            gl::AttachShader(program.gl_id(), shader.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "One of either `program` or `shader` is not an OpenGL object",
                GLError::InvalidOperation => "`shader` is already attached to `program`, `shader` is not a shader object, or `program` is not a program object",
                _ => "Unknown error"
            }
        }
    }

    fn link_program(&self, program: &mut Program) -> Result<(), GLError> {
        let success = unsafe {
            gl::LinkProgram(program.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is not a value from OpenGL",
                GLError::InvalidOperation => "`program` is not a program object",
                _ => "Unknown error"
            }

            let mut link_status : GLint = 0;
            _get_program_iv(program,
                            gl::LINK_STATUS,
                            &mut link_status as *mut GLint);

            link_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            let msg = match self.get_program_info_log(&program) {
                Some(s) => { s },
                None => { String::from("[Unknown program error]") }
            };
            Err(GLError::Message(msg))
        }
    }

    fn get_program_info_log(&self, program: &Program) -> Option<String> {
        unsafe {
            let mut info_length : GLint = 0;
            _get_program_iv(program,
                            gl::INFO_LOG_LENGTH,
                            &mut info_length as *mut GLint);

            if info_length > 0 {
                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetProgramInfoLog(program.gl_id(),
                                      info_length,
                                      ptr::null_mut(),
                                      bytes.as_mut_ptr() as *mut GLchar);
                dbg_gl_sanity_check! {
                    GLError::InvalidValue => "`program` is not a value generated by OpenGL, or `maxLength` < 0",
                    GLError::InvalidOperation => "`program` is not a program object",
                    _ => "Unknown error"
                }
                bytes.set_len((info_length - 1) as usize);

                String::from_utf8(bytes).ok()
            }
            else {
                None
            }
        }
    }

    fn get_attrib_location<'a>(&self, program: &Program, name: &'a str)
        -> Result<ProgramAttrib, UnknownProgramAttrib<'a>>
    {
        let err = Err(UnknownProgramAttrib { name: name });

        let c_str = match CString::new(name) {
            Ok(s) => { s },
            Err(_) => { return err }
        };

        let str_ptr = c_str.as_ptr() as *const GLchar;
        unsafe {
            let index = gl::GetAttribLocation(program.gl_id(), str_ptr);
            dbg_gl_error! {
                GLError::InvalidOperation => "`program` has not been linked, `program` is not a program object, or `program` is not a value generated by OpenGL",
                _ => "Unknown error"
            }

            if index >= 0 {
                Ok(ProgramAttrib { gl_index: index as GLuint })
            }
            else {
                err
            }
        }
    }

    fn get_uniform_location<'a>(&self, program: &Program, name: &'a str)
        -> Result<ProgramUniform, UnknownProgramUniform<'a>>
    {
        let err = Err(UnknownProgramUniform { name: name });

        let c_str = match CString::new(name) {
            Ok(s) => { s },
            Err(_) => { return err; }
        };

        let str_ptr = c_str.as_ptr() as *const GLchar;
        unsafe {
            let index = gl::GetUniformLocation(program.gl_id(), str_ptr);
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is not a value generated by OpenGL",
                GLError::InvalidOperation => "`program` is not a program object, or has not been successfully linked",
                _ => "Unknown error"
            }

            if index >= 0 {
                Ok(ProgramUniform { gl_index: index as GLuint })
            }
            else {
                err
            }
        }
    }

    fn set_uniform<T>(&self,
                      _gl_program: &ProgramBinding,
                      uniform: ProgramUniform,
                      val: T)
        where T: UniformData
    {
        let idx = uniform.gl_index as GLint;
        let count = val.uniform_elements() as GLsizei;
        let ptr = val.uniform_bytes().as_ptr();
        unsafe {
            match T::uniform_datum_type() {
                UniformDatumType::Vec1(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform1fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform1iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec2(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform2fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform2iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec3(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform3fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform3iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Vec4(p) => {
                    match p {
                        UniformPrimitiveType::Float => {
                            gl::Uniform4fv(idx, count, ptr as *const GLfloat);
                        },
                        UniformPrimitiveType::Int => {
                            gl::Uniform4iv(idx, count, ptr as *const GLint);
                        }
                    }
                },
                UniformDatumType::Matrix2x2 => {
                    gl::UniformMatrix2fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
                UniformDatumType::Matrix3x3 => {
                    gl::UniformMatrix3fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
                UniformDatumType::Matrix4x4 => {
                    gl::UniformMatrix4fv(idx,
                                         count,
                                         gl::FALSE,
                                         ptr as *const GLfloat);
                },
            }

            dbg_gl_error! {
                GLError::InvalidOperation => "Invalid uniform operation",
                GLError::InvalidValue => "`count` < 0 or `transpose` is not GL_FALSE",
                _ => "Unknown error"
            }
        }
    }
}

unsafe impl<B, F, P, R, T> ContextProgramExt for ContextOf<B, F, P, R, T> {

}

unsafe impl<'b, B, F, P, R, T> ContextProgramExt
    for &'b mut ContextOf<B, F, P, R, T>
{

}

pub trait ProgramContext: AContext {
    type Rest: AContext;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest);
}

impl<B, F, P, R, T> ProgramContext for ContextOf<B, F, P, R, T>
    where P: BorrowMut<ProgramBinder>
{
    type Rest = ContextOf<B, F, (), R, T>;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest)
    {
        let (mut program_binder, rest) = self.split_program();
        (program_binder.borrow_mut().bind(program), rest)
    }
}

impl<'b, B, F, P, R, T> ProgramContext for &'b mut ContextOf<B, F, P, R, T>
    where P: BorrowMut<ProgramBinder>
{
    type Rest = ContextOf<&'b mut B, &'b mut F, (), &'b mut R, &'b mut T>;

    fn use_program<'a>(self, program: &'a mut Program)
        -> (ProgramBinding<'a>, Self::Rest)
    {
        let gl = self.mut_into();
        let (program_binder, rest): (&mut P, _) = gl.split_program();
        (program_binder.borrow_mut().bind(program), rest)
    }
}

pub struct ProgramBinding<'a> {
    phantom: PhantomData<&'a mut Program>
}

pub struct ProgramBinder;
impl ProgramBinder {
    pub fn bind<'a>(&mut self, program: &'a mut Program) -> ProgramBinding<'a>
    {
        let binding = ProgramBinding { phantom: PhantomData };
        unsafe {
            gl::UseProgram(program.gl_id());
            dbg_gl_error! {
                GLError::InvalidValue => "`program` is neither 0 nor an object generated by OpenGL",
                GLError::InvalidOperation => "`program` is not a program object or `program` could not be made part of the current state",
                _ => "Unknown error"
            }
        }
        binding
    }
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramAttrib {
    pub gl_index: GLuint
}

#[derive(Debug, Clone, Copy)]
pub struct ProgramUniform {
    pub gl_index: GLuint
}

#[derive(Debug)]
pub struct UnknownProgramAttrib<'a> {
    name: &'a str
}

impl<'a> fmt::Display for UnknownProgramAttrib<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Unknown program attribute: {:?}", self.name)
    }
}

impl<'a> error::Error for UnknownProgramAttrib<'a> {
    fn description(&self) -> &str {
        "The desired program attribute was not found"
    }
}

#[derive(Debug)]
pub struct UnknownProgramUniform<'a> {
    name: &'a str
}

impl<'a> fmt::Display for UnknownProgramUniform<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Unknown program uniform: {:?}", self.name)
    }
}

impl<'a> error::Error for UnknownProgramUniform<'a> {
    fn description(&self) -> &str {
        "The desired program uniform was not found"
    }
}
<|endoftext|>


<commit_before>intrinsics! {
    // Implementation from gcc
    // https://raw.githubusercontent.com/gcc-mirror/gcc/master/libgcc/config/epiphany/mulsi3.c
    pub extern "C" fn __mulsi3(a: u32, b: u32) -> u32 {
        let (mut a, mut b) = (a, b);
        let mut r: usize = 0;

        while a > 0 {
            if a & 1 > 0 {
                r += b;
            }
            a >>= 1;
            b <<= 1;
        }

        r
    }
}
<commit_msg>Fix compile on riscv again<commit_after>intrinsics! {
    // Implementation from gcc
    // https://raw.githubusercontent.com/gcc-mirror/gcc/master/libgcc/config/epiphany/mulsi3.c
    pub extern "C" fn __mulsi3(a: u32, b: u32) -> u32 {
        let (mut a, mut b) = (a, b);
        let mut r = 0;

        while a > 0 {
            if a & 1 > 0 {
                r += b;
            }
            a >>= 1;
            b <<= 1;
        }

        r
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate serde;

use iron::{Iron, Request, Response, IronResult};
use self::serde::ser::{ Serialize, Serializer };

pub type ServiceID = String;

#[derive(Clone, Serialize)]
pub struct ServiceProperties {
    pub id: ServiceID,
    pub name: String,
    pub description: String,
    pub http_url: String,
    pub ws_url: String
}

pub trait Service : Drop + Send {
    fn get_properties(&self) -> ServiceProperties;
    fn start(&self);
    fn stop(&self);
    fn process_request(&self, req: &Request) -> IronResult<Response>;
}

impl Serialize for Service {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let props = self.get_properties();
        props.serialize(serializer)
    }
}

pub trait ServiceAdapter {
    fn get_name(&self) -> String;
    fn start(&self);
    fn stop(&self);
}
<commit_msg>Clean up warnings in service.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate serde;

use iron::{Request, Response, IronResult};
use self::serde::ser::{ Serialize, Serializer };

pub type ServiceID = String;

#[derive(Clone, Serialize)]
pub struct ServiceProperties {
    pub id: ServiceID,
    pub name: String,
    pub description: String,
    pub http_url: String,
    pub ws_url: String
}

pub trait Service : Drop + Send {
    fn get_properties(&self) -> ServiceProperties;
    fn start(&self);
    fn stop(&self);
    fn process_request(&self, req: &Request) -> IronResult<Response>;
}

impl Serialize for Service {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let props = self.get_properties();
        props.serialize(serializer)
    }
}

pub trait ServiceAdapter {
    fn get_name(&self) -> String;
    fn start(&self);
    fn stop(&self);
}
<|endoftext|>