<commit_before>use std::mem;
use heartbeat::{self, Heartbeat, HeartbeatRecord, HeartbeatWindowCompleteFn};
#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;

/// Contains the Heartbeat and its window data buffer.
pub struct HeartbeatContainer {
    pub hb: Heartbeat,
    pub hbr: Vec<HeartbeatRecord>,
}

impl HeartbeatContainer {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<HeartbeatWindowCompleteFn>) -> Result<HeartbeatContainer, &'static str> {
        let mut hbr = Vec::with_capacity(window_size);
        unsafe {
            let mut hb = mem::uninitialized();
            match heartbeat::heartbeat_init(&mut hb, hbr.capacity() as u64, hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(HeartbeatContainer { hb: hb, hbr: hbr, }),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat.
    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     start_time: u64,
                     end_time: u64) {
        unsafe {
            heartbeat::heartbeat(&mut self.hb, tag, work, start_time, end_time);
        }
    }

    /// Issue a heartbeat with energy data.
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: u64,
                         end_time: u64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat::heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    #[cfg(unix)]
    pub fn log_window_buffer(&self, log: File, print_header: bool) -> Result<(), &'static str> {
        let ph: i32 = match print_header {
            true => 1,
            false => 0,
        };
        unsafe {
            match heartbeat::heartbeat_log_window_buffer(&self.hb, log.as_raw_fd(), ph) {
                0 => Ok(()),
                _ => Err("Error logging window buffer"),
            }
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            heartbeat::hb_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            heartbeat::hb_get_window_rate(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            heartbeat::hb_get_window_power(&self.hb)
        }
    }
}

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

    #[test]
    fn test_simple() {
        const TIME_INC: u64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = HeartbeatContainer::new(5, None).unwrap();
        let mut start_time: u64 = 0;
        let mut end_time: u64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<commit_msg>Juse use all heartbeat module<commit_after>use std::mem;
use heartbeat::*;
#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;

/// Contains the Heartbeat and its window data buffer.
pub struct HeartbeatContainer {
    pub hb: Heartbeat,
    pub hbr: Vec<HeartbeatRecord>,
}

impl HeartbeatContainer {
    /// Allocate and initialize a new `Heartbeat`.
    pub fn new(window_size: usize,
               hwc_callback: Option<HeartbeatWindowCompleteFn>) -> Result<HeartbeatContainer, &'static str> {
        let mut hbr = Vec::with_capacity(window_size);
        unsafe {
            let mut hb = mem::uninitialized();
            match heartbeat_init(&mut hb, hbr.capacity() as u64, hbr.as_mut_ptr(), hwc_callback) {
                0 => Ok(HeartbeatContainer { hb: hb, hbr: hbr, }),
                _ => Err("Failed to initialize heartbeat")
            }
        }
    }

    /// Issue a heartbeat.
    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     start_time: u64,
                     end_time: u64) {
        unsafe {
            heartbeat(&mut self.hb, tag, work, start_time, end_time);
        }
    }

    /// Issue a heartbeat with energy data.
    pub fn heartbeat_pow(&mut self,
                         tag: u64,
                         work: u64,
                         start_time: u64,
                         end_time: u64,
                         start_energy: u64,
                         end_energy: u64) {
        unsafe {
            heartbeat_pow(&mut self.hb, tag, work, start_time, end_time, start_energy, end_energy)
        }
    }

    #[cfg(unix)]
    pub fn log_window_buffer(&self, log: File, print_header: bool) -> Result<(), &'static str> {
        let ph: i32 = match print_header {
            true => 1,
            false => 0,
        };
        unsafe {
            match heartbeat_log_window_buffer(&self.hb, log.as_raw_fd(), ph) {
                0 => Ok(()),
                _ => Err("Error logging window buffer"),
            }
        }
    }

    /// Utility function to get the most recent user-specified tag
    pub fn get_tag(&self) -> u64 {
        unsafe {
            hb_get_user_tag(&self.hb)
        }
    }

    /// Utility function to get the current window performance.
    pub fn get_window_perf(&self) -> f64 {
        unsafe {
            hb_get_window_rate(&self.hb)
        }
    }

    /// Utility function to get the current window power.
    pub fn get_window_pwr(&self) -> f64 {
        unsafe {
            hb_get_window_power(&self.hb)
        }
    }
}

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

    #[test]
    fn test_simple() {
        const TIME_INC: u64 = 1000000000;
        const ENERGY_INC: u64 = 1000000;
        let mut hb = HeartbeatContainer::new(5, None).unwrap();
        let mut start_time: u64 = 0;
        let mut end_time: u64 = TIME_INC;
        let mut start_energy: u64 = 0;
        let mut end_energy: u64 = ENERGY_INC;
        let mut tag: u64 = 0;
        for _ in 0..10 {
            hb.heartbeat_pow(tag, 1, start_time, end_time, start_energy, end_energy);
            assert!(hb.get_tag() == tag);
            assert!(hb.get_window_perf() == 1.0);
            assert!(hb.get_window_pwr() == 1.0);
            tag += 1;
            start_time = end_time;
            end_time += TIME_INC;
            start_energy = end_energy;
            end_energy += ENERGY_INC;
        }
    }
}
<|endoftext|>


