<commit_before>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

use resource::Res;
use scene::Scene;
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  shading_commands: Vec<Pipe<'a, ShadingCommand<'a>>>
}

impl<'a> RenderLayer<'a> {
  pub fn new() -> Self {
    RenderLayer {
      shading_commands: Vec::new()
    }
  }

  pub fn push_shading_command(&mut self, shading_command: Pipe<'a, ShadingCommand<'a>>) {
    self.shading_commands.push(shading_command);
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, scene: &mut Scene) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: scene.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    unimplemented!()
    //self.consume_tagged_nodes(TaggedNode { node: root, framebuffer_index: None });
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Composite(left, right, eq, src_fct, dst_fct) => self.composite(*left, *right, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];
    let black = [0., 0., 0., 1.];

    Pipeline::new(fb, black, &[], &[], &layer.shading_commands).run();

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new(Some((eq, src_fct, dst_fct)), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<commit_msg>Implemented Compositor::display.<commit_after>use luminance::{Depth32F, Dim2, Flat, Framebuffer, Mode, RGBA32F, Tess, Texture, Uniform, Unit};
use luminance::pipeline::{Pipe, Pipeline, RenderCommand, ShadingCommand};
use luminance::tess::TessRender;
use std::ops::{Add, Sub, Mul};

pub use luminance::{Equation, Factor};

use resource::Res;
use scene::Scene;
use shader::Program;

/// Simple texture that can be embedded into a compositing graph.
pub type TextureLayer<'a> = &'a ColorMap;

pub type ColorMap = Texture<Flat, Dim2, RGBA32F>;
pub type DepthMap = Texture<Flat, Dim2, Depth32F>;

/// Render layer used to host renders.
pub struct RenderLayer<'a> {
  shading_commands: Vec<Pipe<'a, ShadingCommand<'a>>>
}

impl<'a> RenderLayer<'a> {
  pub fn new() -> Self {
    RenderLayer {
      shading_commands: Vec::new()
    }
  }

  pub fn push_shading_command(&mut self, shading_command: Pipe<'a, ShadingCommand<'a>>) {
    self.shading_commands.push(shading_command);
  }
}

/// Compositing node.
pub enum Node<'a> {
  /// A render node.
  ///
  /// Contains render layer.
  Render(RenderLayer<'a>),
  /// A texture node.
  ///
  /// Contains a single texture.
  Texture(TextureLayer<'a>),
  /// Composite node.
  ///
  /// Composite nodes are used to blend two compositing nodes according to a given `Equation` and
  /// two blending `Factor`s for source and destination, respectively.
  Composite(Box<Node<'a>>, Box<Node<'a>>, Equation, Factor, Factor)
}

impl<'a> Node<'a> {
  /// Compose this node with another one.
  pub fn compose_with(self, other: Self, eq: Equation, src_fct: Factor, dst_fct: Factor) -> Self {
    Node::Composite(Box::new(self), Box::new(other), eq, src_fct, dst_fct)
  }
}

impl<'a> From<RenderLayer<'a>> for Node<'a> {
  fn from(layer: RenderLayer<'a>) -> Self {
    Node::Render(layer)
  }
}

impl<'a> From<TextureLayer<'a>> for Node<'a> {
  fn from(texture: TextureLayer<'a>) -> Self {
    Node::Texture(texture)
  }
}

impl<'a> Add for Node<'a> {
  type Output = Self;

  fn add(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::One, Factor::One)
  }
}

impl<'a> Sub for Node<'a> {
  type Output = Self;

  fn sub(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Subtract, Factor::One, Factor::One)
  }
}

impl<'a> Mul for Node<'a> {
  type Output = Self;

  fn mul(self, rhs: Self) -> Self {
    self.compose_with(rhs, Equation::Additive, Factor::Zero, Factor::SrcColor)
  }
}

/// Compositor object; used to consume `Node`s and output to screen.
pub struct Compositor {
  // width
  w: u32,
  // height
  h: u32,
  // allocated framebuffers that might contain nodes’ output
  framebuffers: Vec<Framebuffer<Flat, Dim2, ColorMap, DepthMap>>,
  // free list of available framebuffers
  free_framebuffers: Vec<usize>,
  // program used to compose nodes
  program: Res<Program>,
  // attributeless fullscreen quad for compositing
  quad: Tess
}

const FORWARD_SOURCE: &'static Uniform<Unit> = &Uniform::new(0);

impl Compositor {
  pub fn new(w: u32, h: u32, scene: &mut Scene) -> Self {
    Compositor {
      w: w,
      h: h,
      framebuffers: Vec::new(),
      free_framebuffers: Vec::new(),
      program: scene.get("spectra/compositing/forward.glsl", vec![FORWARD_SOURCE.sem("source")]).unwrap(),
      quad: Tess::attributeless(Mode::TriangleStrip, 4)
    }
  }

  /// Whenever a node must be composed, we need a framebuffer to render into. This function pulls a
  /// framebuffer to use (via self.framebuffers) by returing an index. It might allocate a new
  /// framebuffer if there isn’t enough framebuffers to be pulled.
  fn pull_framebuffer(&mut self) -> usize {
    self.free_framebuffers.pop().unwrap_or_else(|| {
      let framebuffer_index = self.framebuffers.len();

      let framebuffer = Framebuffer::new((self.w, self.h), 0).unwrap();
      self.framebuffers.push(framebuffer);

      framebuffer_index
    })
  }

  /// Whenever a node has finished being composed, we *might* need to dispose the framebuffer it has
  /// pulled. This funciton does that job.
  ///
  /// It never deallocates memory. It has an important property: once a framebuffer is pulled,
  /// calling that function will make it available for other nodes, improving memory usage for the
  /// next calls.
  #[inline]
  fn dispose_framebuffer(&mut self, framebuffer_index: usize) {
    self.free_framebuffers.push(framebuffer_index);
  }

  /// Consume and display a compositing graph represented by its nodes.
  pub fn display(&mut self, root: Node) {
    let fb_index = self.treat_node(root);

    {
      let fb = &self.framebuffers[fb_index];

      let screen = Framebuffer::default((self.w, self.h));

      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
      let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[&*fb.color_slot];

      Pipeline::new(&screen, black, texture_set, &[], shd_cmd).run();
    }

    self.dispose_framebuffer(fb_index);
    assert!(self.free_framebuffers.is_empty());
  }

  /// Treat a node hierarchy and return the index  of the framebuffer that contains the result.
  fn treat_node(&mut self, node: Node) -> usize {
    match node {
      Node::Render(layer) => self.render(layer),
      Node::Texture(texture) => self.texturize(texture),
      Node::Composite(left, right, eq, src_fct, dst_fct) => self.composite(*left, *right, eq, src_fct, dst_fct),
    }
  }

  fn render(&mut self, layer: RenderLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];
    let black = [0., 0., 0., 1.];

    Pipeline::new(fb, black, &[], &[], &layer.shading_commands).run();

    fb_index
  }

  fn texturize(&mut self, texture: TextureLayer) -> usize {
    let fb_index = self.pull_framebuffer();
    let fb = &self.framebuffers[fb_index];

    let black = [0., 0., 0., 1.];
    let program = self.program.borrow();
    let uniforms_tex = [FORWARD_SOURCE.alter(Unit::new(0))];
    let tess_render = TessRender::from(&self.quad);
    let tess = &[Pipe::empty().uniforms(&uniforms_tex).unwrap(tess_render.clone())];
    let render_cmd = &[Pipe::new(RenderCommand::new(None, false, tess))];
    let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
    let texture_set = &[&**texture];

    Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();

    fb_index
  }

  fn composite(&mut self, left: Node, right: Node, eq: Equation, src_fct: Factor, dst_fct: Factor) -> usize {
    let left_index = self.treat_node(left);
    let right_index = self.treat_node(right);

    assert!(left_index < self.framebuffers.len());
    assert!(right_index < self.framebuffers.len());

    let fb_index = self.pull_framebuffer();

    {
      let fb = &self.framebuffers[fb_index];

      let left_fb = &self.framebuffers[left_index];
      let right_fb = &self.framebuffers[right_index];

      // compose
      let black = [0., 0., 0., 1.];
      let program = self.program.borrow();
      let uniforms_left = [FORWARD_SOURCE.alter(Unit::new(0))];
      let uniforms_right = [FORWARD_SOURCE.alter(Unit::new(1))];
      let tess_render = TessRender::from(&self.quad);
      let tess = &[
        Pipe::empty().uniforms(&uniforms_left).unwrap(tess_render.clone()),
        Pipe::empty().uniforms(&uniforms_right).unwrap(tess_render)
      ];
      let render_cmd = &[Pipe::new(RenderCommand::new(Some((eq, src_fct, dst_fct)), false, tess))];
      let shd_cmd = &[Pipe::new(ShadingCommand::new(&program, render_cmd))];
      let texture_set = &[
        &*left_fb.color_slot,
        &*right_fb.color_slot
      ];

      Pipeline::new(fb, black, texture_set, &[], shd_cmd).run();
    }

    // dispose both left and right framebuffers
    self.dispose_framebuffer(left_index);
    self.dispose_framebuffer(right_index);

    fb_index
  }
}
<|endoftext|>


<commit_before>//!CDRS support traffic decompression as it is described in [Apache
//!Cassandra protocol](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L790)
//!
//!Before being used, client and server must agree on a compression algorithm to
//!use, which is done in the STARTUP message. As a consequence, a STARTUP message
//!must never be compressed.  However, once the STARTUP frame has been received
//!by the server, messages can be compressed (including the response to the STARTUP
//!request).
//!
//!CDRS provides generic trait [`Compressor`][compressor].
//!Enum [`Compression`][compression] contains implementation
//!for `Compressor`.
//!
//!```no_run
//!use cdrs::client::CDRS;
//!use cdrs::query::QueryBuilder;
//!use cdrs::authenticators::NoneAuthenticator;
//!use cdrs::compression::Compression;
//!use cdrs::transport::TransportTcp;
//!
//!let addr = "127.0.0.1:9042";
//!let tcp_transport = TransportTcp::new(addr).unwrap();
//!
//!// pass authenticator into CDRS' constructor
//!let client = CDRS::new(tcp_transport, NoneAuthenticator);
//!let session = client.start(Compression::None);
//!//let session = client.start(Compression::Lz4)
//!//let session = client.start(Compression::Snappy)
//!```
//![compression]:enum.Compression.html
//![compressor]:trait.Compressor.html

use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use std::io;

use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(snap::Error),
    /// Lz4 error.
    Lz4(io::Error),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref err) => write!(f, "Lz4 Error: {:?}", err),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref err) => err.description(),
        }
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy, Eq, Ord, PartialOrd)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        }
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        encoder
            .compress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        decoder
            .decompress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        lz4::decompress(&bytes[4..]).map_err(CompressionError::Lz4)
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4_with_invalid_input() {
        let lz4_compression = Compression::Lz4;
        let bytes: Vec<u8> = vec![0x7f, 0x7f, 0x7f, 0x7f, 0x7f];
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let decode = lz4_compression.decode(encoded);
        assert_eq!(decode.is_err(), true);
    }

    #[test]
    fn test_compression_encode_snappy_with_non_utf8() {
        let snappy_compression = Compression::Snappy;
        let v = vec![0xff, 0xff];
        let encoded = snappy_compression
            .encode(v.clone())
            .expect("Should work without exceptions");
        assert_eq!(snappy_compression.decode(encoded).unwrap(), v);
    }

}
<commit_msg>Fix line max length<commit_after>//!CDRS support traffic decompression as it is described in [Apache
//!Cassandra protocol](
//!https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L790)
//!
//!Before being used, client and server must agree on a compression algorithm to
//!use, which is done in the STARTUP message. As a consequence, a STARTUP message
//!must never be compressed.  However, once the STARTUP frame has been received
//!by the server, messages can be compressed (including the response to the STARTUP
//!request).
//!
//!CDRS provides generic trait [`Compressor`][compressor].
//!Enum [`Compression`][compression] contains implementation
//!for `Compressor`.
//!
//!```no_run
//!use cdrs::client::CDRS;
//!use cdrs::query::QueryBuilder;
//!use cdrs::authenticators::NoneAuthenticator;
//!use cdrs::compression::Compression;
//!use cdrs::transport::TransportTcp;
//!
//!let addr = "127.0.0.1:9042";
//!let tcp_transport = TransportTcp::new(addr).unwrap();
//!
//!// pass authenticator into CDRS' constructor
//!let client = CDRS::new(tcp_transport, NoneAuthenticator);
//!let session = client.start(Compression::None);
//!//let session = client.start(Compression::Lz4)
//!//let session = client.start(Compression::Snappy)
//!```
//![compression]:enum.Compression.html
//![compressor]:trait.Compressor.html

use std::convert::From;
use std::error::Error;
use std::result;
use std::fmt;
use std::io;

use snap;
use lz4_compress as lz4;

type Result<T> = result::Result<T, CompressionError>;

pub const LZ4: &'static str = "lz4";
pub const SNAPPY: &'static str = "snappy";

/// It's an error which may occure during encoding or deconding
/// frame body. As there are only two types of compressors it
/// contains two related enum options.
#[derive(Debug)]
pub enum CompressionError {
    /// Snappy error.
    Snappy(snap::Error),
    /// Lz4 error.
    Lz4(io::Error),
}

impl fmt::Display for CompressionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &CompressionError::Snappy(ref err) => write!(f, "Snappy Error: {:?}", err),
            &CompressionError::Lz4(ref err) => write!(f, "Lz4 Error: {:?}", err),
        }
    }
}

impl Error for CompressionError {
    fn description(&self) -> &str {
        match self {
            &CompressionError::Snappy(ref err) => err.description(),
            &CompressionError::Lz4(ref err) => err.description(),
        }
    }
}

/// Compressor trait that defines functionality
/// which should be provided by typical compressor.
pub trait Compressor {
    /// Encodes given bytes and returns `Result` that contains either
    /// encoded data or an error which occures during the transformation.
    fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Encodes given encoded data and returns `Result` that contains either
    /// encoded bytes or an error which occures during the transformation.
    fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>>;
    /// Returns a string which is a name of a compressor. This name should be
    /// exactly the same as one which returns a server in a response to
    /// `Options` request.
    fn into_string(&self) -> Option<String>;
}

/// Enum which represents a type of compression. Only non-startup frame's body can be compressen.
#[derive(Debug, PartialEq, Clone, Copy, Eq, Ord, PartialOrd)]
pub enum Compression {
    /// [lz4](https://code.google.com/p/lz4/) compression
    Lz4,
    /// [snappy](https://code.google.com/p/snappy/) compression
    Snappy,
    /// Non compression
    None,
}

impl Compression {
    /// It encodes `bytes` basing on type of `Compression`..
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///
    ///   let snappy_compression = Compression::Snappy;
    ///   let bytes = String::from("Hello World").into_bytes().to_vec();
    ///   let encoded = snappy_compression.encode(bytes.clone()).unwrap();
    ///   assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    ///
    /// ```
    pub fn encode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::encode_lz4(bytes),
            &Compression::Snappy => Compression::encode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It decodes `bytes` basing on type of compression.
    ///
    /// # Examples
    ///
    /// ```
    ///    use cdrs::compression::Compression;
    ///     let lz4_compression = Compression::Lz4;
    ///     let bytes = String::from("Hello World").into_bytes().to_vec();
    ///     let encoded = lz4_compression.encode(bytes.clone()).unwrap();
    ///     let len = encoded.len() as u8;
    ///     let mut input = vec![0, 0, 0, len];
    ///     input.extend_from_slice(encoded.as_slice());
    ///     assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    /// ```
    pub fn decode(&self, bytes: Vec<u8>) -> Result<Vec<u8>> {
        match self {
            &Compression::Lz4 => Compression::decode_lz4(bytes),
            &Compression::Snappy => Compression::decode_snappy(bytes),
            &Compression::None => Ok(bytes),
        }
    }