<commit_before>use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<Stream<ReadStream<R>>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<Stream<ReadStream<File>>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream<ByteStream>> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = self.info();

    loop {
      match self.producer.parse(|i| frame_parser(i, &stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut self.output[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, &mut self.output);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Remove unused imports<commit_after>use nom::Err;

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<Stream<ReadStream<R>>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<Stream<ReadStream<File>>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream<ByteStream>> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = self.info();

    loop {
      match self.producer.parse(|i| frame_parser(i, &stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut self.output[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, &mut self.output);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


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

use opencl;
use opencl::hl::KernelArg;
use opencl::mem::{Buffer, CLBuffer};
use libc;
use ref_filter_map::ref_filter_map;

use array::Array;
use context::Context;
use helper;
use num::Num;
use range_arg::RangeArg;

pub enum TensorMode {
    In,
    Out,
    Mut,
}

pub struct Tensor<T: Num> {
    shape: Vec<usize>,
    dim_steps: Vec<usize>,
    buffer: CLBuffer<T>,
    event: RefCell<Option<Event>>,
}

impl<T: Num> Tensor<T> {
    pub fn new(ctx: &Context, shape: Vec<usize>, mode: TensorMode) -> Tensor<T> {
        let mem_mode =
            match mode {
                TensorMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                TensorMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                TensorMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        let buf_size = shape.iter().fold(1, |a, b| a*b);
        let dim_steps = helper::compute_dim_steps(&shape);
        Tensor {
            shape: shape,
            dim_steps: dim_steps,
            buffer: ctx.ctx.create_buffer(buf_size, mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn from_array(ctx: &Context,
                      array: &Array<T>,
                      mode: TensorMode) -> Tensor<T> {
        let mem_mode =
            match mode {
                TensorMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                TensorMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                TensorMode::Mut => { opencl::cl::CL_MEM_READ_WRITE },
            };
        Tensor {
            shape: array.shape().to_vec(),
            dim_steps: array.dim_steps().to_owned(),
            buffer: ctx.ctx.create_buffer_from(array.buffer(), mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn get(&self, ctx: &Context) -> Array<T> {
        let vec = ctx.queue.get(&self.buffer, self.get_event().as_ref().map(|x| &**x));
        Array::from_vec(self.shape.clone(), vec)
    }

    pub fn set(&self, ctx: &Context, array: &Array<T>) {
        ctx.queue.write(&self.buffer, &&array.buffer()[..], ());
    }

    pub fn shape(&self) -> &[usize] {
        &self.shape
    }

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

    pub fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    pub fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            ref_filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn slice<'t, 'r>(&'t self, r: &'r [RangeArg]) -> TensorView<'t, 'r, T> {
        TensorView {
            shape: self.shape.as_ref(),
            dim_steps: self.dim_steps.as_ref(),
            ranges: r,
            buffer: &self.buffer,
            event: &self.event,
        }
    }
}

impl<T: Num> KernelArg for Tensor<T> {
    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {
        self.buffer.get_value()
    }
}

impl<'t, 'r, T: Num> KernelArg for TensorView<'t, 'r, T> {
    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {
        self.buffer.get_value()
    }
}

pub struct TensorView<'t, 'r, T: Num+'t> {
    pub shape: &'t [usize],
    pub dim_steps: &'t [usize],
    ranges: &'r [RangeArg],
    buffer: &'t CLBuffer<T>,
    event: &'t RefCell<Option<Event>>,
}

impl<'t, 'r, T: Num> TensorView<'t, 'r, T> {
    pub fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    pub fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            ref_filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn view_offset(&self, dim: usize) -> usize {
        self.ranges[dim].start
    }

    pub fn view_shape(&self, dim: usize) -> usize {
        self.ranges[dim].len(self.shape[dim])
    }

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

pub type Event = opencl::hl::Event;

////////////////////////////////////////////////////////////////////////////////////////////////////

#[test]
fn test_tensor_slicing() {
    use ops::add_slice;

    let ref ctx = Context::new();

    let a = Array::from_vec(vec![4, 3], vec![2, 3, 4,
                                             6, 7, 8,
                                             10, 11, 12,
                                             14, 15, 16]);
    let at = Tensor::from_array(ctx, &a, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(1)];
    let atv = at.slice(slice);

    let b = Array::from_vec(vec![4, 4], vec![1, 2, 3, 4,
                                             5, 6, 7, 8,
                                             9, 10, 11, 12,
                                             13, 14, 15, 16]);
    let bt = Tensor::from_array(ctx, &b, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(3)];
    let btv = bt.slice(slice);

    let c = Array::from_vec(vec![4, 4], vec![0; 16]);
    let ct = Tensor::from_array(ctx, &c, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(2..4), RangeArg::from(0)];
    let ctv = ct.slice(slice);

    add_slice(ctx, &atv, &btv, &ctv);
    assert!(ct.get(ctx).buffer() == &[0, 0, 0, 0,
                                      0, 0, 0, 0,
                                      15, 0, 0, 0,
                                      23, 0, 0, 0]);
}
<commit_msg>cleanup<commit_after>use std::cell::{RefCell, Ref};

use opencl;
use opencl::hl::KernelArg;
use opencl::mem::{Buffer, CLBuffer};
use libc;
use ref_filter_map::ref_filter_map;

use array::Array;
use context::Context;
use helper;
use num::Num;
use range_arg::RangeArg;

pub enum TensorMode {
    In,
    Out,
    Mut,
}

pub struct Tensor<T: Num> {
    shape: Vec<usize>,
    dim_steps: Vec<usize>,
    buffer: CLBuffer<T>,
    event: RefCell<Option<Event>>,
}

impl<T: Num> Tensor<T> {
    pub fn new(ctx: &Context, shape: Vec<usize>, mode: TensorMode) -> Tensor<T> {
        let mem_mode =
            match mode {
                TensorMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                TensorMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                TensorMode::Mut => { opencl::cl::CL_MEM_READ_WRITE },
            };
        let buf_size = shape.iter().fold(1, |a, b| a*b);
        let dim_steps = helper::compute_dim_steps(&shape);
        Tensor {
            shape: shape,
            dim_steps: dim_steps,
            buffer: ctx.ctx.create_buffer(buf_size, mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn from_array(ctx: &Context,
                      array: &Array<T>,
                      mode: TensorMode) -> Tensor<T> {
        let mem_mode =
            match mode {
                TensorMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                TensorMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                TensorMode::Mut => { opencl::cl::CL_MEM_READ_WRITE },
            };
        Tensor {
            shape: array.shape().to_vec(),
            dim_steps: array.dim_steps().to_owned(),
            buffer: ctx.ctx.create_buffer_from(array.buffer(), mem_mode),
            event: RefCell::new(None),
        }
    }

    pub fn get(&self, ctx: &Context) -> Array<T> {
        let vec = ctx.queue.get(&self.buffer, self.get_event().as_ref().map(|x| &**x));
        Array::from_vec(self.shape.clone(), vec)
    }

    pub fn set(&self, ctx: &Context, array: &Array<T>) {
        ctx.queue.write(&self.buffer, &&array.buffer()[..], ());
    }

    pub fn shape(&self) -> &[usize] {
        &self.shape
    }

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

    pub fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    pub fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            ref_filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn slice<'t, 'r>(&'t self, r: &'r [RangeArg]) -> TensorView<'t, 'r, T> {
        TensorView {
            shape: self.shape.as_ref(),
            dim_steps: self.dim_steps.as_ref(),
            ranges: r,
            buffer: &self.buffer,
            event: &self.event,
        }
    }
}

impl<T: Num> KernelArg for Tensor<T> {
    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {
        self.buffer.get_value()
    }
}

impl<'t, 'r, T: Num> KernelArg for TensorView<'t, 'r, T> {
    fn get_value(&self) -> (libc::size_t, *const libc::c_void) {
        self.buffer.get_value()
    }
}

pub struct TensorView<'t, 'r, T: Num+'t> {
    pub shape: &'t [usize],
    pub dim_steps: &'t [usize],
    ranges: &'r [RangeArg],
    buffer: &'t CLBuffer<T>,
    event: &'t RefCell<Option<Event>>,
}

impl<'t, 'r, T: Num> TensorView<'t, 'r, T> {
    pub fn set_event(&self, e: Event) {
        *self.event.borrow_mut() = Some(e);
    }

    pub fn get_event(&self) -> Option<Ref<Event>> {
        if self.event.borrow().is_some() {
            ref_filter_map(self.event.borrow(), |o| o.as_ref())
        } else {
            None
        }
    }

    pub fn view_offset(&self, dim: usize) -> usize {
        self.ranges[dim].start
    }

    pub fn view_shape(&self, dim: usize) -> usize {
        self.ranges[dim].len(self.shape[dim])
    }

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

pub type Event = opencl::hl::Event;

////////////////////////////////////////////////////////////////////////////////////////////////////

#[test]
fn test_tensor_slicing() {
    use ops::add_slice;

    let ref ctx = Context::new();

    let a = Array::from_vec(vec![4, 3], vec![2, 3, 4,
                                             6, 7, 8,
                                             10, 11, 12,
                                             14, 15, 16]);
    let at = Tensor::from_array(ctx, &a, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(1)];
    let atv = at.slice(slice);

    let b = Array::from_vec(vec![4, 4], vec![1, 2, 3, 4,
                                             5, 6, 7, 8,
                                             9, 10, 11, 12,
                                             13, 14, 15, 16]);
    let bt = Tensor::from_array(ctx, &b, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(1..3), RangeArg::from(3)];
    let btv = bt.slice(slice);

    let c = Array::from_vec(vec![4, 4], vec![0; 16]);
    let ct = Tensor::from_array(ctx, &c, TensorMode::Mut);
    let slice: &[RangeArg] = &[RangeArg::from(2..4), RangeArg::from(0)];
    let ctv = ct.slice(slice);

    add_slice(ctx, &atv, &btv, &ctv);
    assert!(ct.get(ctx).buffer() == &[0, 0, 0, 0,
                                      0, 0, 0, 0,
                                      15, 0, 0, 0,
                                      23, 0, 0, 0]);
}
<|endoftext|>


<commit_before>use super::ToTokens;
use std::fmt::{self, Debug, Display};

use proc_macro;
use proc_macro2::{TokenStream, TokenTree};

/// Tokens produced by a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
#[derive(Clone, Default)]
pub struct Tokens {
    tts: Vec<TokenTree>,
}

impl Tokens {
    /// Empty tokens.
    pub fn new() -> Self {
        Tokens { tts: Vec::new() }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    pub fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.tts.push(token.into());
    }

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # use quote::{Tokens, ToTokens};
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    pub fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    pub fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    pub fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

impl ToTokens for Tokens {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.tts.extend(self.tts.iter().cloned());
    }

    fn into_tokens(self) -> Tokens {
        self
    }
}

impl From<Tokens> for TokenStream {
    fn from(tokens: Tokens) -> TokenStream {
        tokens.tts.into_iter().collect()
    }
}

impl From<Tokens> for proc_macro::TokenStream {
    fn from(tokens: Tokens) -> proc_macro::TokenStream {
        TokenStream::from(tokens).into()
    }
}

/// Allows a `Tokens` to be passed to `Tokens::append_all`.
impl IntoIterator for Tokens {
    type Item = TokenTree;
    type IntoIter = private::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        private::into_iter(self.tts.into_iter())
    }
}

mod private {
    use std::vec;
    use proc_macro2::TokenTree;

    pub struct IntoIter(vec::IntoIter<TokenTree>);

    pub fn into_iter(tts: vec::IntoIter<TokenTree>) -> IntoIter {
        IntoIter(tts)
    }

    impl Iterator for IntoIter {
        type Item = TokenTree;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.next()
        }
    }
}

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&TokenStream::from(self.clone()), formatter)
    }
}

impl Debug for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        struct DebugAsDisplay<'a, T: 'a>(&'a T);

        impl<'a, T> Debug for DebugAsDisplay<'a, T>
        where
            T: Display,
        {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                Display::fmt(self.0, formatter)
            }
        }

        formatter
            .debug_tuple("Tokens")
            .field(&DebugAsDisplay(self))
            .finish()
    }
}
<commit_msg>Implement Hash and PartialEq for quote::Tokens<commit_after>use super::ToTokens;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};

use proc_macro;
use proc_macro2::{TokenStream, TokenTree};

/// Tokens produced by a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
#[derive(Clone, Default)]
pub struct Tokens {
    tts: Vec<TokenTree>,
}

impl Tokens {
    /// Empty tokens.
    pub fn new() -> Self {
        Tokens { tts: Vec::new() }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends the token specified to this list of tokens.
    pub fn append<U>(&mut self, token: U)
    where
        U: Into<TokenTree>,
    {
        self.tts.push(token.into());
    }

    /// For use by `ToTokens` implementations.
    ///
    /// ```
    /// # #[macro_use] extern crate quote;
    /// # use quote::{Tokens, ToTokens};
    /// # fn main() {
    /// struct X;
    ///
    /// impl ToTokens for X {
    ///     fn to_tokens(&self, tokens: &mut Tokens) {
    ///         tokens.append_all(&[true, false]);
    ///     }
    /// }
    ///
    /// let tokens = quote!(#X);
    /// assert_eq!(tokens.to_string(), "true false");
    /// # }
    /// ```
    pub fn append_all<T, I>(&mut self, iter: I)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
    {
        for token in iter {
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all of the items in the iterator `I`, separated by the tokens
    /// `U`.
    pub fn append_separated<T, I, U>(&mut self, iter: I, op: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                op.to_tokens(self);
            }
            token.to_tokens(self);
        }
    }

    /// For use by `ToTokens` implementations.
    ///
    /// Appends all tokens in the iterator `I`, appending `U` after each
    /// element, including after the last element of the iterator.
    pub fn append_terminated<T, I, U>(&mut self, iter: I, term: U)
    where
        T: ToTokens,
        I: IntoIterator<Item = T>,
        U: ToTokens,
    {
        for token in iter {
            token.to_tokens(self);
            term.to_tokens(self);
        }
    }
}

impl ToTokens for Tokens {
    fn to_tokens(&self, dst: &mut Tokens) {
        dst.tts.extend(self.tts.iter().cloned());
    }

    fn into_tokens(self) -> Tokens {
        self
    }
}

impl From<Tokens> for TokenStream {
    fn from(tokens: Tokens) -> TokenStream {
        tokens.tts.into_iter().collect()
    }
}

impl From<Tokens> for proc_macro::TokenStream {
    fn from(tokens: Tokens) -> proc_macro::TokenStream {
        TokenStream::from(tokens).into()
    }
}

/// Allows a `Tokens` to be passed to `Tokens::append_all`.
impl IntoIterator for Tokens {
    type Item = TokenTree;
    type IntoIter = private::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        private::into_iter(self.tts.into_iter())
    }
}

mod private {
    use std::vec;
    use proc_macro2::TokenTree;

    pub struct IntoIter(vec::IntoIter<TokenTree>);

    pub fn into_iter(tts: vec::IntoIter<TokenTree>) -> IntoIter {
        IntoIter(tts)
    }

    impl Iterator for IntoIter {
        type Item = TokenTree;

        fn next(&mut self) -> Option<Self::Item> {
            self.0.next()
        }
    }
}

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&TokenStream::from(self.clone()), formatter)
    }
}

impl Debug for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        struct DebugAsDisplay<'a, T: 'a>(&'a T);

        impl<'a, T> Debug for DebugAsDisplay<'a, T>
        where
            T: Display,
        {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                Display::fmt(self.0, formatter)
            }
        }

        formatter
            .debug_tuple("Tokens")
            .field(&DebugAsDisplay(self))
            .finish()
    }
}

fn tt_eq(a: &TokenTree, b: &TokenTree) -> bool {
    use proc_macro2::{TokenNode, Delimiter, Spacing};

    match (&a.kind, &b.kind) {
        (&TokenNode::Group(d1, ref s1), &TokenNode::Group(d2, ref s2)) => {
            match (d1, d2) {
                (Delimiter::Parenthesis, Delimiter::Parenthesis)
                | (Delimiter::Brace, Delimiter::Brace)
                | (Delimiter::Bracket, Delimiter::Bracket)
                | (Delimiter::None, Delimiter::None) => {}
                _ => return false,
            }

            let s1 = s1.clone().into_iter();
            let mut s2 = s2.clone().into_iter();

            for item1 in s1 {
                let item2 = match s2.next() {
                    Some(item) => item,
                    None => return false,
                };
                if !tt_eq(&item1, &item2) {
                    return false;
                }
            }
            s2.next().is_none()
        }
        (&TokenNode::Op(o1, k1), &TokenNode::Op(o2, k2)) => {
            o1 == o2 && match (k1, k2) {
                (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
                _ => false,
            }
        }
        (&TokenNode::Literal(ref l1), &TokenNode::Literal(ref l2)) => {
            l1.to_string() == l2.to_string()
        }
        (&TokenNode::Term(ref s1), &TokenNode::Term(ref s2)) => s1.as_str() == s2.as_str(),
        _ => false,
    }
}

impl PartialEq for Tokens {
    fn eq(&self, other: &Self) -> bool {
        if self.tts.len() != other.tts.len() {
            return false;
        }

        self.tts
            .iter()
            .zip(other.tts.iter())
            .all(|(a, b)| tt_eq(a, b))
    }
}

fn tt_hash<H: Hasher>(tt: &TokenTree, h: &mut H) {
    use proc_macro2::{TokenNode, Delimiter, Spacing};

    match tt.kind {
        TokenNode::Group(delim, ref stream) => {
            0u8.hash(h);
            match delim {
                Delimiter::Parenthesis => 0u8.hash(h),
                Delimiter::Brace => 1u8.hash(h),
                Delimiter::Bracket => 2u8.hash(h),
                Delimiter::None => 3u8.hash(h),
            }

            for item in stream.clone() {
                tt_hash(&item, h);
            }
            0xffu8.hash(h); // terminator w/ a variant we don't normally hash
        }
        TokenNode::Op(op, kind) => {
            1u8.hash(h);
            op.hash(h);
            match kind {
                Spacing::Alone => 0u8.hash(h),
                Spacing::Joint => 1u8.hash(h),
            }
        }
        TokenNode::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
        TokenNode::Term(ref word) => (3u8, word.as_str()).hash(h),
    }
}

impl<'a> Hash for Tokens {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.tts.len().hash(h);
        for tt in &self.tts {
            tt_hash(&tt, h);
        }
    }
}
<|endoftext|>


<commit_before>//! Conversion of data structures to and from MDB_val
//!
//! Since MDB_val is valid through whole transaction, it is kind of safe
//! to keep plain data, i.e. to keep raw pointers and transmute them back
//! and forward into corresponding data structures to avoid any unnecessary
//! copying.
//!
//! `MdbValue` is a simple wrapper with bounded lifetime which should help
//! keep it sane, i.e. provide compile errors when data retrieved outlives
//! transaction.
//!
//! It would be extremely helpful to create `compile-fail` tests to ensure
//! this, but unfortunately there is no way yet.
//!
//! Note that due to https://github.com/rust-lang/rust/issues/17322 it is
//! impossible to convert `&'a str` and `&'a [u8]` for now

use std::{mod, mem};

use core::MdbValue;
use ffi::MDB_val;

/// `ToMdbValue` is supposed to convert a value to a memory
/// slice which `lmdb` uses to prevent multiple copying data
/// multiple times. May be unsafe.
#[experimental]
pub trait ToMdbValue for Sized? {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a>;
}

/// `FromMdbValue` is supposed to reconstruct a value from
/// memory slice. It allows to use zero copy where it is
/// required.
#[experimental]
pub trait FromMdbValue<'a, T:'a> {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> T;
}

impl ToMdbValue for Vec<u8> {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(std::mem::transmute(self.as_ptr()), self.len())
        }
    }
}