    /// It transforms compression method into a `&str`.
    pub fn as_str(&self) -> Option<&'static str> {
        match self {
            &Compression::Lz4 => Some(LZ4),
            &Compression::Snappy => Some(SNAPPY),
            &Compression::None => None,
        }
    }

    fn encode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut encoder = snap::Encoder::new();
        encoder
            .compress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn decode_snappy(bytes: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = snap::Decoder::new();
        decoder
            .decompress_vec(bytes.as_slice())
            .map_err(CompressionError::Snappy)
    }

    fn encode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        return Ok(lz4::compress(bytes.as_slice()));
    }

    fn decode_lz4(bytes: Vec<u8>) -> Result<Vec<u8>> {
        // skip first 4 bytes in accordance to
        // https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L805
        lz4::decompress(&bytes[4..]).map_err(CompressionError::Lz4)
    }
}

impl From<String> for Compression {
    /// It converts `String` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_string: String) -> Compression {
        return Compression::from(compression_string.as_str());
    }
}

impl<'a> From<&'a str> for Compression {
    /// It converts `str` into `Compression`. If string is neither `lz4` nor `snappy` then
    /// `Compression::None` will be returned
    fn from(compression_str: &'a str) -> Compression {
        match compression_str {
            LZ4 => Compression::Lz4,
            SNAPPY => Compression::Snappy,
            _ => Compression::None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_compression_from_str() {
        let lz4 = "lz4";
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy";
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x";
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_from_string() {
        let lz4 = "lz4".to_string();
        assert_eq!(Compression::from(lz4), Compression::Lz4);
        let snappy = "snappy".to_string();
        assert_eq!(Compression::from(snappy), Compression::Snappy);
        let none = "x".to_string();
        assert_eq!(Compression::from(none), Compression::None);
    }

    #[test]
    fn test_compression_encode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_snappy() {
        let snappy_compression = Compression::Snappy;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = snappy_compression.encode(bytes.clone()).unwrap();
        assert_eq!(snappy_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4() {
        let snappy_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        snappy_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_lz4() {
        let lz4_compression = Compression::Lz4;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let len = encoded.len() as u8;
        let mut input = vec![0, 0, 0, len];
        input.extend_from_slice(encoded.as_slice());
        assert_eq!(lz4_compression.decode(input).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        none_compression
            .encode(bytes.clone())
            .expect("Should work without exceptions");
    }

    #[test]
    fn test_compression_decode_none() {
        let none_compression = Compression::None;
        let bytes = String::from("Hello World").into_bytes().to_vec();
        let encoded = none_compression.encode(bytes.clone()).unwrap();
        assert_eq!(none_compression.decode(encoded).unwrap(), bytes);
    }

    #[test]
    fn test_compression_encode_lz4_with_invalid_input() {
        let lz4_compression = Compression::Lz4;
        let bytes: Vec<u8> = vec![0x7f, 0x7f, 0x7f, 0x7f, 0x7f];
        let encoded = lz4_compression.encode(bytes.clone()).unwrap();
        let decode = lz4_compression.decode(encoded);
        assert_eq!(decode.is_err(), true);
    }

    #[test]
    fn test_compression_encode_snappy_with_non_utf8() {
        let snappy_compression = Compression::Snappy;
        let v = vec![0xff, 0xff];
        let encoded = snappy_compression
            .encode(v.clone())
            .expect("Should work without exceptions");
        assert_eq!(snappy_compression.decode(encoded).unwrap(), v);
    }

}
<|endoftext|>


<commit_before>/// Contains various flags to control operations.
pub unsafe fn cr0() -> u64
{
    let ret: u64;
    asm!("mov %cr0, %rax" : "=r" (ret) :);
    ret
}

/// Write cr0.
pub unsafe fn cr0_write(val: u64)
{
    asm!("mov %rax, %cr0" :: "r" (val));
}

/// Contains page-fault linear address.
pub unsafe fn cr2() -> u64
{
    let ret: u64;
    asm!("mov %cr2, %rax" : "=r" (ret) :);
    ret
}

/// Contains page-table root pointer.
pub unsafe fn cr3() -> u64
{
    let ret: u64;
    asm!("mov %cr3, %rax" : "=r" (ret) :);
    ret
}

/// Switch page-table PML4 pointer.
pub unsafe fn cr3_write(val: u64)
{
    asm!("mov %rax, %cr3" :: "r" (val));
}

/// Contains various flags to control operations in protected mode.
pub unsafe fn cr4() -> u64
{
    let ret: u64;
    asm!("mov %cr4, %rax" : "=r" (ret) :);
    ret
}

/// Write cr4.
pub unsafe fn cr4_write(val: u64)
{
    asm!("mov %rax, %cr4" :: "r" (val));
}
<commit_msg>Use any register.<commit_after>/// Contains various flags to control operations.
pub unsafe fn cr0() -> u64
{
    let ret: u64;
    asm!("mov %cr0, $0" : "=r" (ret) : );
    ret
}

/// Write cr0.
pub unsafe fn cr0_write(val: u64)
{
    asm!("mov %rax, %cr0" :: "r" (val));
}

/// Contains page-fault linear address.
pub unsafe fn cr2() -> u64
{
    let ret: u64;
    asm!("mov %cr2, %rax" : "=r" (ret) :);
    ret
}

/// Contains page-table root pointer.
pub unsafe fn cr3() -> u64
{
    let ret: u64;
    asm!("mov %cr3, %rax" : "=r" (ret) :);
    ret
}

/// Switch page-table PML4 pointer.
pub unsafe fn cr3_write(val: u64)
{
    asm!("mov %rax, %cr3" :: "r" (val));
}

/// Contains various flags to control operations in protected mode.
pub unsafe fn cr4() -> u64
{
    let ret: u64;
    asm!("mov %cr4, %rax" : "=r" (ret) :);
    ret
}

/// Write cr4.
pub unsafe fn cr4_write(val: u64)
{
    asm!("mov %rax, %cr4" :: "r" (val));
}
<|endoftext|>


<commit_before>use backend::Backend;
use provider::error;
use provider::Output;
use provider::service::ServiceProvider;

pub struct Service<'a> {
    name: &'static str,
    backend: &'a Backend,
    provider: &'a ServiceProvider,
    error: Option<error::Error>,
}

impl<'a> Service<'a> {
    pub fn new(n: &'static str, b: &'a Backend, p: &'a ServiceProvider) -> Service<'a> {
        Service {
            name: n,
            backend: b,
            provider: p,
            error: None,
        }
    }
}
<commit_msg>Add is_running for service resource<commit_after>use backend::Backend;
use provider::error;
use provider::Output;
use provider::service::ServiceProvider;

pub struct Service<'a> {
    name: &'static str,
    backend: &'a Backend,
    provider: &'a ServiceProvider,
    error: Option<error::Error>,
}

impl<'a> Service<'a> {
    pub fn new(n: &'static str, b: &'a Backend, p: &'a ServiceProvider) -> Service<'a> {
        Service {
            name: n,
            backend: b,
            provider: p,
            error: None,
        }
    }

    pub fn is_running(&self) -> Result<bool, error::Error> {
        self.backend
            .handle(self.provider.is_running(self.name))
            .and_then(Output::to_bool)
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::collections::HashMap;

use rsh::State;
use rsh::utils;

pub type Builtin = fn(&mut State) -> i32;

pub fn load() -> HashMap<String, Builtin> {
    let mut h = HashMap::new();

    h.insert("cd".to_string(), cd as fn(&mut State) -> i32);
    h.insert("ls".to_string(), ls as fn(&mut State) -> i32);
    h.insert("echo".to_string(), echo as fn(&mut State) -> i32);
    h.insert("set".to_string(), set as fn(&mut State) -> i32);
    h.insert("unset".to_string(), unset as fn(&mut State) -> i32);
    h.insert("get".to_string(), get as fn(&mut State) -> i32);

    h
}

fn cd(s: &mut State) -> i32 {
    let mut new_path: PathBuf;

    match s.argv.get(1) {
        Some(x) => new_path = PathBuf::from(x),
        None => {
            new_path = PathBuf::from(s.variables
                .get("HOME")
                .unwrap_or(&"".to_string()))
        }
    };

    if !new_path.has_root() {
        match utils::make_absolute(new_path) {
            Ok(p) => new_path = p,
            Err(e) => {
                println!("cd: {}", e);
                return 1;
            }
        };
    }

    if !new_path.exists() {
        println!("cd: no such file or directory");
        return 1;
    }

    s.cwd = new_path;

    0
}

fn ls(s: &mut State) -> i32 {
    if s.argv.len() == 1 {
        list_dir(&s.cwd);
        return 0;
    }

    for d in s.argv.iter() {
        let p = PathBuf::from(d);
        list_dir(&p);
    }

    0
}

fn list_dir(p: &PathBuf) {
    // Cheking if file so we don't do extra processing
    if p.is_file() {
        println!("FILE: {}", p.to_str().unwrap_or("WTF"));
        return;
    }

    // Unwrapping because we know it's a dir, not a file
    for entry in p.read_dir().unwrap() {
        match entry {
            Ok(e) => {
                // TODO replace this unwrap to something safer
                print!("{} ", e.file_name().into_string().unwrap());
            }
            Err(e) => println!("Error: {}", e),
        }
    }

    print!("\n");
}

pub fn echo(s: &mut State) -> i32 {
    if s.argv[1] == "-n" {
        let strings = &s.argv[2..s.argv.len()].join(" ");
        print!("{}", strings);
    } else {
        let strings = &s.argv[1..s.argv.len()].join(" ");
        println!("{}", strings);
    }

    0
}

fn set(s: &mut State) -> i32 {

    let var_name = s.argv.get(1);
    let value = s.argv.get(2);

    if var_name.is_none() || value.is_none() {
        println!("set: not enough arguments to set");
        return 0;
    }

    let var = var_name.unwrap().clone();
    let val = value.unwrap().clone();

    s.variables.insert(var.to_string(), val.to_string());

    0
}

fn unset(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables.remove(var);
            0
        }
        None => {
            println!("unset: not enough arguments");
            1
        }
    }
}

fn get(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables
                .get(var)
                .map(|val| {
                    println!("{}", val);
                });

            0
        }
        None => {
            println!("get: not enough arguments");
            1
        }
    }
}

// TODO make these tests better once we can capture stdout
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_cd() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.cwd.to_str().unwrap(), "/");
    }

    #[test]
    #[should_panic]
    fn test_cd_bad_path() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/123".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_set() {
        let mut s = State::default();
        s.argv = vec!["set".to_string(), "test".to_string(), "hello world".to_string()];

        let i = set(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test").unwrap(), "hello world");
    }

    #[test]
    fn test_unset() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["unset".to_string(), "test".to_string()];

        let i = unset(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test"), None);
    }

    #[test]
    fn test_get() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["get".to_string(), "test".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_ls() {
        let mut s = State::default();
        s.argv = vec!["ls".to_string()];

        let i = ls(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_echo() {
        let mut s = State::default();
        s.argv = vec!["echo".to_string(), "\"Hello world!\"".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }
}
<commit_msg>fixed crappy type definition<commit_after>use std::path::PathBuf;
use std::collections::HashMap;

use rsh::State;
use rsh::utils;

pub type Builtin = fn(&mut State) -> i32;

pub fn load() -> HashMap<String, Builtin> {
    let mut h: HashMap<String, Builtin> = HashMap::new();

    h.insert("cd".to_string(), cd);
    h.insert("ls".to_string(), ls);
    h.insert("echo".to_string(), echo);
    h.insert("set".to_string(), set);
    h.insert("unset".to_string(), unset);
    h.insert("get".to_string(), get);

    h
}

fn cd(s: &mut State) -> i32 {
    let mut new_path: PathBuf;

    match s.argv.get(1) {
        Some(x) => new_path = PathBuf::from(x),
        None => {
            new_path = PathBuf::from(s.variables
                .get("HOME")
                .unwrap_or(&"".to_string()))
        }
    };

    if !new_path.has_root() {
        match utils::make_absolute(new_path) {
            Ok(p) => new_path = p,
            Err(e) => {
                println!("cd: {}", e);
                return 1;
            }
        };
    }

    if !new_path.exists() {
        println!("cd: no such file or directory");
        return 1;
    }

    s.cwd = new_path;

    0
}

fn ls(s: &mut State) -> i32 {
    if s.argv.len() == 1 {
        list_dir(&s.cwd);
        return 0;
    }

    for d in s.argv.iter() {
        let p = PathBuf::from(d);
        list_dir(&p);
    }

    0
}

fn list_dir(p: &PathBuf) {
    // Cheking if file so we don't do extra processing
    if p.is_file() {
        println!("FILE: {}", p.to_str().unwrap_or("WTF"));
        return;
    }

    // Unwrapping because we know it's a dir, not a file
    for entry in p.read_dir().unwrap() {
        match entry {
            Ok(e) => {
                // TODO replace this unwrap to something safer
                print!("{} ", e.file_name().into_string().unwrap());
            }
            Err(e) => println!("Error: {}", e),
        }
    }

    print!("\n");
}

pub fn echo(s: &mut State) -> i32 {
    if s.argv[1] == "-n" {
        let strings = &s.argv[2..s.argv.len()].join(" ");
        print!("{}", strings);
    } else {
        let strings = &s.argv[1..s.argv.len()].join(" ");
        println!("{}", strings);
    }

    0
}

fn set(s: &mut State) -> i32 {

    let var_name = s.argv.get(1);
    let value = s.argv.get(2);

    if var_name.is_none() || value.is_none() {
        println!("set: not enough arguments to set");
        return 0;
    }

    let var = var_name.unwrap().clone();
    let val = value.unwrap().clone();

    s.variables.insert(var.to_string(), val.to_string());

    0
}

fn unset(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables.remove(var);
            0
        }
        None => {
            println!("unset: not enough arguments");
            1
        }
    }
}

fn get(s: &mut State) -> i32 {
    match s.argv.get(1) {
        Some(var) => {
            s.variables
                .get(var)
                .map(|val| {
                    println!("{}", val);
                });

            0
        }
        None => {
            println!("get: not enough arguments");
            1
        }
    }
}

// TODO make these tests better once we can capture stdout
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_cd() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.cwd.to_str().unwrap(), "/");
    }

    #[test]
    #[should_panic]
    fn test_cd_bad_path() {
        let mut s = State::default();
        s.argv = vec!["cd".to_string(), "/123".to_string()];

        let i = cd(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_set() {
        let mut s = State::default();
        s.argv = vec!["set".to_string(), "test".to_string(), "hello world".to_string()];

        let i = set(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test").unwrap(), "hello world");
    }

    #[test]
    fn test_unset() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["unset".to_string(), "test".to_string()];

        let i = unset(&mut s);

        assert_eq!(i, 0);
        assert_eq!(s.variables.get("test"), None);
    }

    #[test]
    fn test_get() {
        let mut s = State::default();
        s.variables.insert("test".to_string(), "hello world".to_string());
        s.argv = vec!["get".to_string(), "test".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_ls() {
        let mut s = State::default();
        s.argv = vec!["ls".to_string()];

        let i = ls(&mut s);

        assert_eq!(i, 0);
    }

    #[test]
    fn test_echo() {
        let mut s = State::default();
        s.argv = vec!["echo".to_string(), "\"Hello world!\"".to_string()];

        let i = get(&mut s);

        assert_eq!(i, 0);
    }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{self, Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(10));

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state    = ParserState::Header;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }
}
<commit_msg>Remove unused import<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(10));

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state    = ParserState::Header;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }
}
<|endoftext|>


<commit_before>use align::*;
use event::{Event, EventResult};
use rect::Rect;
use theme::ColorStyle;
use unicode_width::UnicodeWidthStr;
use vec::Vec2;
use view::{View, ViewWrapper};
use Printer;
use With;

/// Draws a border around a wrapped view.
#[derive(Debug)]
pub struct Panel<V: View> {
    // Inner view
    view: V,

    // Possibly empty title.
    title: String,

    // Where to put the title position
    title_position: HAlign,

    // `true` when we needs to relayout
    invalidated: bool,
}

impl<V: View> Panel<V> {
    /// Creates a new panel around the given view.
    pub fn new(view: V) -> Self {
        Panel {
            view,
            title: String::new(),
            title_position: HAlign::Center,
            invalidated: true,
        }
    }

    inner_getters!(self.view: V);

    /// Sets the title of the dialog.
    ///
    /// If not empty, it will be visible at the top.
    pub fn title<S: Into<String>>(self, label: S) -> Self {
        self.with(|s| s.set_title(label))
    }

    /// Sets the title of the dialog.
    pub fn set_title<S: Into<String>>(&mut self, label: S) {
        self.title = label.into();
        self.invalidate();
    }

    /// Sets the horizontal position of the title in the dialog.
    /// The default position is `HAlign::Center`
    pub fn title_position(self, align: HAlign) -> Self {
        self.with(|s| s.set_title_position(align))
    }

    /// Sets the horizontal position of the title in the dialog.
    /// The default position is `HAlign::Center`
    pub fn set_title_position(&mut self, align: HAlign) {
        self.title_position = align;
    }

    fn draw_title(&self, printer: &Printer) {
        if !self.title.is_empty() {
            let len = self.title.width();
            if len + 4 > printer.size.x {
                return;
            }
            let spacing = 3; //minimum distance to borders
            let x = spacing + self
                .title_position
                .get_offset(len, printer.size.x - 2 * spacing);
            printer.with_high_border(false, |printer| {
                printer.print((x - 2, 0), "┤ ");
                printer.print((x + len, 0), " ├");
            });

            printer.with_color(ColorStyle::title_primary(), |p| {
                p.print((x, 0), &self.title)
            });
        }
    }