impl<'a> FromMdbValue<'a, Vec<u8>> for Vec<u8> {
    fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> Vec<u8> {
        unsafe {
            Vec::from_raw_buf(std::mem::transmute(value.get_ref()),
                                    value.get_size() as uint)
        }
    }
}

impl ToMdbValue for String {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            let t = self.as_slice();
            MdbValue::new(std::mem::transmute(t.as_ptr()), t.len())
        }
    }
}

// Conversion from `&'a str` and `&'a [u8]` is broken due:
// https://github.com/rust-lang/rust/issues/17322
impl<'a> ToMdbValue for &'a str {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(mem::transmute(self.as_ptr()),
                          self.len())
        }
    }
}

/*
impl<'a> ToMdbValue<'a> for &'a [u8] {
    fn to_mdb_value(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(std::mem::transmute(self.as_ptr()),
                          self.len())
        }
    }
}
*/

impl ToMdbValue for MDB_val {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new((*self).mv_data, (*self).mv_size as uint)
        }
    }
}

impl<'a> ToMdbValue for MdbValue<'a> {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        *self
    }
}

impl<'a> FromMdbValue<'a, String> for String {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> String {
        unsafe {
            String::from_raw_buf_len(std::mem::transmute(value.get_ref()),
                                     value.get_size()).to_string()
        }
    }
}