    fn invalidate(&mut self) {
        self.invalidated = true;
    }
}

impl<V: View> ViewWrapper for Panel<V> {
    wrap_impl!(self.view: V);

    fn wrap_on_event(&mut self, event: Event) -> EventResult {
        self.view.on_event(event.relativized((1, 1)))
    }

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // TODO: make borders conditional?
        let req = req.saturating_sub((2, 2));

        self.view.required_size(req) + (2, 2)
    }

    fn wrap_draw(&self, printer: &Printer) {
        printer.print_box((0, 0), printer.size, true);
        self.draw_title(&printer);

        let printer = printer.offset((1, 1)).shrinked((1, 1));
        self.view.draw(&printer);
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.view.layout(size.saturating_sub((2, 2)));
    }

    fn wrap_important_area(&self, size: Vec2) -> Rect {
        let inner_size = size.saturating_sub((2, 2));
        self.view.important_area(inner_size) + (1, 1)
    }

    fn wrap_needs_relayout(&self) -> bool {
        self.invalidated
            || self.with_view(|v| v.needs_relayout()).unwrap_or(true)
    }
}
<commit_msg>Simplify Panel::wrap_needs_relayout<commit_after>use align::*;
use event::{Event, EventResult};
use rect::Rect;
use theme::ColorStyle;
use unicode_width::UnicodeWidthStr;
use vec::Vec2;
use view::{View, ViewWrapper};
use Printer;
use With;

/// Draws a border around a wrapped view.
#[derive(Debug)]
pub struct Panel<V: View> {
    // Inner view
    view: V,

    // Possibly empty title.
    title: String,

    // Where to put the title position
    title_position: HAlign,

    // `true` when we needs to relayout
    invalidated: bool,
}

impl<V: View> Panel<V> {
    /// Creates a new panel around the given view.
    pub fn new(view: V) -> Self {
        Panel {
            view,
            title: String::new(),
            title_position: HAlign::Center,
            invalidated: true,
        }
    }

    inner_getters!(self.view: V);

    /// Sets the title of the dialog.
    ///
    /// If not empty, it will be visible at the top.
    pub fn title<S: Into<String>>(self, label: S) -> Self {
        self.with(|s| s.set_title(label))
    }

    /// Sets the title of the dialog.
    pub fn set_title<S: Into<String>>(&mut self, label: S) {
        self.title = label.into();
        self.invalidate();
    }

    /// Sets the horizontal position of the title in the dialog.
    /// The default position is `HAlign::Center`
    pub fn title_position(self, align: HAlign) -> Self {
        self.with(|s| s.set_title_position(align))
    }

    /// Sets the horizontal position of the title in the dialog.
    /// The default position is `HAlign::Center`
    pub fn set_title_position(&mut self, align: HAlign) {
        self.title_position = align;
    }

    fn draw_title(&self, printer: &Printer) {
        if !self.title.is_empty() {
            let len = self.title.width();
            if len + 4 > printer.size.x {
                return;
            }
            let spacing = 3; //minimum distance to borders
            let x = spacing + self
                .title_position
                .get_offset(len, printer.size.x - 2 * spacing);
            printer.with_high_border(false, |printer| {
                printer.print((x - 2, 0), "┤ ");
                printer.print((x + len, 0), " ├");
            });

            printer.with_color(ColorStyle::title_primary(), |p| {
                p.print((x, 0), &self.title)
            });
        }
    }

    fn invalidate(&mut self) {
        self.invalidated = true;
    }
}

impl<V: View> ViewWrapper for Panel<V> {
    wrap_impl!(self.view: V);

    fn wrap_on_event(&mut self, event: Event) -> EventResult {
        self.view.on_event(event.relativized((1, 1)))
    }

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // TODO: make borders conditional?
        let req = req.saturating_sub((2, 2));

        self.view.required_size(req) + (2, 2)
    }

    fn wrap_draw(&self, printer: &Printer) {
        printer.print_box((0, 0), printer.size, true);
        self.draw_title(&printer);

        let printer = printer.offset((1, 1)).shrinked((1, 1));
        self.view.draw(&printer);
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.view.layout(size.saturating_sub((2, 2)));
    }

    fn wrap_important_area(&self, size: Vec2) -> Rect {
        let inner_size = size.saturating_sub((2, 2));
        self.view.important_area(inner_size) + (1, 1)
    }

    fn wrap_needs_relayout(&self) -> bool {
        self.invalidated || self.view.needs_relayout()
    }
}
<|endoftext|>


<commit_before>use std::mem;

use runtime::{Class, Imp, Sel, ToMessage};
use runtime;

pub struct MethodDecl {
	sel: Sel,
	imp: Imp,
	types: String,
}

pub struct ClassDecl {
	cls: Class,
}

impl ClassDecl {
	pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
		let cls = name.with_c_str(|name| unsafe {
			runtime::objc_allocateClassPair(*superclass, name, 0)
		});
		if cls.is_nil() {
			None
		} else {
			Some(ClassDecl { cls: cls })
		}
	}

	pub fn add_method(&mut self, method: MethodDecl) -> bool {
		method.types.with_c_str(|types| unsafe {
			runtime::class_addMethod(self.cls, method.sel, method.imp, types)
		})
	}

	pub fn register(self) -> Class {
		unsafe {
			runtime::objc_registerClassPair(self.cls);
		}
		let cls = self.cls;
		// Forget self otherwise the class will be disposed in drop
		unsafe {
			mem::forget(self);
		}
		cls
	}
}

impl Drop for ClassDecl {
	fn drop(&mut self) {
		unsafe {
			runtime::objc_disposeClassPair(self.cls);
		}
	}
}

#[cfg(test)]
mod tests {
	use runtime::{Class, Object};
	use super::ClassDecl;