impl<'a> FromMdbValue<'a, ()> for () {
    fn from_mdb_value(_: &'a MdbValue<'a>) {
    }
}

impl<'a> FromMdbValue<'a, &'a str> for &'a str {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> &'a str {
        unsafe {
            std::mem::transmute(std::raw::Slice {
                data: value.get_ref(),
                len: value.get_size(),
            })
        }
    }
}

impl<'a> FromMdbValue<'a, &'a [u8]> for &'a [u8] {
    fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> &'a [u8] {
        unsafe {
            std::mem::transmute(std::raw::Slice {
                data: value.get_ref(),
                len: value.get_size(),
            })
        }
    }
}

macro_rules! mdb_for_primitive {
    ($t:ty) => (
        impl ToMdbValue for $t {
            fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
                MdbValue::new_from_sized(self)
            }
        }

        impl<'a> FromMdbValue<'a, $t> for $t {
            fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> $t {
                unsafe {
                    let t: *const $t = mem::transmute(value.get_ref());
                    *t
                }
            }
        }

        )
}

mdb_for_primitive!(u8)
mdb_for_primitive!(i8)
mdb_for_primitive!(u16)
mdb_for_primitive!(i16)
mdb_for_primitive!(u32)
mdb_for_primitive!(i32)
mdb_for_primitive!(u64)
mdb_for_primitive!(i64)
mdb_for_primitive!(f32)
mdb_for_primitive!(f64)
mdb_for_primitive!(bool)
<commit_msg>Update to nightly<commit_after>//! Conversion of data structures to and from MDB_val
//!
//! Since MDB_val is valid through whole transaction, it is kind of safe
//! to keep plain data, i.e. to keep raw pointers and transmute them back
//! and forward into corresponding data structures to avoid any unnecessary
//! copying.
//!
//! `MdbValue` is a simple wrapper with bounded lifetime which should help
//! keep it sane, i.e. provide compile errors when data retrieved outlives
//! transaction.
//!
//! It would be extremely helpful to create `compile-fail` tests to ensure
//! this, but unfortunately there is no way yet.
//!
//! Note that due to https://github.com/rust-lang/rust/issues/17322 it is
//! impossible to convert `&'a str` and `&'a [u8]` for now

use std::{mod, mem};

use core::MdbValue;
use ffi::MDB_val;

/// `ToMdbValue` is supposed to convert a value to a memory
/// slice which `lmdb` uses to prevent multiple copying data
/// multiple times. May be unsafe.
#[experimental]
pub trait ToMdbValue for Sized? {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a>;
}

/// `FromMdbValue` is supposed to reconstruct a value from
/// memory slice. It allows to use zero copy where it is
/// required.
#[experimental]
pub trait FromMdbValue<'a, T:'a> {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> T;
}

impl ToMdbValue for Vec<u8> {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(std::mem::transmute(self.as_ptr()), self.len())
        }
    }
}

impl ToMdbValue for String {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            let t = self.as_slice();
            MdbValue::new(std::mem::transmute(t.as_ptr()), t.len())
        }
    }
}

impl<'a> ToMdbValue for &'a str {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(mem::transmute(self.as_ptr()),
                          self.len())
        }
    }
}

impl<'a> ToMdbValue for &'a [u8] {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new(std::mem::transmute(self.as_ptr()),
                          self.len())
        }
    }
}

impl ToMdbValue for MDB_val {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        unsafe {
            MdbValue::new((*self).mv_data, (*self).mv_size as uint)
        }
    }
}

impl<'a> ToMdbValue for MdbValue<'a> {
    fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
        *self
    }
}

impl<'a> FromMdbValue<'a, String> for String {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> String {
        unsafe {
            String::from_raw_buf_len(std::mem::transmute(value.get_ref()),
                                     value.get_size()).to_string()
        }
    }
}

impl<'a> FromMdbValue<'a, Vec<u8>> for Vec<u8> {
    fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> Vec<u8> {
        unsafe {
            Vec::from_raw_buf(std::mem::transmute(value.get_ref()),
                              value.get_size() as uint)
        }
    }
}

impl<'a> FromMdbValue<'a, ()> for () {
    fn from_mdb_value(_: &'a MdbValue<'a>) {
    }
}

impl<'a> FromMdbValue<'a, &'a str> for &'a str {
    fn from_mdb_value(value: &'a MdbValue<'a>) -> &'a str {
        unsafe {
            std::mem::transmute(std::raw::Slice {
                data: value.get_ref(),
                len: value.get_size(),
            })
        }
    }
}

impl<'a> FromMdbValue<'a, &'a [u8]> for &'a [u8] {
    fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> &'a [u8] {
        unsafe {
            std::mem::transmute(std::raw::Slice {
                data: value.get_ref(),
                len: value.get_size(),
            })
        }
    }
}

macro_rules! mdb_for_primitive {
    ($t:ty) => (
        impl ToMdbValue for $t {
            fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
                MdbValue::new_from_sized(self)
            }
        }

        impl<'a> FromMdbValue<'a, $t> for $t {
            fn from_mdb_value<'a>(value: &'a MdbValue<'a>) -> $t {
                unsafe {
                    let t: *const $t = mem::transmute(value.get_ref());
                    *t
                }
            }
        }

        )
}

mdb_for_primitive!(u8)
mdb_for_primitive!(i8)
mdb_for_primitive!(u16)
mdb_for_primitive!(i16)
mdb_for_primitive!(u32)
mdb_for_primitive!(i32)
mdb_for_primitive!(u64)
mdb_for_primitive!(i64)
mdb_for_primitive!(f32)
mdb_for_primitive!(f64)
mdb_for_primitive!(bool)
<|endoftext|>


<commit_before>//! Traits that I can't find elsewhere.

/// A type that can be converted to an f32
pub trait ToFloat: Copy {
    fn to_float(self) -> f32;
}

/// A type to which we can clamp an f32
pub trait Clamp {
    fn clamp(x: f32) -> Self;
}

impl ToFloat for u8 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i8 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for u16 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i16 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for u32 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i32 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for f32 {
    fn to_float(self) -> f32 {
        return self;
    }
}

impl Clamp for u8 {
    fn clamp(x: f32) -> u8 {
        if x < 0f32 { return 0;}
        if x > 255f32 { return 255; }
        x as u8
    }
}
<commit_msg>Add WithChannel trait<commit_after>//! Traits that I can't find elsewhere.

use image::{
    Rgb,
    Rgba,
    Luma,
    Pixel,
    Primitive
};

/// Used to name the type we get by replacing
/// the channel type of a given Pixel type.
pub trait WithChannel<C>: Pixel {
    type Pixel;
}

impl<T, U> WithChannel<U> for Rgb<T>
    where T: Primitive + 'static,
          U: Primitive + 'static {
    type Pixel = Rgb<U>;
}

impl<T, U> WithChannel<U> for Rgba<T>
    where T: Primitive + 'static,
          U: Primitive + 'static {
    type Pixel = Rgba<U>;
}

impl<T, U> WithChannel<U> for Luma<T>
    where T: Primitive + 'static,
          U: Primitive + 'static {
    type Pixel = Luma<U>;
}

/// A type that can be converted to an f32
pub trait ToFloat: Copy {
    fn to_float(self) -> f32;
}

/// A type to which we can clamp an f32. Implementations
/// are not required to handle NaNs gracefully.
pub trait Clamp {
    fn clamp(x: f32) -> Self;
}

impl ToFloat for u8 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i8 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for u16 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i16 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for u32 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for i32 {
    fn to_float(self) -> f32 {
        return self as f32;
    }
}

impl ToFloat for f32 {
    fn to_float(self) -> f32 {
        return self;
    }
}

impl Clamp for u8 {
    fn clamp(x: f32) -> u8 {
        if x < 0f32 { return 0;}
        if x > 255f32 { return 255; }
        x as u8
    }
}

#[cfg(test)]
mod test {

    use super::Clamp;

    #[test]
    fn test_clamp_u8() {
        let t: u8 = Clamp::clamp(255f32);
        assert_eq!(t, 255u8);
        let u: u8 = Clamp::clamp(300f32);
        assert_eq!(u, 255u8);
        let v: u8 = Clamp::clamp(0f32);
        assert_eq!(v, 0u8);
        let w: u8 = Clamp::clamp(-5f32);
        assert_eq!(w, 0u8);
    }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};

/// Trait represents global state of the
/// entire simulation which can updated
/// independently from any particular cell.
/// Consider to store there as much as you can
/// because this data will be created only once
/// and will not be copied.
pub trait EvolutionState {
    /// Method is called once between cells' updates.
    fn update(&mut self);
}

pub trait Cell: Serialize + Deserialize {
    type Coord: Coord;
    type State: EvolutionState;

    fn update<'a, I>(&'a mut self, old: &'a Self, neighbors: I, &Self::State)
        where I: Iterator<Item = Option<&'a Self>>;

    fn with_coord<C: Coord>(C) -> Self;
    fn coord(&self) -> &Self::Coord;
    fn set_coord<C: Coord>(&mut self, &C);
}

/// Represents neighborhood for automata.
pub trait Nhood {
    /// Coords this nhood supports.
    type Coord: Coord;

    /// Method returns for any given coord
    /// coordinates of surrounding neighbors.
    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;
    /// Hint for grid.
    fn neighbors_count(&self) -> usize;
}

/// Basic coordinate with three components.
/// This crate is used for creating automata
/// on 2D grids for now, so `z` has default impl.
pub trait Coord: Clone + Serialize + Deserialize {
    /// Build coord from any other representation of coord.
    fn from_2d(x: i32, y: i32) -> Self;

    /// Returns `x` component.
    fn x(&self) -> i32;
    /// Returns `y` component.
    fn y(&self) -> i32;
    /// Returns `z` component.
    fn z(&self) -> i32 { 0 }
}

/// Grid stores cells and updates them. Also
/// grid contains global evolution state.
pub trait Grid {
    /// Grid wants to work with them.
    type Cell: Cell;
    /// Grid knows how to work with them.
    type Coord: Coord;

    /// One step in evolution.
    fn update(&mut self);

    /// Getter for evolution state.
    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State;
    /// Getter for all cells. It is `Vec` because
    /// Rust does not have abstract return types for now.
    /// So custom grids are doomed to use `Vec`s internally.
    fn cells(&self) -> &Vec<Self::Cell>;
    /// Returns `Coord` with rows and cols counts of grid (2D).
    /// 3D grids would have more dimensions.
    fn dimensions(&self) -> Self::Coord;

    /// This method gives an ability to change grid externally.
    /// It could be done from consumer, for example
    /// (consider an app where you reacting to user input),
    /// or from engine (consider distributed engine received
    /// updates from nodes).
    fn set_cells(&mut self, Vec<Self::Cell>);
}

/// Interface to the outer world.
pub trait Consumer {
    /// Cells supported by this consumer. Helps
    /// to use cells from grid directly if grid
    /// has the same cell in it.
    type Cell: Cell;

    /// Called once when all cells has been updated.
    fn consume<G>(&mut self, &mut G)
        where G: Grid<Cell = Self::Cell>;
}

/// Interlayer between grid and consumer(s).
pub trait Engine {
    /// Runs evolution fixed number of times.
    fn run_times(&mut self, i64);
}
<commit_msg>Note about Cell.<commit_after>use serde::{Deserialize, Serialize};

/// Trait represents global state of the
/// entire simulation which can updated
/// independently from any particular cell.
/// Consider to store there as much as you can
/// because this data will be created only once
/// and will not be copied.
pub trait EvolutionState {
    /// Method is called once between cells' updates.
    fn update(&mut self);
}

/// Main trait should be implemented in user's code.
/// Such structs contain main logic of cellular
/// automaton. Grids can handle only one cell,
/// so it should be all-in-one.
pub trait Cell: Serialize + Deserialize {
    /// Coords supported by Cell.
    type Coord: Coord;
    /// Global state of evolution.
    type State: EvolutionState;

    /// This method is called for every instance of Cell
    /// in grid. Cell can mutate itself. Grid should pass
    /// neighbors, previous version of this Cell and the
    /// global state.
    fn update<'a, I>(&'a mut self, old: &'a Self, neighbors: I, &Self::State)
        where I: Iterator<Item = Option<&'a Self>>;

    /// Constructs Cell with given coord.
    fn with_coord<C: Coord>(C) -> Self;
    /// Getter for cell's coordinate.
    fn coord(&self) -> &Self::Coord;
    /// Setter for cell's coordinate.
    fn set_coord<C: Coord>(&mut self, &C);
}

/// Represents neighborhood for automata.
pub trait Nhood {
    /// Coords this nhood supports.
    type Coord: Coord;

    /// Method returns for any given coord
    /// coordinates of surrounding neighbors.
    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;
    /// Hint for grid.
    fn neighbors_count(&self) -> usize;
}

/// Basic coordinate with three components.
/// This crate is used for creating automata
/// on 2D grids for now, so `z` has default impl.
pub trait Coord: Clone + Serialize + Deserialize {
    /// Build coord from any other representation of coord.
    fn from_2d(x: i32, y: i32) -> Self;

    /// Returns `x` component.
    fn x(&self) -> i32;
    /// Returns `y` component.
    fn y(&self) -> i32;
    /// Returns `z` component.
    fn z(&self) -> i32 { 0 }
}

/// Grid stores cells and updates them. Also
/// grid contains global evolution state.
pub trait Grid {
    /// Grid wants to work with them.
    type Cell: Cell;
    /// Grid knows how to work with them.
    type Coord: Coord;

    /// One step in evolution.
    fn update(&mut self);

    /// Getter for evolution state.
    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State;
    /// Getter for all cells. It is `Vec` because
    /// Rust does not have abstract return types for now.
    /// So custom grids are doomed to use `Vec`s internally.
    fn cells(&self) -> &Vec<Self::Cell>;
    /// Returns `Coord` with rows and cols counts of grid (2D).
    /// 3D grids would have more dimensions.
    fn dimensions(&self) -> Self::Coord;

    /// This method gives an ability to change grid externally.
    /// It could be done from consumer, for example
    /// (consider an app where you reacting to user input),
    /// or from engine (consider distributed engine received
    /// updates from nodes).
    fn set_cells(&mut self, Vec<Self::Cell>);
}

/// Interface to the outer world.
pub trait Consumer {
    /// Cells supported by this consumer. Helps
    /// to use cells from grid directly if grid
    /// has the same cell in it.
    type Cell: Cell;

    /// Called once when all cells has been updated.
    fn consume<G>(&mut self, &mut G)
        where G: Grid<Cell = Self::Cell>;
}

/// Interlayer between grid and consumer(s).
pub trait Engine {
    /// Runs evolution fixed number of times.
    fn run_times(&mut self, i64);
}
<|endoftext|>


<commit_before>#![feature(convert)]
#![feature(slice_patterns)]
#![feature(collections)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