	#[test]
	fn test_custom_class() {
		let superclass = Class::get("NSObject").unwrap();
		let decl = ClassDecl::new(&superclass, "MyObject");
		assert!(decl.is_some());
		let mut decl = decl.unwrap();

		decl.add_method(method!(
			(*mut Object)_this, doNothing; {
				()
			}
		));
		decl.add_method(method!(
			(*mut Object)_this, doNothingWithFoo:(uint)_foo; {
				()
			}
		));
		decl.add_method(method!(
			(*mut Object)this, doSomething -> *mut Object {
				this
			}
		));
		decl.add_method(method!(
			(*mut Object)this, doSomethingWithFoo:(uint)_foo -> *mut Object {
				this
			}
		));

		let cls = decl.register();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];

			msg_send![obj doNothing];
			msg_send![obj doNothingWithFoo:0u];
			let result = msg_send![obj doSomething];
			assert!(result == obj);
			let result = msg_send![obj doSomethingWithFoo:0u];
			assert!(result == obj);

			msg_send![obj release];
		}
	}
}
<commit_msg>Make MethodDecl fields public.<commit_after>use std::mem;

use runtime::{Class, Imp, Sel, ToMessage};
use runtime;

pub struct MethodDecl {
	pub sel: Sel,
	pub imp: Imp,
	pub types: String,
}

pub struct ClassDecl {
	cls: Class,
}

impl ClassDecl {
	pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
		let cls = name.with_c_str(|name| unsafe {
			runtime::objc_allocateClassPair(*superclass, name, 0)
		});
		if cls.is_nil() {
			None
		} else {
			Some(ClassDecl { cls: cls })
		}
	}

	pub fn add_method(&mut self, method: MethodDecl) -> bool {
		method.types.with_c_str(|types| unsafe {
			runtime::class_addMethod(self.cls, method.sel, method.imp, types)
		})
	}

	pub fn register(self) -> Class {
		unsafe {
			runtime::objc_registerClassPair(self.cls);
		}
		let cls = self.cls;
		// Forget self otherwise the class will be disposed in drop
		unsafe {
			mem::forget(self);
		}
		cls
	}
}

impl Drop for ClassDecl {
	fn drop(&mut self) {
		unsafe {
			runtime::objc_disposeClassPair(self.cls);
		}
	}
}

#[cfg(test)]
mod tests {
	use runtime::{Class, Object};
	use super::ClassDecl;

	#[test]
	fn test_custom_class() {
		let superclass = Class::get("NSObject").unwrap();
		let decl = ClassDecl::new(&superclass, "MyObject");
		assert!(decl.is_some());
		let mut decl = decl.unwrap();

		decl.add_method(method!(
			(*mut Object)_this, doNothing; {
				()
			}
		));
		decl.add_method(method!(
			(*mut Object)_this, doNothingWithFoo:(uint)_foo; {
				()
			}
		));
		decl.add_method(method!(
			(*mut Object)this, doSomething -> *mut Object {
				this
			}
		));
		decl.add_method(method!(
			(*mut Object)this, doSomethingWithFoo:(uint)_foo -> *mut Object {
				this
			}
		));

		let cls = decl.register();
		unsafe {
			let obj = msg_send![cls alloc];
			let obj = msg_send![obj init];

			msg_send![obj doNothing];
			msg_send![obj doNothingWithFoo:0u];
			let result = msg_send![obj doSomething];
			assert!(result == obj);
			let result = msg_send![obj doSomethingWithFoo:0u];
			assert!(result == obj);

			msg_send![obj release];
		}
	}
}
<|endoftext|>


<commit_before>//! Data related to IRC functionality
#![experimental]

pub mod kinds {
    //! Trait definitions of appropriate Writers and Buffers for use with this library
    #![unstable]

    /// Trait describing all possible Writers for this library
    #[unstable]
    pub trait IrcWriter: Writer + Sized + Send + 'static {}
    impl<T> IrcWriter for T where T: Writer + Sized + Send + 'static {}
    /// Trait describing all possible Readers for this library
    #[unstable]
    pub trait IrcReader: Buffer + Sized + Send + 'static {}
    impl<T> IrcReader for T where T: Buffer + Sized + Send + 'static {}
}

pub mod command;
pub mod config;
pub mod message;
<commit_msg>Added exports to data module.<commit_after>//! Data related to IRC functionality
#![experimental]

pub use data::config::Config;
pub use data::message::Message;
pub use data::command::Command;

pub mod kinds {
    //! Trait definitions of appropriate Writers and Buffers for use with this library
    #![unstable]

    /// Trait describing all possible Writers for this library
    #[unstable]
    pub trait IrcWriter: Writer + Sized + Send + 'static {}
    impl<T> IrcWriter for T where T: Writer + Sized + Send + 'static {}
    /// Trait describing all possible Readers for this library
    #[unstable]
    pub trait IrcReader: Buffer + Sized + Send + 'static {}
    impl<T> IrcReader for T where T: Buffer + Sized + Send + 'static {}
}

pub mod command;
pub mod config;
pub mod message;
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use ::memory::PAddr;

use super::Section;
use super::section;

use core::fmt;
use core::mem;

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Header {
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    pub entry_point: PAddr
  , /// Offset for start of program headers
    pub ph_offset: PAddr
  , /// Offset for start of section headers
    pub sh_offset: PAddr
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , pub sh_str_idx: u16
}

impl Header {