struct VM<'a> {
  stack: Vec<Expr>,
  instructions: Vec<&'a str>,
  locals: HashMap<&'a str, Expr>,
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      stack: Vec::new(),
      instructions: instructions,
      locals: HashMap::new(),
    }
  }

  fn unsafe_pop(&mut self) -> Expr {
    match self.stack.pop() {
      Some(expr) => expr,
      None => panic!("VM error: stack is empty"),
    }
  }

  pub fn run(&mut self) {
    // just some aliases for brevity
    let len = self.instructions.len();

    // VM variables (might be moved back to the struct itself)
    let mut ip = 0; // instruction pointer
    let mut carry = false;

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        ["push", "int", n] => self.stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        ["push", "str", n] => self.stack.push(Expr::Str(String::from_str(n))),

        ["dup"] => {
          let expr = self.unsafe_pop();
          self.stack.push(expr.clone());
          self.stack.push(expr);
        },

        // convert to string
        ["strconv", "int"] => if let Some(&Expr::Int(arg)) = self.stack.last() {
          self.stack.push(Expr::Str(arg.to_string()));
        } else {
          panic!("VM error: cannot convert int to string");
        },

        // how = "carry" | "always"
        ["jump", how, n] => {
          let new_ip = n.parse::<usize>().unwrap();

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how != "carry" || carry {
              ip = new_ip;
            }
            // only reset carry if it was used
            if how == "carry" {
              carry = false;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        ["carry", "set", val] => carry = val == "true",
        ["carry", "invert"] => carry = !carry,

        ["call", "say"] => if let Some(Expr::Str(arg)) = self.stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call! a call to infix:<...>, that is
        ["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 + arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          self.stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `add`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        ["cmp", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          carry = match op {
            "<" => arg1 < arg2,
            ">" => arg1 > arg2,
            "<=" => arg1 <= arg2,
            ">=" => arg1 >= arg2,
            "=" => arg1 == arg2,
            _ => panic!("VM error: unrecognized `cmp` operator: {}", op),
          };
        } else {
          panic!("VM error: not enough arguments to `cmp`");
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        ["local", "load", name] => match self.locals.get(name) {
          Some(expr) => self.stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        ["local", "store", name] => if let Some(arg) = self.stack.pop() {
          let _ = self.locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        [instr, ..] => panic!("VM error: no such instruction {}", instr),
        [..] => panic!("VM error: Unrecognized instruction!"),
      }
    }
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<commit_msg>Remove "infix<..>", since this most probably will not have a real grammar.<commit_after>#![feature(convert)]
#![feature(slice_patterns)]
#![feature(collections)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

struct VM<'a> {
  stack: Vec<Expr>,
  instructions: Vec<&'a str>,
  locals: HashMap<&'a str, Expr>,
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      stack: Vec::new(),
      instructions: instructions,
      locals: HashMap::new(),
    }
  }

  fn unsafe_pop(&mut self) -> Expr {
    match self.stack.pop() {
      Some(expr) => expr,
      None => panic!("VM error: stack is empty"),
    }
  }

  pub fn run(&mut self) {
    // just some aliases for brevity
    let len = self.instructions.len();

    // VM variables (might be moved back to the struct itself)
    let mut ip = 0; // instruction pointer
    let mut carry = false;

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        ["push", "int", n] => self.stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        ["push", "str", n] => self.stack.push(Expr::Str(String::from_str(n))),

        ["dup"] => {
          let expr = self.unsafe_pop();
          self.stack.push(expr.clone());
          self.stack.push(expr);
        },

        // convert to string
        ["strconv", "int"] => if let Some(&Expr::Int(arg)) = self.stack.last() {
          self.stack.push(Expr::Str(arg.to_string()));
        } else {
          panic!("VM error: cannot convert int to string");
        },

        // how = "carry" | "always"
        ["jump", how, n] => {
          let new_ip = n.parse::<usize>().unwrap();

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how != "carry" || carry {
              ip = new_ip;
            }
            // only reset carry if it was used
            if how == "carry" {
              carry = false;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        ["carry", "set", val] => carry = val == "true",
        ["carry", "invert"] => carry = !carry,

        ["call", "say"] => if let Some(Expr::Str(arg)) = self.stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        ["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 + arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          self.stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `add`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        ["cmp", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          carry = match op {
            "<" => arg1 < arg2,
            ">" => arg1 > arg2,
            "<=" => arg1 <= arg2,
            ">=" => arg1 >= arg2,
            "=" => arg1 == arg2,
            _ => panic!("VM error: unrecognized `cmp` operator: {}", op),
          };
        } else {
          panic!("VM error: not enough arguments to `cmp`");
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        ["local", "load", name] => match self.locals.get(name) {
          Some(expr) => self.stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        ["local", "store", name] => if let Some(arg) = self.stack.pop() {
          let _ = self.locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        [instr, ..] => panic!("VM error: no such instruction {}", instr),
        [..] => panic!("VM error: Unrecognized instruction!"),
      }
    }
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<|endoftext|>


<commit_before>//! Module: czmq-zframe

use {czmq_sys, Error, ErrorKind, RawInterface, Result, Sockish};
use std::{error, fmt, ptr, result, slice};
use std::ffi::{CStr, CString};
use std::os::raw::c_void;

bitflags! {
    pub flags Flags: i32 {
        const ZFRAME_MORE     = 0b00000001,
        const ZFRAME_REUSE    = 0b00000010,
        const ZFRAME_DONTWAIT = 0b00000100,
    }
}

#[derive(Eq)]
pub struct ZFrame {
    zframe: *mut czmq_sys::zframe_t,
    owned: bool,
}

unsafe impl Send for ZFrame {}
unsafe impl Sync for ZFrame {}

impl Drop for ZFrame {
    fn drop(&mut self) {
        if self.owned {
            unsafe { czmq_sys::zframe_destroy(&mut self.zframe) };
        }
    }
}

impl PartialEq for ZFrame {
    fn eq(&self, other: &ZFrame) -> bool {
        ZFrame::eq(self, other)
    }
}

impl ZFrame {
    pub fn new(data: &[u8]) -> Result<ZFrame> {
        let data_c = CString::new(data).unwrap().into_raw();
        let zframe = unsafe { czmq_sys::zframe_new(data_c as *const c_void, data.len() as u64) };
        unsafe { CString::from_raw(data_c) };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::Instantiate));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    pub fn empty() -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_new_empty() };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::Instantiate));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    // The correlating C fn zframe_from wraps zframe_new(), which is
    // already wrapped by ZFrame::new, thus we can call our new()
    // instead.
    pub fn from(frame: &str) -> Result<ZFrame> {
        Self::new(frame.as_bytes())
    }

    pub fn recv<S: Sockish>(source: &S) -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_recv(source.borrow_raw()) };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    // This fn consumes the ZFrame, implying no REUSE flag
    pub fn send<D: Sockish>(self, dest: &D, flags: Option<Flags>) -> Result<i32> {
        let mut zframe = self;
        zframe.do_send(dest.borrow_raw(), flags)
    }

    // This fn doesn't consume the ZFrame, which implies REUSE flag
    pub fn send_reuse<D: Sockish>(&mut self, dest: &D, flags: Option<Flags>) -> Result<i32> {
        let flags = if let Some(f) = flags {
            f | ZFRAME_REUSE
        } else {
            ZFRAME_REUSE
        };
        self.do_send(dest.borrow_raw(), Some(flags))
    }

    fn do_send(&mut self, dest: *mut c_void, flags: Option<Flags>) -> Result<i32> {
        let flags_c = if let Some(f) = flags { f.bits() } else { 0 };
        let size = unsafe { czmq_sys::zframe_send(&mut self.zframe as *mut *mut czmq_sys::zframe_t, dest, flags_c) };
        if size == -1 {
            Err(Error::new(ErrorKind::NonZero, ZFrameError::CmdFailed))
        } else {
            Ok(size)
        }
    }

    pub fn size(&self) -> usize {
        unsafe { czmq_sys::zframe_size(self.zframe) as usize }
    }

    pub fn data(&self) -> Result<result::Result<String, Vec<u8>>> {
        let data = unsafe { czmq_sys::zframe_data(self.zframe) };

        if data == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let bytes = unsafe { slice::from_raw_parts(data, self.size()) };
            match String::from_utf8(bytes.to_vec()) {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes.to_vec()))
            }
        }
    }

    pub fn meta(&self, property: &str) -> Option<result::Result<String, Vec<u8>>> {
        let property_c = CString::new(property).unwrap_or(CString::new("").unwrap());
        let meta = unsafe { czmq_sys::zframe_meta(self.zframe, property_c.as_ptr()) };

        if meta == ptr::null_mut() {
            None
        } else {
            let c_string = unsafe { CStr::from_ptr(meta) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Some(Ok(s)),
                Err(_) => Some(Err(bytes)),
            }
        }
    }

    pub fn dup(&self) -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_dup(self.zframe) };

        if zframe == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            Ok(ZFrame {
                zframe: zframe,
                owned: true,
            })
        }
    }

    pub fn strhex(&self) -> Result<result::Result<String, Vec<u8>>> {
        let hex = unsafe { czmq_sys::zframe_strhex(self.zframe) };

        if hex == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let c_string = unsafe { CStr::from_ptr(hex) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes)),
            }
        }
    }

    pub fn strdup(&self) -> Result<result::Result<String, Vec<u8>>> {
        let string = unsafe { czmq_sys::zframe_strdup(self.zframe) };

        if string == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let c_string = unsafe { CStr::from_ptr(string) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes)),
            }
        }
    }

    pub fn streq(&self, string: &str) -> bool {
        unsafe { czmq_sys::zframe_streq(self.zframe, CString::new(string).unwrap_or(CString::new("").unwrap()).as_ptr()) == 1 }
    }

    pub fn more(&self) -> bool {
        unsafe { czmq_sys::zframe_more(self.zframe) == 1 }
    }

    pub fn set_more(&self, more: bool) {
        unsafe { czmq_sys::zframe_set_more(self.zframe, if more { 1 } else { 0 }) }
    }

    pub fn eq(&self, other: &ZFrame) -> bool {
        unsafe { czmq_sys::zframe_eq(self.zframe, other.zframe) == 1 }
    }

    pub fn reset(&self, data: &[u8]) {
        unsafe { czmq_sys::zframe_reset(self.zframe, data.as_ptr() as *const c_void, data.len() as u64) };
    }

    pub fn print(&self, prefix: Option<&str>) {
        let prefix_ptr = match prefix {
            Some(p) => CString::new(p).unwrap_or(CString::new("").unwrap()).as_ptr(),
            None => ptr::null(),
        };
        unsafe { czmq_sys::zframe_print(self.zframe, prefix_ptr) };
    }
}