    /// Attempt to extract an ELF file header from a slice of bytes.
    pub fn from_slice<'a>(input: &'a [u8]) -> Result<&'a Header, &str> {
        if input.len() < mem::size_of::<Header>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Header>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    pub fn section<'a>(&'a self, input: &'a [u8], idx: u16)
                      -> Result<&'a Section, &str>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start // start offset for section
                = self.sh_offset.as_u64() + idx as u64 * self.sh_entry_size as u64;
            let end // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unimplemented!()
              , Class::Elf64 => unsafe {
                    Ok(mem::transmute(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

    #[inline]
    pub fn get_type(&self) -> Type { self.elftype.as_type() }

}

/// ELF header magic
pub const MAGIC: [u8; 4] = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be [0x7, E, L, F]
    pub magic: Magic
  , /// ELF file class (32- or 64-bit)
    pub class: Class
  , /// ELF data encoding (big- or little-endian)
    pub data: Data
  , /// ELF file version
    pub version: Version
  , pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Data {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBSD  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBSD = 0x09
               , OpenBSD = 0x0C
               , OpenVMS = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
pub struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPC = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<commit_msg>[kernel] tweak names of fields in ELF header<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use ::memory::PAddr;

use super::Section;
use super::section;

use core::fmt;
use core::mem;

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Header {
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    pub entry_point: PAddr
  , /// Offset for start of program headers
    pub ph_offset: PAddr
  , /// Offset for start of section headers
    pub sh_offset: PAddr
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , pub sh_str_idx: u16
}

impl Header {

    /// Attempt to extract an ELF file header from a slice of bytes.
    pub fn from_slice<'a>(input: &'a [u8]) -> Result<&'a Header, &str> {
        if input.len() < mem::size_of::<Header>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Header>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    pub fn section<'a>(&'a self, input: &'a [u8], idx: u16)
                      -> Result<&'a Section, &str>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start // start offset for section
                = self.sh_offset.as_u64() + idx as u64 * self.sh_entry_size as u64;
            let end // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unimplemented!()
              , Class::Elf64 => unsafe {
                    Ok(mem::transmute(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

    #[inline]
    pub fn get_type(&self) -> Type { self.elftype.as_type() }

}

/// ELF header magic
pub const MAGIC: [u8; 4] = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be [0x7, E, L, F]
    pub magic: Magic
  , /// ELF file class (32- or 64-bit)
    pub class: Class
  , /// ELF data encoding (big- or little-endian)
    pub data: DataEncoding
  , /// ELF file version
    pub version: Version
  , pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBSD  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBSD = 0x09
               , OpenBSD = 0x0C
               , OpenVMS = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
pub struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPC = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<|endoftext|>


<commit_before>use env::{Env, MultiEnv};

use densearray::prelude::*;
use operator::prelude::*;
use rng::xorshift::{Xorshiftplus128Rng};

use rand::{Rng};
use std::collections::{VecDeque};
use std::rc::{Rc};
use std::sync::{Arc};

pub trait EnvObsRepr<F>: Env {
  fn _obs_shape3d() -> (usize, usize, usize) { unimplemented!(); }
  fn observe(&self, rng: &mut Xorshiftplus128Rng) -> F;
}

pub trait EnvObsBuf<F>: Env {
  fn observe_buf(&self, rng: &mut Xorshiftplus128Rng, obs: &F);
}

pub trait MultiEnvObserve<Obs>: MultiEnv {
  fn observe<R>(&self, observer_rank: usize, rng: &mut R) -> Obs where R: Rng + Sized;
}

pub trait MultiObs {
  fn observer_rank(&self) -> usize;
  fn num_observers(&self) -> usize;
}

pub trait MultiBeliefState<Obs>: Clone where Obs: MultiObs {
  fn depth(&self) -> usize;
  fn reset(&mut self);
  fn append(&mut self, obs: Rc<Obs>);
}

pub trait SharedMultiBeliefState<Obs>: Clone where Obs: MultiObs {
  fn depth(&self) -> usize;
  fn reset(&mut self);
  fn append(&mut self, obs: Arc<Obs>);
}

pub struct BeliefState<F> {
  pub history_len:  Option<usize>,
  pub obs_reprs:    VecDeque<Rc<F>>,
}

impl<F> Clone for BeliefState<F> {
  fn clone(&self) -> Self {
    BeliefState{
      history_len:  self.history_len,
      obs_reprs:    self.obs_reprs.clone(),
    }
  }
}

impl<F> BeliefState<F> {
  pub fn new(history_len: Option<usize>) -> BeliefState<F> {
    BeliefState{
      history_len:  history_len,
      obs_reprs:    VecDeque::new(),
    }
  }

  pub fn len(&self) -> usize {
    self.obs_reprs.len()
  }

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

  pub fn push(&mut self, obs: Rc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }
    }
    self.obs_reprs.push_back(obs);
  }
}

impl<F> Extract<[u8]> for BeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract(&mut output[offset .. ]) {
        Err(_)    => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

pub struct SharedBeliefState<F> {
  pub history_len:  Option<usize>,
  pub obs_reprs:    VecDeque<Arc<F>>,
}

impl<F> Clone for SharedBeliefState<F> {
  fn clone(&self) -> Self {
    SharedBeliefState{
      history_len:  self.history_len,
      obs_reprs:    self.obs_reprs.clone(),
    }
  }
}

impl<F> SharedBeliefState<F> {
  pub fn new(history_len: Option<usize>) -> SharedBeliefState<F> {
    SharedBeliefState{
      history_len:  history_len,
      obs_reprs:    VecDeque::new(),
    }
  }

  pub fn len(&self) -> usize {
    self.obs_reprs.len()
  }

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

  pub fn push(&mut self, obs: Arc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }
    }
    self.obs_reprs.push_back(obs);
  }
}

impl<F> Extract<[u8]> for SharedBeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract(&mut output[offset .. ]) {
        Err(_)    => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

/*pub struct BeliefState<F> {
  pub history_len:  Option<usize>,
  //pub frame_dim:    (usize, usize, usize),
  //pub obs_reprs:    VecDeque<Rc<F>>,
  pub obs_reprs:    Vec<Rc<F>>,
  frame_counter:    usize,
  frame_length:     usize,
}

impl<F> Clone for BeliefState<F> {
  fn clone(&self) -> Self {
    BeliefState{
      history_len:  self.history_len,
      //frame_dim:    self.frame_dim,
      obs_reprs:    self.obs_reprs.clone(),
      frame_counter:    self.frame_counter,
      frame_length:     self.frame_length,
    }
  }
}

impl<F> BeliefState<F> {
  pub fn new(history_len: Option<usize>, /*frame_dim: (usize, usize, usize)*/) -> BeliefState<F> {
    BeliefState{
      history_len:  history_len,
      //frame_dim:    frame_dim,
      //obs_reprs:    VecDeque::new(),
      obs_reprs:    Vec::with_capacity(history_len.unwrap_or(4)),
      frame_counter:    0,
      frame_length:     0,
    }
  }

  pub fn reset(&mut self) {
    self.obs_reprs.clear();
    self.frame_counter = 0;
    self.frame_length = 0;
  }

  pub fn push(&mut self, obs: Rc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      /*if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }*/
      if self.obs_reprs.len() < cap {
        self.obs_reprs.push(obs);
        self.frame_counter += 1;
        self.frame_length += 1;
      } else {
        self.obs_reprs[self.frame_counter] = obs;
        self.frame_counter += 1;
      }
      if self.frame_counter < cap {
      } else if self.frame_counter == cap {
        self.frame_counter = 0;
      } else {
        unreachable!();
      }
      assert!(self.frame_length <= cap);
    } else {
      self.obs_reprs.push(obs);
      self.frame_counter += 1;
      self.frame_length += 1;
    }
    //self.obs_reprs.push_back(obs);
  }

  /*pub fn _shape3d(&self) -> (usize, usize, usize) {
    (self.frame_dim.0, self.frame_dim.1, self.obs_reprs.len() * self.frame_dim.2)
  }*/
}