impl RawInterface<czmq_sys::zframe_t> for ZFrame {
    fn from_raw(ptr: *mut czmq_sys::zframe_t, owned: bool) -> ZFrame {
        ZFrame {
            zframe: ptr,
            owned: owned,
        }
    }

    fn into_raw(mut self) -> *mut czmq_sys::zframe_t {
        self.owned = false;
        self.zframe
    }

    fn borrow_raw(&self) -> *mut czmq_sys::zframe_t {
        self.zframe
    }
}

#[derive(Debug)]
pub enum ZFrameError {
    Instantiate,
    CmdFailed,
}

impl fmt::Display for ZFrameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ZFrameError::Instantiate => write!(f, "Could not instantiate new ZFrame struct"),
            ZFrameError::CmdFailed => write!(f, "ZFrame command failed"),
        }
    }
}

impl error::Error for ZFrameError {
    fn description(&self) -> &str {
        match *self {
            ZFrameError::Instantiate => "Could not instantiate new ZFrame struct",
            ZFrameError::CmdFailed => "ZFrame command failed",
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {zmq, ZSock, zsys_init};

    #[test]
    fn test_sendrecv_zmq() {
        let mut ctx = zmq::Context::new();

        let mut server = ctx.socket(zmq::REP).unwrap();
        server.bind("inproc://zframe_sendrecv_zmq").unwrap();

        let mut client = ctx.socket(zmq::REQ).unwrap();
        client.connect("inproc://zframe_sendrecv_zmq").unwrap();

        let mut zframe1 = ZFrame::from("Hello world!").unwrap();
        zframe1.send_reuse(&client, Some(ZFRAME_MORE)).unwrap();
        zframe1.send(&client, None).unwrap();

        for _ in 1..2 {
            let zframe = ZFrame::recv(&server).unwrap();
            assert_eq!(zframe.data().unwrap().unwrap(), "Hello world!");
        }
    }

    #[test]
    fn test_sendrecv_zsock() {
        zsys_init();

        let server = ZSock::new_rep("inproc://zframe_sendrecv_zsock").unwrap();
        let client = ZSock::new_req("inproc://zframe_sendrecv_zsock").unwrap();

        let mut zframe1 = ZFrame::from("Hello world!").unwrap();
        zframe1.send_reuse(&client, Some(ZFRAME_MORE)).unwrap();
        zframe1.send(&client, None).unwrap();

        for _ in 1..2 {
            let zframe = ZFrame::recv(&server).unwrap();
            assert_eq!(zframe.data().unwrap().unwrap(), "Hello world!");
        }
    }

    #[test]
    fn test_dup() {
        let zframe = ZFrame::from("moo cow").unwrap();
        let zframe_dup = zframe.dup().unwrap();
        assert_eq!(zframe_dup.data().unwrap().unwrap(), "moo cow");
    }

    #[test]
    fn test_strhex() {
        let zframe = ZFrame::from("Oh Tobias, you blowhard!").unwrap();
        assert_eq!(zframe.strhex().unwrap().unwrap(), "4F6820546F626961732C20796F7520626C6F776861726421");
    }

    #[test]
    fn test_strdup() {
        let zframe = ZFrame::from("Because that's how you get ants, Lana!").unwrap();
        assert_eq!(zframe.strdup().unwrap().unwrap(), "Because that's how you get ants, Lana!");
    }

    #[test]
    fn test_streq() {
        let zframe = ZFrame::from("And that's why you always leave a note.").unwrap();
        assert!(zframe.streq("And that's why you always leave a note."));
    }

    #[test]
    fn test_more() {
        let zframe = ZFrame::empty().unwrap();
        zframe.set_more(true);
        assert!(zframe.more());
        zframe.set_more(false);
        assert!(!zframe.more());
    }

    #[test]
    fn test_eq() {
        let zframe1 = ZFrame::from("Steve Holt!").unwrap();
        let zframe2 = ZFrame::from("Steve Holt!").unwrap();
        assert!(zframe1.eq(&zframe2));
    }

    #[test]
    fn test_reset() {
        let zframe = ZFrame::from("Phrasing!").unwrap();
        zframe.reset("Holy shitsnacks!".as_bytes());
        assert_eq!(zframe.data().unwrap().unwrap(), "Holy shitsnacks!");
    }

    // XXX We need to capture output here before we can test.
    // #[test]
    // fn test_print() {
    //     let zframe = ZFrame::from("You're not my supervisor!").unwrap();
    //     zframe.print(Some("prefix_"));
    //     zframe.print(None);
    // }
}
<commit_msg>Don't convert byte slice to CString. That was stupid...<commit_after>//! Module: czmq-zframe

use {czmq_sys, Error, ErrorKind, RawInterface, Result, Sockish};
use std::{error, fmt, ptr, result, slice};
use std::ffi::{CStr, CString};
use std::os::raw::c_void;

bitflags! {
    pub flags Flags: i32 {
        const ZFRAME_MORE     = 0b00000001,
        const ZFRAME_REUSE    = 0b00000010,
        const ZFRAME_DONTWAIT = 0b00000100,
    }
}

#[derive(Eq)]
pub struct ZFrame {
    zframe: *mut czmq_sys::zframe_t,
    owned: bool,
}

unsafe impl Send for ZFrame {}
unsafe impl Sync for ZFrame {}

impl Drop for ZFrame {
    fn drop(&mut self) {
        if self.owned {
            unsafe { czmq_sys::zframe_destroy(&mut self.zframe) };
        }
    }
}

impl PartialEq for ZFrame {
    fn eq(&self, other: &ZFrame) -> bool {
        ZFrame::eq(self, other)
    }
}

impl ZFrame {
    pub fn new(data: &[u8]) -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_new(data.as_ptr() as *const c_void, data.len() as u64) };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::Instantiate));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    pub fn empty() -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_new_empty() };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::Instantiate));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    // The correlating C fn zframe_from wraps zframe_new(), which is
    // already wrapped by ZFrame::new, thus we can call our new()
    // instead.
    pub fn from(frame: &str) -> Result<ZFrame> {
        Self::new(frame.as_bytes())
    }

    pub fn recv<S: Sockish>(source: &S) -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_recv(source.borrow_raw()) };

        if zframe == ptr::null_mut() {
            return Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed));
        }

        Ok(ZFrame {
            zframe: zframe,
            owned: true,
        })
    }

    // This fn consumes the ZFrame, implying no REUSE flag
    pub fn send<D: Sockish>(self, dest: &D, flags: Option<Flags>) -> Result<i32> {
        let mut zframe = self;
        zframe.do_send(dest.borrow_raw(), flags)
    }

    // This fn doesn't consume the ZFrame, which implies REUSE flag
    pub fn send_reuse<D: Sockish>(&mut self, dest: &D, flags: Option<Flags>) -> Result<i32> {
        let flags = if let Some(f) = flags {
            f | ZFRAME_REUSE
        } else {
            ZFRAME_REUSE
        };
        self.do_send(dest.borrow_raw(), Some(flags))
    }

    fn do_send(&mut self, dest: *mut c_void, flags: Option<Flags>) -> Result<i32> {
        let flags_c = if let Some(f) = flags { f.bits() } else { 0 };
        let size = unsafe { czmq_sys::zframe_send(&mut self.zframe as *mut *mut czmq_sys::zframe_t, dest, flags_c) };
        if size == -1 {
            Err(Error::new(ErrorKind::NonZero, ZFrameError::CmdFailed))
        } else {
            Ok(size)
        }
    }

    pub fn size(&self) -> usize {
        unsafe { czmq_sys::zframe_size(self.zframe) as usize }
    }

    pub fn data(&self) -> Result<result::Result<String, Vec<u8>>> {
        let data = unsafe { czmq_sys::zframe_data(self.zframe) };

        if data == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let bytes = unsafe { slice::from_raw_parts(data, self.size()) };
            match String::from_utf8(bytes.to_vec()) {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes.to_vec()))
            }
        }
    }

    pub fn meta(&self, property: &str) -> Option<result::Result<String, Vec<u8>>> {
        let property_c = CString::new(property).unwrap_or(CString::new("").unwrap());
        let meta = unsafe { czmq_sys::zframe_meta(self.zframe, property_c.as_ptr()) };

        if meta == ptr::null_mut() {
            None
        } else {
            let c_string = unsafe { CStr::from_ptr(meta) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Some(Ok(s)),
                Err(_) => Some(Err(bytes)),
            }
        }
    }

    pub fn dup(&self) -> Result<ZFrame> {
        let zframe = unsafe { czmq_sys::zframe_dup(self.zframe) };

        if zframe == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            Ok(ZFrame {
                zframe: zframe,
                owned: true,
            })
        }
    }

    pub fn strhex(&self) -> Result<result::Result<String, Vec<u8>>> {
        let hex = unsafe { czmq_sys::zframe_strhex(self.zframe) };

        if hex == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let c_string = unsafe { CStr::from_ptr(hex) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes)),
            }
        }
    }

    pub fn strdup(&self) -> Result<result::Result<String, Vec<u8>>> {
        let string = unsafe { czmq_sys::zframe_strdup(self.zframe) };

        if string == ptr::null_mut() {
            Err(Error::new(ErrorKind::NullPtr, ZFrameError::CmdFailed))
        } else {
            let c_string = unsafe { CStr::from_ptr(string) }.to_owned();
            let bytes = c_string.as_bytes().to_vec();
            match c_string.into_string() {
                Ok(s) => Ok(Ok(s)),
                Err(_) => Ok(Err(bytes)),
            }
        }
    }

    pub fn streq(&self, string: &str) -> bool {
        unsafe { czmq_sys::zframe_streq(self.zframe, CString::new(string).unwrap_or(CString::new("").unwrap()).as_ptr()) == 1 }
    }

    pub fn more(&self) -> bool {
        unsafe { czmq_sys::zframe_more(self.zframe) == 1 }
    }

    pub fn set_more(&self, more: bool) {
        unsafe { czmq_sys::zframe_set_more(self.zframe, if more { 1 } else { 0 }) }
    }

    pub fn eq(&self, other: &ZFrame) -> bool {
        unsafe { czmq_sys::zframe_eq(self.zframe, other.zframe) == 1 }
    }

    pub fn reset(&self, data: &[u8]) {
        unsafe { czmq_sys::zframe_reset(self.zframe, data.as_ptr() as *const c_void, data.len() as u64) };
    }

    pub fn print(&self, prefix: Option<&str>) {
        let prefix_ptr = match prefix {
            Some(p) => CString::new(p).unwrap_or(CString::new("").unwrap()).as_ptr(),
            None => ptr::null(),
        };
        unsafe { czmq_sys::zframe_print(self.zframe, prefix_ptr) };
    }
}

impl RawInterface<czmq_sys::zframe_t> for ZFrame {
    fn from_raw(ptr: *mut czmq_sys::zframe_t, owned: bool) -> ZFrame {
        ZFrame {
            zframe: ptr,
            owned: owned,
        }
    }

    fn into_raw(mut self) -> *mut czmq_sys::zframe_t {
        self.owned = false;
        self.zframe
    }

    fn borrow_raw(&self) -> *mut czmq_sys::zframe_t {
        self.zframe
    }
}

#[derive(Debug)]
pub enum ZFrameError {
    Instantiate,
    CmdFailed,
}

impl fmt::Display for ZFrameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ZFrameError::Instantiate => write!(f, "Could not instantiate new ZFrame struct"),
            ZFrameError::CmdFailed => write!(f, "ZFrame command failed"),
        }
    }
}

impl error::Error for ZFrameError {
    fn description(&self) -> &str {
        match *self {
            ZFrameError::Instantiate => "Could not instantiate new ZFrame struct",
            ZFrameError::CmdFailed => "ZFrame command failed",
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {zmq, ZSock, zsys_init};

    #[test]
    fn test_sendrecv_zmq() {
        let mut ctx = zmq::Context::new();

        let mut server = ctx.socket(zmq::REP).unwrap();
        server.bind("inproc://zframe_sendrecv_zmq").unwrap();

        let mut client = ctx.socket(zmq::REQ).unwrap();
        client.connect("inproc://zframe_sendrecv_zmq").unwrap();

        let mut zframe1 = ZFrame::from("Hello world!").unwrap();
        zframe1.send_reuse(&client, Some(ZFRAME_MORE)).unwrap();
        zframe1.send(&client, None).unwrap();

        for _ in 1..2 {
            let zframe = ZFrame::recv(&server).unwrap();
            assert_eq!(zframe.data().unwrap().unwrap(), "Hello world!");
        }
    }

    #[test]
    fn test_sendrecv_zsock() {
        zsys_init();

        let server = ZSock::new_rep("inproc://zframe_sendrecv_zsock").unwrap();
        let client = ZSock::new_req("inproc://zframe_sendrecv_zsock").unwrap();

        let mut zframe1 = ZFrame::from("Hello world!").unwrap();
        zframe1.send_reuse(&client, Some(ZFRAME_MORE)).unwrap();
        zframe1.send(&client, None).unwrap();

        for _ in 1..2 {
            let zframe = ZFrame::recv(&server).unwrap();
            assert_eq!(zframe.data().unwrap().unwrap(), "Hello world!");
        }
    }

    #[test]
    fn test_dup() {
        let zframe = ZFrame::from("moo cow").unwrap();
        let zframe_dup = zframe.dup().unwrap();
        assert_eq!(zframe_dup.data().unwrap().unwrap(), "moo cow");
    }

    #[test]
    fn test_strhex() {
        let zframe = ZFrame::from("Oh Tobias, you blowhard!").unwrap();
        assert_eq!(zframe.strhex().unwrap().unwrap(), "4F6820546F626961732C20796F7520626C6F776861726421");
    }

    #[test]
    fn test_strdup() {
        let zframe = ZFrame::from("Because that's how you get ants, Lana!").unwrap();
        assert_eq!(zframe.strdup().unwrap().unwrap(), "Because that's how you get ants, Lana!");
    }

    #[test]
    fn test_streq() {
        let zframe = ZFrame::from("And that's why you always leave a note.").unwrap();
        assert!(zframe.streq("And that's why you always leave a note."));
    }

    #[test]
    fn test_more() {
        let zframe = ZFrame::empty().unwrap();
        zframe.set_more(true);
        assert!(zframe.more());
        zframe.set_more(false);
        assert!(!zframe.more());
    }

    #[test]
    fn test_eq() {
        let zframe1 = ZFrame::from("Steve Holt!").unwrap();
        let zframe2 = ZFrame::from("Steve Holt!").unwrap();
        assert!(zframe1.eq(&zframe2));
    }

    #[test]
    fn test_reset() {
        let zframe = ZFrame::from("Phrasing!").unwrap();
        zframe.reset("Holy shitsnacks!".as_bytes());
        assert_eq!(zframe.data().unwrap().unwrap(), "Holy shitsnacks!");
    }

    // XXX We need to capture output here before we can test.
    // #[test]
    // fn test_print() {
    //     let zframe = ZFrame::from("You're not my supervisor!").unwrap();
    //     zframe.print(Some("prefix_"));
    //     zframe.print(None);
    // }
}
<|endoftext|>