impl<F> Extract<[u8]> for BeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    /*for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }*/
    for frame_idx in 0 .. self.frame_length {
      let frame_offset =
          if let Some(cap) = self.history_len {
            (self.frame_counter + cap - self.frame_length + 1) % cap
          } else {
            frame_idx
          };
      match self.obs_reprs[frame_offset].extract(&mut output[offset .. ]) {
        Err(_) => panic!(),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

impl<F> SampleExtractInput<[u8]> for BeliefState<F> where F: SampleExtractInput<[u8]> {
  fn extract_input(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    /*for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }*/
    for frame_idx in 0 .. self.frame_length {
      let frame_offset =
          if let Some(cap) = self.history_len {
            (self.frame_counter + cap - self.frame_length + 1) % cap
          } else {
            frame_idx
          };
      match self.obs_reprs[frame_offset].extract_input(&mut output[offset .. ]) {
        Err(_) => panic!(),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

impl<F> SampleExtractInput<[f32]> for BeliefState<F> where F: SampleExtractInput<[f32]> {
  fn extract_input(&self, output: &mut [f32]) -> Result<usize, ()> {
    // FIXME(20170126)
    unimplemented!();
    /*let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)*/
  }
}

//impl<F, Shape> SampleInputShape<Shape> for BeliefState<F> where F: SampleInputShape<Shape>, Shape: PartialEq + Eq {
impl<F> SampleInputShape<(usize, usize, usize)> for BeliefState<F> where F: SampleInputShape<(usize, usize, usize)> {
  fn input_shape(&self) -> Option<(usize, usize, usize)> {
    /*let mut shape = None;
    for obs in self.obs_reprs.iter() {
      let obs_shape = match obs.input_shape() {
        None => continue,
        Some(shape) => shape,
      };
      match shape {
        None => shape = Some(obs_shape),
        Some(ref prev_shape) => if prev_shape != &obs_shape { panic!(); },
      }
    }
    shape.map(|(w, h, c)| (w, h, c * self.obs_reprs.len()))*/

    /*let (w, h, c) = self.frame_dim;
    Some((w, h, c * self.frame_length))*/
    unimplemented!();
  }
}*/
<commit_msg>Add a constructor to the multi-agent belief state trait. Make the single-agent belief state impls more similar to the multi-agent trait.<commit_after>use env::{Env, MultiEnv};

use densearray::prelude::*;
use operator::prelude::*;
use rng::xorshift::{Xorshiftplus128Rng};

use rand::{Rng};
use std::collections::{VecDeque};
use std::rc::{Rc};
use std::sync::{Arc};

pub trait EnvObsRepr<F>: Env {
  fn _obs_shape3d() -> (usize, usize, usize) { unimplemented!(); }
  fn observe(&self, rng: &mut Xorshiftplus128Rng) -> F;
}

pub trait EnvObsBuf<F>: Env {
  fn observe_buf(&self, rng: &mut Xorshiftplus128Rng, obs: &F);
}

pub trait MultiEnvObserve<Obs>: MultiEnv {
  fn observe<R>(&self, observer_rank: usize, rng: &mut R) -> Obs where R: Rng + Sized;
}

pub trait MultiObs {
  fn observer_rank(&self) -> usize;
  fn num_observers(&self) -> usize;
}

pub trait MultiBeliefState<Obs>: Clone where Obs: MultiObs {
  fn depth(&self) -> usize;
  fn reset(&mut self);
  fn append(&mut self, obs: Rc<Obs>);
}

pub trait SharedMultiBeliefState<Obs>: Clone where Obs: MultiObs {
  fn _build(max_depth: Option<usize>) -> Self where Self: Sized;
  fn depth(&self) -> usize;
  fn reset(&mut self);
  fn append(&mut self, obs: Arc<Obs>);
}

pub struct BeliefState<F> {
  pub history_len:  Option<usize>,
  pub obs_reprs:    VecDeque<Rc<F>>,
}

impl<F> Clone for BeliefState<F> {
  fn clone(&self) -> Self {
    BeliefState{
      history_len:  self.history_len,
      obs_reprs:    self.obs_reprs.clone(),
    }
  }
}

impl<F> BeliefState<F> {
  pub fn new(history_len: Option<usize>) -> BeliefState<F> {
    BeliefState{
      history_len:  history_len,
      obs_reprs:    VecDeque::new(),
    }
  }

  pub fn len(&self) -> usize {
    self.obs_reprs.len()
  }

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

  pub fn push(&mut self, obs: Rc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }
    }
    self.obs_reprs.push_back(obs);
  }
}

impl<F> Extract<[u8]> for BeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract(&mut output[offset .. ]) {
        Err(_)    => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

pub struct SharedBeliefState<F> {
  pub history_len:  Option<usize>,
  pub obs_reprs:    VecDeque<Arc<F>>,
}

impl<F> Clone for SharedBeliefState<F> {
  fn clone(&self) -> Self {
    SharedBeliefState{
      history_len:  self.history_len,
      obs_reprs:    self.obs_reprs.clone(),
    }
  }
}

impl<F> SharedBeliefState<F> {
  pub fn new(history_len: Option<usize>) -> SharedBeliefState<F> {
    SharedBeliefState{
      history_len:  history_len,
      obs_reprs:    VecDeque::new(),
    }
  }

  pub fn len(&self) -> usize {
    self.depth()
  }

  pub fn depth(&self) -> usize {
    self.obs_reprs.len()
  }

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

  pub fn push(&mut self, obs: Arc<F>) {
    self.append(obs);
  }

  pub fn append(&mut self, obs: Arc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }
    }
    self.obs_reprs.push_back(obs);
  }
}

impl<F> Extract<[u8]> for SharedBeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract(&mut output[offset .. ]) {
        Err(_)    => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

/*pub struct BeliefState<F> {
  pub history_len:  Option<usize>,
  //pub frame_dim:    (usize, usize, usize),
  //pub obs_reprs:    VecDeque<Rc<F>>,
  pub obs_reprs:    Vec<Rc<F>>,
  frame_counter:    usize,
  frame_length:     usize,
}

impl<F> Clone for BeliefState<F> {
  fn clone(&self) -> Self {
    BeliefState{
      history_len:  self.history_len,
      //frame_dim:    self.frame_dim,
      obs_reprs:    self.obs_reprs.clone(),
      frame_counter:    self.frame_counter,
      frame_length:     self.frame_length,
    }
  }
}

impl<F> BeliefState<F> {
  pub fn new(history_len: Option<usize>, /*frame_dim: (usize, usize, usize)*/) -> BeliefState<F> {
    BeliefState{
      history_len:  history_len,
      //frame_dim:    frame_dim,
      //obs_reprs:    VecDeque::new(),
      obs_reprs:    Vec::with_capacity(history_len.unwrap_or(4)),
      frame_counter:    0,
      frame_length:     0,
    }
  }

  pub fn reset(&mut self) {
    self.obs_reprs.clear();
    self.frame_counter = 0;
    self.frame_length = 0;
  }

  pub fn push(&mut self, obs: Rc<F>) {
    if let Some(cap) = self.history_len {
      assert!(self.obs_reprs.len() <= cap);
      /*if self.obs_reprs.len() == cap {
        let _ = self.obs_reprs.pop_front();
      }*/
      if self.obs_reprs.len() < cap {
        self.obs_reprs.push(obs);
        self.frame_counter += 1;
        self.frame_length += 1;
      } else {
        self.obs_reprs[self.frame_counter] = obs;
        self.frame_counter += 1;
      }
      if self.frame_counter < cap {
      } else if self.frame_counter == cap {
        self.frame_counter = 0;
      } else {
        unreachable!();
      }
      assert!(self.frame_length <= cap);
    } else {
      self.obs_reprs.push(obs);
      self.frame_counter += 1;
      self.frame_length += 1;
    }
    //self.obs_reprs.push_back(obs);
  }

  /*pub fn _shape3d(&self) -> (usize, usize, usize) {
    (self.frame_dim.0, self.frame_dim.1, self.obs_reprs.len() * self.frame_dim.2)
  }*/
}

impl<F> Extract<[u8]> for BeliefState<F> where F: Extract<[u8]> {
  fn extract(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    /*for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }*/
    for frame_idx in 0 .. self.frame_length {
      let frame_offset =
          if let Some(cap) = self.history_len {
            (self.frame_counter + cap - self.frame_length + 1) % cap
          } else {
            frame_idx
          };
      match self.obs_reprs[frame_offset].extract(&mut output[offset .. ]) {
        Err(_) => panic!(),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

impl<F> SampleExtractInput<[u8]> for BeliefState<F> where F: SampleExtractInput<[u8]> {
  fn extract_input(&self, output: &mut [u8]) -> Result<usize, ()> {
    let mut offset = 0;
    /*for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }*/
    for frame_idx in 0 .. self.frame_length {
      let frame_offset =
          if let Some(cap) = self.history_len {
            (self.frame_counter + cap - self.frame_length + 1) % cap
          } else {
            frame_idx
          };
      match self.obs_reprs[frame_offset].extract_input(&mut output[offset .. ]) {
        Err(_) => panic!(),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)
  }
}

impl<F> SampleExtractInput<[f32]> for BeliefState<F> where F: SampleExtractInput<[f32]> {
  fn extract_input(&self, output: &mut [f32]) -> Result<usize, ()> {
    // FIXME(20170126)
    unimplemented!();
    /*let mut offset = 0;
    for obs in self.obs_reprs.iter() {
      match obs.extract_input(&mut output[offset .. ]) {
        Err(_) => return Err(()),
        Ok(count) => offset += count,
      }
    }
    Ok(offset)*/
  }
}

//impl<F, Shape> SampleInputShape<Shape> for BeliefState<F> where F: SampleInputShape<Shape>, Shape: PartialEq + Eq {
impl<F> SampleInputShape<(usize, usize, usize)> for BeliefState<F> where F: SampleInputShape<(usize, usize, usize)> {
  fn input_shape(&self) -> Option<(usize, usize, usize)> {
    /*let mut shape = None;
    for obs in self.obs_reprs.iter() {
      let obs_shape = match obs.input_shape() {
        None => continue,
        Some(shape) => shape,
      };
      match shape {
        None => shape = Some(obs_shape),
        Some(ref prev_shape) => if prev_shape != &obs_shape { panic!(); },
      }
    }
    shape.map(|(w, h, c)| (w, h, c * self.obs_reprs.len()))*/

    /*let (w, h, c) = self.frame_dim;
    Some((w, h, c * self.frame_length))*/
    unimplemented!();
  }
}*/
<|endoftext|>